001// Generated by delombok at Sat Feb 25 17:58:34 UTC 2023 002package io.cui.tools.collect; 003 004import static io.cui.tools.collect.CollectionLiterals.mutableList; 005import static java.util.Objects.requireNonNull; 006import java.lang.reflect.Array; 007import java.util.ArrayList; 008import java.util.Collection; 009import java.util.Collections; 010import java.util.Comparator; 011import java.util.HashSet; 012import java.util.Iterator; 013import java.util.List; 014import java.util.NavigableSet; 015import java.util.Optional; 016import java.util.Set; 017import java.util.TreeSet; 018import java.util.concurrent.ConcurrentSkipListSet; 019import java.util.concurrent.CopyOnWriteArrayList; 020import java.util.concurrent.CopyOnWriteArraySet; 021import java.util.stream.Stream; 022 023/** 024 * <h2>Overview</h2> 025 * Builder for creating {@link java.util.Collection}s providing some convenience methods. The class 026 * writes 027 * everything through into the contained collector. Using the default constructor a newly created 028 * {@link java.util.ArrayList} will be used as collector, but you can pass you own collector as 029 * constructor-argument. Of course this should be mutable in order to work. 030 * <h3>Handling of null-values</h3> 031 * <p> 032 * As default {@code null} values are ignored. This behavior can be changed by call 033 * {@link #addNullValues(boolean)}. 034 * <em>Caution:</em> In case of using one of the {@link #copyFrom(Collection)} 035 * methods for instantiation the {@code null} values will not be checked in that way 036 * </p> 037 * <h3>Standard Usage</h3> 038 * 039 * <pre> 040 * 041 * List<String> result = new CollectionBuilder<String>().add("this").add("that") 042 * .add(mutableList("on", "or an other")).toImmutableList(); 043 * </pre> 044 * 045 * or 046 * 047 * <pre> 048 * 049 * Set<String> result = new CollectionBuilder<String>().add("this").add("that") 050 * .add(mutableList("on", "or an other")).toMutableSet(); 051 * </pre> 052 * 053 * <h3>Copy From</h3> 054 * This methods can be used for ensuring a real copy 055 * 056 * <pre> 057 * 058 * List<String> result = 059 * CollectionBuilder.copyFrom(mutableList("on", "or an other")).add("element").toMutableList(); 060 * 061 * </pre> 062 * 063 * <h3>Sorting</h3> 064 * <p> 065 * The contained {@link java.util.Collection} can be sorted any time by calling 066 * {@link #sort(Comparator)} 067 * </p> 068 * 069 * @author Oliver Wolff 070 * @param <E> The type of the contained {@link java.util.Collection} 071 */ 072public final class CollectionBuilder<E> implements Iterable<E> { 073 private final Collection<E> collector; 074 /** 075 * If set to {@code true} {@code null} elements are added to the contained collector, if 076 * {@code false}, default value, {@code null} values are ignored. 077 */ 078 private boolean addNullValues = false; 079 080 /** 081 * <p> 082 * Constructor for CollectionBuilder. 083 * </p> 084 * 085 * @param collector to be used for storage. Must not be null 086 */ 087 public CollectionBuilder(Collection<E> collector) { 088 super(); 089 this.collector = requireNonNull(collector); 090 } 091 092 /** 093 * Default Constructor initializing the collector with an {@link java.util.ArrayList} 094 */ 095 public CollectionBuilder() { 096 this(new ArrayList<>()); 097 } 098 099 /** 100 * <p> 101 * addNullValues. 102 * </p> 103 * 104 * @param addNullValues If set to {@code true} {@code null} elements are added to the contained 105 * collector, if {@code false}, default value, {@code null} values are ignored. 106 * @return the instance itself in order to use it in a fluent way. 107 */ 108 public CollectionBuilder<E> addNullValues(boolean addNullValues) { 109 this.addNullValues = addNullValues; 110 return this; 111 } 112 113 /** 114 * <p> 115 * size. 116 * </p> 117 * 118 * @return the size of the contained Collection 119 */ 120 public int size() { 121 return collector.size(); 122 } 123 124 /** 125 * <p> 126 * isEmpty. 127 * </p> 128 * 129 * @return see {@link java.util.Collection#isEmpty()} 130 */ 131 public boolean isEmpty() { 132 return collector.isEmpty(); 133 } 134 135 /** 136 * <p> 137 * contains. 138 * </p> 139 * 140 * @param o a {@link java.lang.Object} object 141 * @return see {@link java.util.Collection#isEmpty()} 142 */ 143 public boolean contains(Object o) { 144 return collector.contains(o); 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public Iterator<E> iterator() { 152 return collector.iterator(); 153 } 154 155 /** 156 * <p> 157 * stream. 158 * </p> 159 * 160 * @return a {@link java.util.stream.Stream} on the contained objects 161 */ 162 public Stream<E> stream() { 163 return collector.stream(); 164 } 165 166 /** 167 * <p> 168 * add. 169 * </p> 170 * 171 * @param e the element to be added 172 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 173 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 174 */ 175 public CollectionBuilder<E> add(E e) { 176 if (addNullValues || null != e) { 177 collector.add(e); 178 } 179 return this; 180 } 181 182 /** 183 * <p> 184 * add. 185 * </p> 186 * 187 * @param elements to be added 188 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 189 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 190 */ 191 public CollectionBuilder<E> add(@SuppressWarnings("unchecked") E... elements) { 192 if (!MoreCollections.isEmpty(elements)) { 193 for (E element : elements) { 194 add(element); 195 } 196 } 197 return this; 198 } 199 200 /** 201 * <p> 202 * add. 203 * </p> 204 * 205 * @param elements to be added 206 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 207 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 208 */ 209 public CollectionBuilder<E> add(Iterable<E> elements) { 210 if (!MoreCollections.isEmpty(elements)) { 211 elements.forEach(this::add); 212 } 213 return this; 214 } 215 216 /** 217 * <p> 218 * add. 219 * </p> 220 * 221 * @param elements to be added 222 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 223 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 224 */ 225 public CollectionBuilder<E> add(Collection<E> elements) { 226 if (!MoreCollections.isEmpty(elements)) { 227 elements.forEach(this::add); 228 } 229 return this; 230 } 231 232 /** 233 * <p> 234 * add. 235 * </p> 236 * 237 * @param element to be added if present. 238 * <em>Caution</em>: passing an {@link java.util.Optional} 239 * parameter is a not a good thing to do, I know, but in this context it is quite 240 * convenient: Don't do this at home 241 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 242 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 243 */ 244 public CollectionBuilder<E> add(Optional<E> element) { 245 element.ifPresent(this::add); 246 return this; 247 } 248 249 /** 250 * <p> 251 * add. 252 * </p> 253 * 254 * @param elements to be added 255 * @return the instance itself in order to use it in a fluent way. <em>Caution:</em> with this 256 * call the return value of {@link java.util.Collection#add(Object)} will be ignored. 257 */ 258 public CollectionBuilder<E> add(Stream<E> elements) { 259 if (!MoreCollections.isEmpty(elements)) { 260 elements.forEach(this::add); 261 } 262 return this; 263 } 264 265 /** 266 * Sorts the contained Collection. 267 * 268 * @param comparator must not be null. 269 * @return the instance itself in order to use it in a fluent way. 270 */ 271 public CollectionBuilder<E> sort(Comparator<? super E> comparator) { 272 if (collector instanceof List) { 273 Collections.sort((List<E>) collector, comparator); 274 } else { 275 List<E> sorter = new ArrayList<>(collector); 276 Collections.sort(sorter, comparator); 277 collector.clear(); 278 collector.addAll(sorter); 279 } 280 return this; 281 } 282 283 /** 284 * <p> 285 * toMutableList. 286 * </p> 287 * 288 * @return a mutable {@link java.util.List} representation of the builders content, the actual 289 * implementation is an {@link java.util.ArrayList} 290 */ 291 public List<E> toMutableList() { 292 return new ArrayList<>(collector); 293 } 294 295 /** 296 * <p> 297 * toImmutableList. 298 * </p> 299 * 300 * @return an immutable {@link java.util.List} representation of the builders content, the 301 * actual 302 * implementation calls {@link java.util.Collections#unmodifiableList(List)}. The 303 * underlying 304 * {@link java.util.Collection} will be copied by calling {@link #toMutableList()} 305 */ 306 public List<E> toImmutableList() { 307 return Collections.unmodifiableList(toMutableList()); 308 } 309 310 /** 311 * <p> 312 * toMutableSet. 313 * </p> 314 * 315 * @return a mutable {@link java.util.Set} representation of the builders content, the actual 316 * implementation is an {@link java.util.HashSet} 317 */ 318 public Set<E> toMutableSet() { 319 return new HashSet<>(collector); 320 } 321 322 /** 323 * <p> 324 * toImmutableSet. 325 * </p> 326 * 327 * @return an immutable {@link java.util.Set} representation of the builders content, the actual 328 * implementation calls {@link java.util.Collections#unmodifiableList(List)}. The 329 * underlying 330 * {@link java.util.Collection} will be copied by calling {@link #toMutableSet()} 331 */ 332 public Set<E> toImmutableSet() { 333 return Collections.unmodifiableSet(toMutableSet()); 334 } 335 336 /** 337 * <p> 338 * toConcurrentList. 339 * </p> 340 * 341 * @return a concurrent mutable {@link java.util.List} representation of the builders content, 342 * the actual 343 * implementation is an {@link java.util.concurrent.CopyOnWriteArrayList} 344 */ 345 public List<E> toConcurrentList() { 346 return new CopyOnWriteArrayList<>(collector); 347 } 348 349 /** 350 * <p> 351 * toConcurrentSet. 352 * </p> 353 * 354 * @return a concurrent mutable {@link java.util.Set} representation of the builders content, 355 * the actual 356 * implementation is an {@link java.util.concurrent.CopyOnWriteArraySet} 357 */ 358 public Set<E> toConcurrentSet() { 359 return new CopyOnWriteArraySet<>(collector); 360 } 361 362 /** 363 * <p> 364 * toMutableNavigableSet. 365 * </p> 366 * 367 * @return a mutable {@link java.util.NavigableSet} representation of the builders content, the 368 * actual 369 * implementation is an {@link java.util.TreeSet}. The assumption is that the Actual 370 * type is at 371 * least {@link java.lang.Comparable} 372 */ 373 public NavigableSet<E> toMutableNavigableSet() { 374 return new TreeSet<>(collector); 375 } 376 377 /** 378 * <p> 379 * toImmutableNavigableSet. 380 * </p> 381 * 382 * @return an immutable {@link java.util.NavigableSet} representation of the builders content, 383 * the actual 384 * implementation is an {@link java.util.TreeSet} wrapped by 385 * {@link java.util.Collections#unmodifiableNavigableSet(NavigableSet)}. The assumption 386 * is that 387 * the Actual type is at least {@link java.lang.Comparable} 388 */ 389 public NavigableSet<E> toImmutableNavigableSet() { 390 return Collections.unmodifiableNavigableSet(toMutableNavigableSet()); 391 } 392 393 /** 394 * <p> 395 * toConcurrentNavigableSet. 396 * </p> 397 * 398 * @return a mutable {@link java.util.NavigableSet} representation of the builders content, the 399 * actual 400 * implementation is an {@link java.util.concurrent.ConcurrentSkipListSet}. The 401 * assumption is that the 402 * actual type is at least {@link java.lang.Comparable} 403 */ 404 public NavigableSet<E> toConcurrentNavigableSet() { 405 return new ConcurrentSkipListSet<>(collector); 406 } 407 408 /** 409 * <p> 410 * toArray. 411 * </p> 412 * 413 * @param targetType identifying the concrete ArrayType 414 * @return an array representation of the builders content 415 */ 416 @SuppressWarnings("unchecked") 417 public E[] toArray(Class<? super E> targetType) { 418 if (isEmpty()) { 419 return (E[]) Array.newInstance(targetType, 0); 420 } 421 var target = (E[]) Array.newInstance(targetType, size()); 422 return collector.toArray(target); 423 } 424 425 /** 426 * Clears the elements in the collector 427 * 428 * @return the instance itself in order to use it in a fluent way. 429 */ 430 public CollectionBuilder<E> clear() { 431 collector.clear(); 432 return this; 433 } 434 435 /** 436 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 437 * of the given source 438 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 439 * defined within {@link #addNullValues(boolean)} 440 * 441 * @param source may be null 442 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 443 * @param <E> a E class 444 */ 445 public static <E> CollectionBuilder<E> copyFrom(Iterable<? extends E> source) { 446 return new CollectionBuilder<>(mutableList(source)); 447 } 448 449 /** 450 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 451 * of the given source 452 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 453 * defined within {@link #addNullValues(boolean)} 454 * 455 * @param source may be null 456 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 457 * @param <E> a E class 458 */ 459 public static <E> CollectionBuilder<E> copyFrom(Iterator<? extends E> source) { 460 return new CollectionBuilder<>(mutableList(source)); 461 } 462 463 /** 464 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 465 * of the given source 466 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 467 * defined within {@link #addNullValues(boolean)} 468 * 469 * @param source may be null 470 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 471 * @param <E> a E class 472 */ 473 public static <E> CollectionBuilder<E> copyFrom(Collection<? extends E> source) { 474 return new CollectionBuilder<>(mutableList(source)); 475 } 476 477 /** 478 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 479 * of the given source 480 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 481 * defined within {@link #addNullValues(boolean)} 482 * 483 * @param source may be null 484 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 485 * @param <E> a E class 486 */ 487 public static <E> CollectionBuilder<E> copyFrom(Stream<? extends E> source) { 488 return new CollectionBuilder<>(mutableList(source)); 489 } 490 491 /** 492 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 493 * of the given source 494 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 495 * defined within {@link #addNullValues(boolean)} 496 * 497 * @param source may be null 498 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 499 * @param <E> a E class 500 */ 501 @SafeVarargs 502 public static <E> CollectionBuilder<E> copyFrom(E... source) { 503 return new CollectionBuilder<>(mutableList(source)); 504 } 505 506 /** 507 * Creates an Instance of {@link io.cui.tools.collect.CollectionBuilder} by copying the content 508 * of the given source 509 * <em>Caution:</em> The given source will be used as it is, there will be no filtering as 510 * defined within {@link #addNullValues(boolean)} 511 * 512 * @param source may be null 513 * @return the newly created {@link io.cui.tools.collect.CollectionBuilder} 514 * @param <E> a E class 515 */ 516 public static <E> CollectionBuilder<E> copyFrom(E source) { 517 return new CollectionBuilder<>(mutableList(source)); 518 } 519 520 @java.lang.Override 521 @java.lang.SuppressWarnings("all") 522 @lombok.Generated 523 public boolean equals(final java.lang.Object o) { 524 if (o == this) return true; 525 if (!(o instanceof CollectionBuilder)) return false; 526 final CollectionBuilder<?> other = (CollectionBuilder<?>) o; 527 if (this.isAddNullValues() != other.isAddNullValues()) return false; 528 final java.lang.Object this$collector = this.collector; 529 final java.lang.Object other$collector = other.collector; 530 if (this$collector == null ? other$collector != null : !this$collector.equals(other$collector)) return false; 531 return true; 532 } 533 534 @java.lang.Override 535 @java.lang.SuppressWarnings("all") 536 @lombok.Generated 537 public int hashCode() { 538 final int PRIME = 59; 539 int result = 1; 540 result = result * PRIME + (this.isAddNullValues() ? 79 : 97); 541 final java.lang.Object $collector = this.collector; 542 result = result * PRIME + ($collector == null ? 43 : $collector.hashCode()); 543 return result; 544 } 545 546 @java.lang.Override 547 @java.lang.SuppressWarnings("all") 548 @lombok.Generated 549 public java.lang.String toString() { 550 return "CollectionBuilder(collector=" + this.collector + ", addNullValues=" + this.isAddNullValues() + ")"; 551 } 552 553 /** 554 * If set to {@code true} {@code null} elements are added to the contained collector, if 555 * {@code false}, default value, {@code null} values are ignored. 556 */ 557 @java.lang.SuppressWarnings("all") 558 @lombok.Generated 559 public boolean isAddNullValues() { 560 return this.addNullValues; 561 } 562}