001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.util; 028 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.Collection; 032import java.util.Collections; 033import java.util.Iterator; 034import java.util.LinkedList; 035import java.util.List; 036import java.util.Map; 037import java.util.Set; 038import java.util.Spliterator; 039import java.util.Spliterators; 040import java.util.stream.Collectors; 041import java.util.stream.IntStream; 042import java.util.stream.Stream; 043import java.util.stream.StreamSupport; 044 045import edu.umd.cs.findbugs.annotations.NonNull; 046import edu.umd.cs.findbugs.annotations.Nullable; 047 048public final class CollectionUtil { 049 050 private CollectionUtil() { 051 // disable construction 052 } 053 054 /** 055 * Get a {@link Stream} for the provided {@link Iterable}. 056 * 057 * @param <T> 058 * the type to iterate on 059 * @param iterator 060 * the iterator 061 * @return the stream 062 */ 063 public static <T> Stream<T> toStream(@NonNull Iterator<T> iterator) { 064 Iterable<T> iterable = toIterable(iterator); 065 return StreamSupport.stream(iterable.spliterator(), false); 066 } 067 068 /** 069 * Get an {@link Iterable} for the provided {@link Stream}. 070 * 071 * @param <T> 072 * the type to iterate on 073 * @param stream 074 * the stream to iterate over 075 * @return the resulting iterable instance 076 */ 077 @NonNull 078 public static <T> Iterable<T> toIterable(@NonNull Stream<T> stream) { 079 return toIterable(ObjectUtils.notNull(stream.iterator())); 080 } 081 082 /** 083 * Get an {@link Iterable} for the provided {@link Iterator}. 084 * 085 * @param <T> 086 * the type to iterate on 087 * @param iterator 088 * the iterator 089 * @return the resulting iterable instance 090 */ 091 @NonNull 092 public static <T> Iterable<T> toIterable(@NonNull Iterator<T> iterator) { 093 return () -> iterator; 094 } 095 096 /** 097 * Get a reverse {@link Iterable} for the provided {@link List}. 098 * 099 * @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}