View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.metaschema.core.util;
28  
29  import java.util.ArrayList;
30  import java.util.Arrays;
31  import java.util.Collection;
32  import java.util.Collections;
33  import java.util.Iterator;
34  import java.util.LinkedList;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  import java.util.Spliterator;
39  import java.util.Spliterators;
40  import java.util.stream.Collectors;
41  import java.util.stream.IntStream;
42  import java.util.stream.Stream;
43  import java.util.stream.StreamSupport;
44  
45  import edu.umd.cs.findbugs.annotations.NonNull;
46  import edu.umd.cs.findbugs.annotations.Nullable;
47  
48  public final class CollectionUtil {
49  
50    private CollectionUtil() {
51      // disable construction
52    }
53  
54    /**
55     * Get a {@link Stream} for the provided {@link Iterable}.
56     *
57     * @param <T>
58     *          the type to iterate on
59     * @param iterator
60     *          the iterator
61     * @return the stream
62     */
63    public static <T> Stream<T> toStream(@NonNull Iterator<T> iterator) {
64      Iterable<T> iterable = toIterable(iterator);
65      return StreamSupport.stream(iterable.spliterator(), false);
66    }
67  
68    /**
69     * Get an {@link Iterable} for the provided {@link Stream}.
70     *
71     * @param <T>
72     *          the type to iterate on
73     * @param stream
74     *          the stream to iterate over
75     * @return the resulting iterable instance
76     */
77    @NonNull
78    public static <T> Iterable<T> toIterable(@NonNull Stream<T> stream) {
79      return toIterable(ObjectUtils.notNull(stream.iterator()));
80    }
81  
82    /**
83     * Get an {@link Iterable} for the provided {@link Iterator}.
84     *
85     * @param <T>
86     *          the type to iterate on
87     * @param iterator
88     *          the iterator
89     * @return the resulting iterable instance
90     */
91    @NonNull
92    public static <T> Iterable<T> toIterable(@NonNull Iterator<T> iterator) {
93      return () -> iterator;
94    }
95  
96    /**
97     * Get a reverse {@link Iterable} for the provided {@link List}.
98     *
99     * @param <T>
100    *          the type to iterate on
101    * @param list
102    *          the list of items to iterate over
103    * @return the resulting iterable instance
104    */
105   @NonNull
106   public static <T> Iterable<T> toDescendingIterable(@NonNull List<T> list) {
107     return toIterable(descendingIterator(list));
108   }
109 
110   /**
111    * Convert the provided {@link Iterable} to a list of the same generic type.
112    *
113    * @param <T>
114    *          the collection item's generic type
115    * @param iterable
116    *          the Iterable to convert to a list
117    * @return the list
118    */
119   @NonNull
120   public static <T> List<T> toList(Iterable<T> iterable) {
121     return ObjectUtils.notNull(StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()));
122   }
123 
124   /**
125    * Convert the provided {@link Iterator} to a list of the same generic type.
126    *
127    * @param <T>
128    *          the collection item's generic type
129    * @param iterator
130    *          the Iterator to convert to a list
131    * @return the list
132    */
133   @NonNull
134   public static <T> List<T> toList(Iterator<T> iterator) {
135     return ObjectUtils.notNull(
136         StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
137             .collect(Collectors.toList()));
138   }
139 
140   /**
141    * Get a reverse {@link Iterator} for the provided {@link List}.
142    *
143    * @param <T>
144    *          the type to iterate on
145    * @param list
146    *          the list of items to iterate over
147    * @return the resulting Iterator instance
148    */
149   @NonNull
150   public static <T> Iterator<T> descendingIterator(@NonNull List<T> list) {
151     Iterator<T> retval;
152     if (list instanceof LinkedList) {
153       retval = ((LinkedList<T>) list).descendingIterator();
154     } else if (list instanceof ArrayList) {
155       retval = IntStream.range(0, list.size())
156           .map(i -> list.size() - 1 - i)
157           .mapToObj(list::get).iterator();
158     } else {
159       throw new UnsupportedOperationException();
160     }
161     return ObjectUtils.notNull(retval);
162   }
163 
164   @NonNull
165   public static <T extends Collection<A>, A> T requireNonEmpty(@NonNull T collection) {
166     if (collection.isEmpty()) {
167       throw new IllegalStateException();
168     }
169     return collection;
170   }
171 
172   @NonNull
173   public static <T extends Collection<A>, A> T requireNonEmpty(@NonNull T collection, @NonNull String message) {
174     if (collection.isEmpty()) {
175       throw new IllegalStateException(message);
176     }
177     return collection;
178   }
179 
180   /**
181    * A wrapper of the {@link Collections#unmodifiableCollection(Collection)}
182    * method that ensure a {@link NonNull} result is returned.
183    *
184    * @param <T>
185    *          the collection's item type
186    * @param collection
187    *          the collection
188    * @return a non-null unmodifiable instance of the provided collection
189    */
190   @SuppressWarnings("null")
191   @NonNull
192   public static <T> Collection<T> unmodifiableCollection(@NonNull Collection<T> collection) {
193     return Collections.unmodifiableCollection(collection);
194   }
195 
196   @SuppressWarnings("null")
197   @NonNull
198   public static <T> Set<T> singleton(@NonNull T value) {
199     return Collections.singleton(value);
200   }
201 
202   @SuppressWarnings("null")
203   @NonNull
204   public static <T> Set<T> emptySet() {
205     return Collections.emptySet();
206   }
207 
208   @SuppressWarnings("null")
209   @NonNull
210   public static <T> Set<T> unmodifiableSet(@NonNull Set<T> set) {
211     return Collections.unmodifiableSet(set);
212   }
213 
214   @NonNull
215   public static <T> List<T> listOrEmpty(@Nullable List<T> list) {
216     return list == null ? emptyList() : list;
217   }
218 
219   @SafeVarargs
220   @SuppressWarnings("null")
221   @NonNull
222   public static <T> List<T> listOrEmpty(@Nullable T... array) {
223     return array == null || array.length == 0 ? emptyList() : Arrays.asList(array);
224   }
225 
226   @SuppressWarnings("null")
227   @NonNull
228   public static <T> List<T> emptyList() {
229     return Collections.emptyList();
230   }
231 
232   @SuppressWarnings("null")
233   @NonNull
234   public static <T> List<T> unmodifiableList(@NonNull List<T> list) {
235     return Collections.unmodifiableList(list);
236   }
237 
238   @SuppressWarnings("null")
239   @NonNull
240   public static <T> List<T> singletonList(@NonNull T instance) {
241     return Collections.singletonList(instance);
242   }
243 
244   @SuppressWarnings("null")
245   @NonNull
246   public static <K, V> Map<K, V> emptyMap() {
247     return Collections.emptyMap();
248   }
249 
250   @SuppressWarnings("null")
251   @NonNull
252   public static <K, V> Map<K, V> singletonMap(@NonNull K key, @NonNull V value) {
253     return Collections.singletonMap(key, value);
254   }
255 
256   @SuppressWarnings("null")
257   @NonNull
258   public static <K, V> Map<K, V> unmodifiableMap(@NonNull Map<K, V> map) {
259     return Collections.unmodifiableMap(map);
260   }
261 }