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