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&lt;String&gt; result = new CollectionBuilder&lt;String&gt;().add("this").add("that")
042 *         .add(mutableList("on", "or an other")).toImmutableList();
043 * </pre>
044 *
045 * or
046 *
047 * <pre>
048 *
049 * Set&lt;String&gt; result = new CollectionBuilder&lt;String&gt;().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&lt;String&gt; 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}