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