001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.internal;
014
015import java.lang.reflect.*;
016import java.util.*;
017import java.util.function.*;
018
019/**
020 * Utility methods for collections.
021 *
022 * <h5 class='section'>See Also:</h5><ul>
023
024 * </ul>
025 */
026public final class CollectionUtils {
027
028   /**
029    * Creates a new set from the specified collection.
030    *
031    * @param <E> The element type.
032    * @param val The value to copy from.
033    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
034    */
035   public static <E> Set<E> setFrom(Collection<E> val) {
036      return val == null ? null : new LinkedHashSet<>(val);
037   }
038
039   /**
040    * Creates a new set from the specified collection.
041    *
042    * @param <E> The element type.
043    * @param val The value to copy from.
044    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
045    */
046   public static <E> Set<E> copyOf(Set<E> val) {
047      return val == null ? null : new LinkedHashSet<>(val);
048   }
049
050   /**
051    * Creates a new collection from the specified collection.
052    *
053    * @param <E> The element type.
054    * @param val The value to copy from.
055    * @return A new {@link LinkedHashSet}, or <jk>null</jk> if the input was null.
056    */
057   public static <E> Collection<E> copyOf(Collection<E> val) {
058      return val == null ? null : new LinkedHashSet<>(val);
059   }
060
061   /**
062    * Creates a new map from the specified map.
063    *
064    * @param <K> The key type.
065    * @param <V> The value type.
066    * @param val The value to copy from.
067    * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input was null.
068    */
069   public static <K,V> Map<K,V> copyOf(Map<K,V> val) {
070      return val == null ? null : new LinkedHashMap<>(val);
071   }
072
073   /**
074    * Instantiates a new builder on top of the specified map.
075    *
076    * @param <K> The key type.
077    * @param <V> The value type.
078    * @param addTo The map to add to.
079    * @return A new builder on top of the specified map.
080    */
081   public static <K,V> MapBuilder<K,V> mapBuilder(Map<K,V> addTo) {
082      return new MapBuilder<>(addTo);
083   }
084
085   /**
086    * Instantiates a new builder of the specified map type.
087    *
088    * @param <K> The key type.
089    * @param <V> The value type.
090    * @param keyType The key type.
091    * @param valueType The value type.
092    * @param valueTypeArgs The value type args.
093    * @return A new builder on top of the specified map.
094    */
095   public static <K,V> MapBuilder<K,V> mapBuilder(Class<K> keyType, Class<V> valueType, Type...valueTypeArgs) {
096      return new MapBuilder<>(keyType, valueType, valueTypeArgs);
097   }
098
099   /**
100    * Instantiates a new builder on top of the specified list.
101    *
102    * @param <E> The element type.
103    * @param addTo The list to add to.
104    * @return A new builder on top of the specified list.
105    */
106   public static <E> ListBuilder<E> listBuilder(List<E> addTo) {
107      return new ListBuilder<>(addTo);
108   }
109
110   /**
111    * Instantiates a new builder of the specified list type.
112    *
113    * @param <E> The element type.
114    * @param elementType The element type.
115    * @param elementTypeArgs The element type args.
116    * @return A new builder on top of the specified list.
117    */
118   public static <E> ListBuilder<E> listBuilder(Class<E> elementType, Type...elementTypeArgs) {
119      return new ListBuilder<>(elementType, elementTypeArgs);
120   }
121
122   /**
123    * Instantiates a new builder on top of the specified set.
124    *
125    * @param <E> The element type.
126    * @param addTo The set to add to.
127    * @return A new builder on top of the specified set.
128    */
129   public static <E> SetBuilder<E> setBuilder(Set<E> addTo) {
130      return new SetBuilder<>(addTo);
131   }
132
133   /**
134    * Instantiates a new builder of the specified set.
135    *
136    * @param <E> The element type.
137    * @param elementType The element type.
138    * @param elementTypeArgs The element type args.
139    * @return A new builder on top of the specified set.
140    */
141   public static <E> SetBuilder<E> setBuilder(Class<E> elementType, Type...elementTypeArgs) {
142      return new SetBuilder<>(elementType, elementTypeArgs);
143   }
144
145   /**
146    * Simple passthrough to {@link Collections#emptyList()}
147    *
148    * @param <E> The element type.
149    * @return A new unmodifiable empty list.
150    */
151   public static <E> List<E> emptyList() {
152      return Collections.emptyList();
153   }
154
155   /**
156    * Convenience method for creating an {@link ArrayList}.
157    *
158    * @param <E> The element type.
159    * @param values The values to initialize the list with.
160    * @return A new modifiable list.
161    */
162   @SafeVarargs
163   public static <E> ArrayList<E> list(E...values) {
164      ArrayList<E> l = new ArrayList<>(values.length);
165      for (E v : values)
166         l.add(v);
167      return l;
168   }
169
170   /**
171    * Convenience method for creating an {@link ArrayList} of the specified size.
172    *
173    * @param <E> The element type.
174    * @param size The initial size of the list.
175    * @return A new modifiable list.
176    */
177   public static <E> ArrayList<E> list(int size) {
178      return new ArrayList<>(size);
179   }
180
181   /**
182    * Convenience method for creating a {@link LinkedList}.
183    *
184    * @param <E> The element type.
185    * @param values The values to initialize the list with.
186    * @return A new modifiable list.
187    */
188   @SafeVarargs
189   public static <E> LinkedList<E> linkedList(E...values) {
190      LinkedList<E> l = new LinkedList<>();
191      for (E v : values)
192         l.add(v);
193      return l;
194   }
195
196   /**
197    * Convenience method for creating an array-backed list by calling {@link Arrays#asList(Object...)}.
198    *
199    * @param <E> The element type.
200    * @param values The values to initialize the list with.
201    * @return A new modifiable list, or <jk>null</jk> if the array was <jk>null</jk>.
202    */
203   @SafeVarargs
204   public static <E> List<E> alist(E...values) {
205      if (values == null)
206         return null;
207      return Arrays.asList(values);
208   }
209
210   /**
211    * Creates an {@link ArrayList} copy from a collection.
212    *
213    * @param <E> The element type.
214    * @param value The collection to copy from.
215    * @return A new modifiable list.
216    */
217   public static <E> ArrayList<E> listFrom(Collection<E> value) {
218      return listFrom(value, false);
219   }
220
221   /**
222    * Creates an {@link ArrayList} copy from a collection.
223    *
224    * @param <K> The key type.
225    * @param <V> The value type.
226    * @param value The collection to copy from.
227    * @return A new modifiable list.
228    */
229   public static <K,V> LinkedHashMap<K,V> mapFrom(Map<K,V> value) {
230      if (value == null)
231         return null;
232      return new LinkedHashMap<>(value);
233   }
234
235   /**
236    * Creates an {@link ArrayList} copy from a collection.
237    *
238    * @param <E> The element type.
239    * @param value The collection to copy from.
240    * @param nullIfEmpty If <jk>true</jk> will return <jk>null</jk> if the collection is empty.
241    * @return A new modifiable list.
242    */
243   public static <E> ArrayList<E> listFrom(Collection<E> value, boolean nullIfEmpty) {
244      if (value == null || (nullIfEmpty && value.isEmpty()))
245         return null;
246      ArrayList<E> l = new ArrayList<>();
247      value.forEach(x -> l.add(x));
248      return l;
249   }
250
251   /**
252    * Convenience method for creating a {@link LinkedHashSet}.
253    *
254    * @param <E> The element type.
255    * @param values The values to initialize the set with.
256    * @return A new modifiable set.
257    */
258   @SafeVarargs
259   public static <E> LinkedHashSet<E> set(E...values) {
260      LinkedHashSet<E> l = new LinkedHashSet<>();
261      for (E v : values)
262         l.add(v);
263      return l;
264   }
265
266   /**
267    * Convenience method for creating an unmodifiable {@link LinkedHashSet}.
268    *
269    * @param <E> The element type.
270    * @param values The values to initialize the set with.
271    * @return A new unmodifiable set.
272    */
273   @SafeVarargs
274   public static <E> Set<E> uset(E...values) {
275      return unmodifiable(set(values));
276   }
277
278   /**
279    * Convenience method for creating an unmodifiable list.
280    *
281    * @param <E> The element type.
282    * @param values The values to initialize the list with.
283    * @return A new unmodifiable list, or <jk>null</jk> if the array was <jk>null</jk>.
284    */
285   @SafeVarargs
286   public static <E> List<E> ulist(E...values) {
287      if (values == null)
288         return null;
289      return unmodifiable(alist(values));
290   }
291
292   /**
293    * Convenience method for creating a {@link TreeSet}.
294    *
295    * @param <E> The element type.
296    * @param values The values to initialize the set with.
297    * @return A new modifiable set.
298    */
299   @SafeVarargs
300   public static <E> TreeSet<E> sortedSet(E...values) {
301      TreeSet<E> l = new TreeSet<>();
302      for (E v : values)
303         l.add(v);
304      return l;
305   }
306
307   /**
308    * Creates a new {@link TreeSet} from the specified collection.
309    *
310    * @param <E> The element type.
311    * @param value The value to copy from.
312    * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null.
313    */
314   public static <E> TreeSet<E> sortedSetFrom(Collection<E> value) {
315      if (value == null)
316         return null;
317      TreeSet<E> l = new TreeSet<>();
318      value.forEach(x -> l.add(x));
319      return l;
320   }
321
322   /**
323    * Creates a new {@link TreeSet} from the specified collection.
324    *
325    * @param <E> The element type.
326    * @param value The value to copy from.
327    * @param nullIfEmpty If <jk>true</jk> returns <jk>null</jk> if the collection is empty.
328    * @return A new {@link TreeSet}, or <jk>null</jk> if the input was null.
329    */
330   public static <E> TreeSet<E> sortedSetFrom(Collection<E> value, boolean nullIfEmpty) {
331      if (value == null || (nullIfEmpty && value.isEmpty()))
332         return null;
333      TreeSet<E> l = new TreeSet<>();
334      value.forEach(x -> l.add(x));
335      return l;
336   }
337
338   /**
339    * Convenience method for creating a {@link LinkedHashMap}.
340    *
341    * @param <K> The key type.
342    * @param <V> The value type.
343    * @return A new modifiable map.
344    */
345   public static <K,V> LinkedHashMap<K,V> map() {
346      LinkedHashMap<K,V> m = new LinkedHashMap<>();
347      return m;
348   }
349
350   /**
351    * Convenience method for creating a {@link LinkedHashMap}.
352    *
353    * @param <K> The key type.
354    * @param <V> The value type.
355    * @param k1 Key 1.
356    * @param v1 Value 1.
357    * @return A new modifiable map.
358    */
359   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1) {
360      LinkedHashMap<K,V> m = new LinkedHashMap<>();
361      m.put(k1, v1);
362      return m;
363   }
364
365   /**
366    * Convenience method for creating a {@link LinkedHashMap}.
367    *
368    * @param <K> The key type.
369    * @param <V> The value type.
370    * @param k1 Key 1.
371    * @param v1 Value 1.
372    * @param k2 Key 2.
373    * @param v2 Value 2.
374    * @return A new modifiable map.
375    */
376   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2) {
377      LinkedHashMap<K,V> m = new LinkedHashMap<>();
378      m.put(k1, v1);
379      m.put(k2, v2);
380      return m;
381   }
382
383   /**
384    * Convenience method for creating a {@link LinkedHashMap}.
385    *
386    * @param <K> The key type.
387    * @param <V> The value type.
388    * @param k1 Key 1.
389    * @param v1 Value 1.
390    * @param k2 Key 2.
391    * @param v2 Value 2.
392    * @param k3 Key 3.
393    * @param v3 Value 3.
394    * @return A new modifiable map.
395    */
396   public static <K,V> LinkedHashMap<K,V> map(K k1, V v1, K k2, V v2, K k3, V v3) {
397      LinkedHashMap<K,V> m = new LinkedHashMap<>();
398      m.put(k1, v1);
399      m.put(k2, v2);
400      m.put(k3, v3);
401      return m;
402   }
403
404   /**
405    * Convenience method for creating a {@link TreeMap}.
406    *
407    * @param <K> The key type.
408    * @param <V> The value type.
409    * @return A new modifiable set.
410    */
411   public static <K,V> TreeMap<K,V> sortedMap() {
412      return new TreeMap<>();
413   }
414
415   /**
416    * Convenience method for copying a list.
417    *
418    * @param <E> The element type.
419    * @param value The list to copy.
420    * @return A new modifiable list.
421    */
422   public static <E> ArrayList<E> copyOf(List<E> value) {
423      return value == null ? null : new ArrayList<>(value);
424   }
425
426   /**
427    * Convenience method for creating an {@link ArrayList} and sorting it.
428    *
429    * @param <E> The element type.
430    * @param values The values to initialize the list with.
431    * @return A new modifiable list.
432    */
433   @SuppressWarnings({ "rawtypes", "unchecked" })
434   @SafeVarargs
435   public static <E> ArrayList<E> sortedList(E...values) {
436      ArrayList<E> l = list(values);
437      Collections.sort((List<Comparable>) l);
438      return l;
439   }
440
441   /**
442    * Convenience method for creating an {@link ArrayList} and sorting it.
443    *
444    * @param <E> The element type.
445    * @param comparator The comparator to use to sort the list.
446    * @param values The values to initialize the list with.
447    * @return A new modifiable list.
448    */
449   public static <E> ArrayList<E> sortedList(Comparator<E> comparator, E[] values) {
450      ArrayList<E> l = list(values);
451      Collections.sort(l, comparator);
452      return l;
453   }
454
455   /**
456    * Convenience method for creating an {@link ArrayList} and sorting it.
457    *
458    * @param <E> The element type.
459    * @param comparator The comparator to use to sort the list.
460    * @param value The values to initialize the list with.
461    * @return A new modifiable list.
462    */
463   public static <E> ArrayList<E> sortedList(Comparator<E> comparator, Collection<E> value) {
464      ArrayList<E> l = listFrom(value);
465      Collections.sort(l, comparator);
466      return l;
467   }
468
469   /**
470    * Wraps the specified list in {@link Collections#unmodifiableList(List)}.
471    *
472    * @param <E> The element type.
473    * @param value The list to wrap.
474    * @return The wrapped list.
475    */
476   public static <E> List<E> unmodifiable(List<E> value) {
477      return value == null ? null: Collections.unmodifiableList(value);
478   }
479
480   /**
481    * Wraps the specified set in {@link Collections#unmodifiableSet(Set)}.
482    *
483    * @param <E> The element type.
484    * @param value The set to wrap.
485    * @return The wrapped set.
486    */
487   public static <E> Set<E> unmodifiable(Set<E> value) {
488      return value == null ? null: Collections.unmodifiableSet(value);
489   }
490
491   /**
492    * Wraps the specified map in {@link Collections#unmodifiableMap(Map)}.
493    *
494    * @param <K> The key type.
495    * @param <V> The value type.
496    * @param value The map to wrap.
497    * @return The wrapped map.
498    */
499   public static <K,V> Map<K,V> unmodifiable(Map<K,V> value) {
500      return value == null ? null: Collections.unmodifiableMap(value);
501   }
502
503   /**
504    * Wraps the specified list in {@link Collections#unmodifiableList(List)}.
505    *
506    * @param <E> The element type.
507    * @param value The list to wrap.
508    * @return The wrapped list.
509    */
510   public static <E> List<E> synced(List<E> value) {
511      return value == null ? null: Collections.synchronizedList(value);
512   }
513
514   /**
515    * Wraps the specified set in {@link Collections#unmodifiableSet(Set)}.
516    *
517    * @param <E> The element type.
518    * @param value The set to wrap.
519    * @return The wrapped set.
520    */
521   public static <E> Set<E> synced(Set<E> value) {
522      return value == null ? null: Collections.synchronizedSet(value);
523   }
524
525   /**
526    * Wraps the specified map in {@link Collections#unmodifiableMap(Map)}.
527    *
528    * @param <K> The key type.
529    * @param <V> The value type.
530    * @param value The map to wrap.
531    * @return The wrapped map.
532    */
533   public static <K,V> Map<K,V> synced(Map<K,V> value) {
534      return value == null ? null: Collections.synchronizedMap(value);
535   }
536
537   /**
538    * Converts the specified collection to an array.
539    *
540    * @param <E> The element type.
541    * @param value The collection to convert.
542    * @param componentType The component type of the array.
543    * @return A new array.
544    */
545   @SuppressWarnings("unchecked")
546   public static <E> E[] array(Collection<E> value, Class<E> componentType) {
547      if (value == null)
548         return null;
549      E[] array = (E[])Array.newInstance(componentType, value.size());
550      return value.toArray(array);
551   }
552
553   /**
554    * Iterates the specified list in reverse order.
555    *
556    * @param <E> The element type.
557    * @param value The list to iterate.
558    * @param action The action to perform.
559    */
560   public static <E> void forEachReverse(List<E> value, Consumer<E> action) {
561      if (value instanceof ArrayList) {
562         for (int i = value.size()-1; i >= 0; i--)
563            action.accept(value.get(i));
564      } else {
565         ListIterator<E> i = value.listIterator(value.size());
566         while (i.hasPrevious())
567            action.accept(i.previous());
568      }
569   }
570
571   /**
572    * Iterates the specified array in reverse order.
573    *
574    * @param <E> The element type.
575    * @param value The array to iterate.
576    * @param action The action to perform.
577    */
578   public static <E> void forEachReverse(E[] value, Consumer<E> action) {
579      for (int i = value.length-1; i >= 0; i--)
580         action.accept(value[i]);
581   }
582
583   /**
584    * Adds all the specified values to the specified collection.
585    * Creates a new set if the value is <jk>null</jk>.
586    *
587    * @param <E> The element type.
588    * @param value The collection to add to.
589    * @param entries The entries to add.
590    * @return The set.
591    */
592   @SafeVarargs
593   public static <E> Set<E> addAll(Set<E> value, E...entries) {
594      if (entries != null) {
595         if (value == null)
596            value = set(entries);
597         else
598            Collections.addAll(value, entries);
599      }
600      return value;
601   }
602
603   /**
604    * Adds all the specified values to the specified collection.
605    * Creates a new set if the value is <jk>null</jk>.
606    *
607    * @param <E> The element type.
608    * @param value The collection to add to.
609    * @param entries The entries to add.
610    * @return The set.
611    */
612   @SafeVarargs
613   public static <E> SortedSet<E> addAll(SortedSet<E> value, E...entries) {
614      if (entries != null) {
615         if (value == null)
616            value = sortedSet(entries);
617         else
618            Collections.addAll(value, entries);
619      }
620      return value;
621   }
622
623   /**
624    * Adds all the specified values to the specified collection.
625    * Creates a new set if the value is <jk>null</jk>.
626    *
627    * @param <E> The element type.
628    * @param value The collection to add to.
629    * @param entries The entries to add.
630    * @return The set.
631    */
632   @SafeVarargs
633   public static <E> List<E> addAll(List<E> value, E...entries) {
634      if (entries != null) {
635         if (value == null)
636            value = list(entries);
637         else
638            Collections.addAll(value, entries);
639      }
640      return value;
641   }
642
643   /**
644    * Adds all the specified values to the specified collection.
645    * Creates a new set if the value is <jk>null</jk>.
646    *
647    * @param <E> The element type.
648    * @param value The collection to add to.
649    * @param entries The entries to add.
650    * @return The set.
651    */
652   @SafeVarargs
653   public static <E> List<E> prependAll(List<E> value, E...entries) {
654      if (entries != null) {
655         if (value == null)
656            value = list(entries);
657         else
658            value.addAll(0, alist(entries));
659      }
660      return value;
661   }
662
663   /**
664    * Returns the last entry in a list.
665    *
666    * @param <E> The element type.
667    * @param l The list.
668    * @return The last element, or <jk>null</jk> if the list is <jk>null</jk> or empty.
669    */
670   public static <E> E last(List<E> l) {
671      if (l == null || l.isEmpty())
672         return null;
673      return l.get(l.size()-1);
674   }
675
676   /**
677    * Returns the last entry in an array.
678    *
679    * @param <E> The element type.
680    * @param l The array.
681    * @return The last element, or <jk>null</jk> if the array is <jk>null</jk> or empty.
682    */
683   public static <E> E last(E[] l) {
684      if (l == null || l.length == 0)
685         return null;
686      return l[l.length-1];
687   }
688
689   /**
690    * Returns an optional of the specified value.
691    *
692    * @param <T> The component type.
693    * @param value The value.
694    * @return A new Optional.
695    */
696   public static <T> Optional<T> optional(T value) {
697      return Optional.ofNullable(value);
698   }
699
700   /**
701    * Returns an empty {@link Optional}.
702    *
703    * @param <T> The component type.
704    * @return An empty {@link Optional}.
705    */
706   public static <T> Optional<T> empty() {
707      return Optional.empty();
708   }
709
710   /**
711    * Returns <jk>true</jk> if the specified collection is not <jk>null</jk> and not empty.
712    *
713    * @param <E> The element type.
714    * @param value The value being checked.
715    * @return <jk>true</jk> if the specified collection is not <jk>null</jk> and not empty.
716    */
717   public static <E> boolean isNotEmpty(Collection<E> value) {
718      return value != null && ! value.isEmpty();
719   }
720
721   /**
722    * Returns <jk>true</jk> if the specified map is not <jk>null</jk> and not empty.
723    *
724    * @param <K> The key type.
725    * @param <V> The value type.
726    * @param value The value being checked.
727    * @return <jk>true</jk> if the specified map is not <jk>null</jk> and not empty.
728    */
729   public static <K,V> boolean isNotEmpty(Map<K,V> value) {
730      return value != null && ! value.isEmpty();
731   }
732}