CollectionUtils.java
001 /*
002  * Copyright 2008-2016 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *     http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 package griffon.util;
017 
018 import javax.annotation.Nonnull;
019 import java.util.ArrayList;
020 import java.util.Arrays;
021 import java.util.Collection;
022 import java.util.Collections;
023 import java.util.Enumeration;
024 import java.util.HashMap;
025 import java.util.HashSet;
026 import java.util.Iterator;
027 import java.util.LinkedHashMap;
028 import java.util.LinkedHashSet;
029 import java.util.List;
030 import java.util.ListIterator;
031 import java.util.Map;
032 import java.util.Properties;
033 import java.util.Set;
034 
035 import static java.util.Objects.requireNonNull;
036 
037 /**
038  <p>Utility class that simplifies creating collections in Java.</p>
039  <p><strong>Creating Maps</strong><br/>
040  <pre>
041  * Map<String, Object> m = map()
042  *     .e("foo", foo)
043  *     .e("bar", bar);
044  </pre></p>
045  *
046  <p><strong>Creating Lists</strong><br/>
047  <pre>
048  * List<String> l = list()
049  *     .e("foo")
050  *     .e("bar");
051  </pre></p>
052  *
053  <p><strong>Creating Maps</strong><br/>
054  <pre>
055  * Set<String> s = set()
056  *     .e("foo")
057  *     .e("bar");
058  </pre></p>
059  *
060  @author Andres Almiray
061  @since 2.0.0
062  */
063 public final class CollectionUtils {
064     public static <T> List<T> reverse(List<T> input) {
065         List<T> output = new ArrayList<>(input);
066         Collections.reverse(output);
067         return output;
068     }
069 
070     public static <T> List<T> reverse(Collection<T> input) {
071         List<T> output = new ArrayList<>(input);
072         Collections.reverse(output);
073         return output;
074     }
075 
076     @SuppressWarnings({"rawtypes""unchecked"})
077     public static <K, V> Map newMap(Object... keysAndValues) {
078         if (keysAndValues == null) {
079             return Collections.emptyMap();
080         }
081         if (keysAndValues.length % == 1) {
082             throw new IllegalArgumentException("Must have an even number of keys and values");
083         }
084 
085         Map<K, V> map = new HashMap<>();
086         for (int i = 0; i < keysAndValues.length; i += 2) {
087             map.put((KkeysAndValues[i](VkeysAndValues[i + 1]);
088         }
089         return map;
090     }
091 
092     @SafeVarargs
093     public static <T> Set<T> newSet(T... values) {
094         if (values == null) {
095             return Collections.emptySet();
096         }
097 
098         return new HashSet<>(Arrays.asList(values));
099     }
100 
101     @SafeVarargs
102     public static <T> List<T> newList(T... values) {
103         if (values == null) {
104             return Collections.emptyList();
105         }
106 
107         return new ArrayList<>(Arrays.asList(values));
108     }
109 
110     public static <K, V> MapBuilder<K, V> map() {
111         return map(new LinkedHashMap<K, V>());
112     }
113 
114     public static <K, V> MapBuilder<K, V> map(Map<K, V> delegate) {
115         return new MapBuilder<>(delegate);
116     }
117 
118     public static <E> ListBuilder<E> list() {
119         return list(new ArrayList<E>());
120     }
121 
122     public static <E> ListBuilder<E> list(List<E> delegate) {
123         return new ListBuilder<>(delegate);
124     }
125 
126     public static <E> SetBuilder<E> set() {
127         return set(new HashSet<E>());
128     }
129 
130     public static <E> SetBuilder<E> set(Set<E> delegate) {
131         return new SetBuilder<>(delegate);
132     }
133 
134     /**
135      * Returns an adapted Map as a Properties instance.
136      <p>
137      * The Map is used live, which means changes made to it will affect the
138      * Properties instance directly.
139      *
140      @param map the Map instance ot adapt as a Properties instance
141      @return a new Properties instance backed by the supplied Map.
142      @since 2.1.0
143      */
144     @Nonnull
145     public static Properties toProperties(@Nonnull Map<String, Object> map) {
146         requireNonNull(map, "Argument 'map' must not be null");
147         return new MapToPropertiesAdapter(map);
148     }
149 
150     public static class MapBuilder<K, V> implements Map<K, V> {
151         private final Map<K, V> delegate;
152 
153         public MapBuilder(Map<K, V> delegate) {
154             this.delegate = delegate;
155         }
156 
157         public MapBuilder<K, V> e(K k, V v) {
158             delegate.put(k, v);
159             return this;
160         }
161 
162         public int size() {
163             return delegate.size();
164         }
165 
166         public boolean isEmpty() {
167             return delegate.isEmpty();
168         }
169 
170         public boolean containsKey(Object o) {
171             return delegate.containsKey(o);
172         }
173 
174         public boolean containsValue(Object o) {
175             return delegate.containsValue(o);
176         }
177 
178         public V get(Object o) {
179             return delegate.get(o);
180         }
181 
182         public V put(K k, V v) {
183             return delegate.put(k, v);
184         }
185 
186         public V remove(Object o) {
187             return delegate.remove(o);
188         }
189 
190         public void putAll(Map<? extends K, ? extends V> map) {
191             delegate.putAll(map);
192         }
193 
194         public void clear() {
195             delegate.clear();
196         }
197 
198         public Set<K> keySet() {
199             return delegate.keySet();
200         }
201 
202         public Collection<V> values() {
203             return delegate.values();
204         }
205 
206         public Set<Entry<K, V>> entrySet() {
207             return delegate.entrySet();
208         }
209 
210         @Override
211         public boolean equals(Object o) {
212             return delegate.equals(o);
213         }
214 
215         @Override
216         public int hashCode() {
217             return delegate.hashCode();
218         }
219 
220         @Override
221         public String toString() {
222             return delegate.toString();
223         }
224     }
225 
226     public static class ListBuilder<E> implements List<E> {
227         private final List<E> delegate;
228 
229         public ListBuilder(List<E> delegate) {
230             this.delegate = delegate;
231         }
232 
233         public ListBuilder<E> e(E e) {
234             delegate.add(e);
235             return this;
236         }
237 
238         public int size() {
239             return delegate.size();
240         }
241 
242         public boolean isEmpty() {
243             return delegate.isEmpty();
244         }
245 
246         public boolean contains(Object o) {
247             return delegate.contains(o);
248         }
249 
250         public Iterator<E> iterator() {
251             return delegate.iterator();
252         }
253 
254         public Object[] toArray() {
255             return delegate.toArray();
256         }
257 
258         public <T> T[] toArray(T[] ts) {
259             return delegate.toArray(ts);
260         }
261 
262         public boolean add(E e) {
263             return delegate.add(e);
264         }
265 
266         public boolean remove(Object o) {
267             return delegate.remove(o);
268         }
269 
270         public boolean containsAll(Collection<?> objects) {
271             return delegate.containsAll(objects);
272         }
273 
274         public boolean addAll(Collection<? extends E> es) {
275             return delegate.addAll(es);
276         }
277 
278         public boolean addAll(int i, Collection<? extends E> es) {
279             return delegate.addAll(i, es);
280         }
281 
282         public boolean removeAll(Collection<?> objects) {
283             return delegate.removeAll(objects);
284         }
285 
286         public boolean retainAll(Collection<?> objects) {
287             return delegate.retainAll(objects);
288         }
289 
290         public void clear() {
291             delegate.clear();
292         }
293 
294         @Override
295         public boolean equals(Object o) {
296             return delegate.equals(o);
297         }
298 
299         @Override
300         public int hashCode() {
301             return delegate.hashCode();
302         }
303 
304         @Override
305         public String toString() {
306             return delegate.toString();
307         }
308 
309         public E get(int i) {
310             return delegate.get(i);
311         }
312 
313         public E set(int i, E e) {
314             return delegate.set(i, e);
315         }
316 
317         public void add(int i, E e) {
318             delegate.add(i, e);
319         }
320 
321         public E remove(int i) {
322             return delegate.remove(i);
323         }
324 
325         public int indexOf(Object o) {
326             return delegate.indexOf(o);
327         }
328 
329         public int lastIndexOf(Object o) {
330             return delegate.lastIndexOf(o);
331         }
332 
333         public ListIterator<E> listIterator() {
334             return delegate.listIterator();
335         }
336 
337         public ListIterator<E> listIterator(int i) {
338             return delegate.listIterator(i);
339         }
340 
341         public List<E> subList(int i, int i1) {
342             return delegate.subList(i, i1);
343         }
344     }
345 
346     public static class SetBuilder<E> implements Set<E> {
347         private final Set<E> delegate;
348 
349         public SetBuilder(Set<E> delegate) {
350             this.delegate = delegate;
351         }
352 
353         public SetBuilder<E> e(E e) {
354             delegate.add(e);
355             return this;
356         }
357 
358         public int size() {
359             return delegate.size();
360         }
361 
362         public boolean isEmpty() {
363             return delegate.isEmpty();
364         }
365 
366         public boolean contains(Object o) {
367             return delegate.contains(o);
368         }
369 
370         public Iterator<E> iterator() {
371             return delegate.iterator();
372         }
373 
374         public Object[] toArray() {
375             return delegate.toArray();
376         }
377 
378         public <T> T[] toArray(T[] ts) {
379             return delegate.toArray(ts);
380         }
381 
382         public boolean add(E e) {
383             return delegate.add(e);
384         }
385 
386         public boolean remove(Object o) {
387             return delegate.remove(o);
388         }
389 
390         public boolean containsAll(Collection<?> objects) {
391             return delegate.containsAll(objects);
392         }
393 
394         public boolean addAll(Collection<? extends E> es) {
395             return delegate.addAll(es);
396         }
397 
398         public boolean retainAll(Collection<?> objects) {
399             return delegate.retainAll(objects);
400         }
401 
402         public boolean removeAll(Collection<?> objects) {
403             return delegate.removeAll(objects);
404         }
405 
406         public void clear() {
407             delegate.clear();
408         }
409 
410         @Override
411         public boolean equals(Object o) {
412             return delegate.equals(o);
413         }
414 
415         @Override
416         public int hashCode() {
417             return delegate.hashCode();
418         }
419 
420         @Override
421         public String toString() {
422             return delegate.toString();
423         }
424     }
425 
426     private static class MapToPropertiesAdapter extends Properties {
427         private final Map<String, Object> map;
428 
429         private MapToPropertiesAdapter(@Nonnull Map<String, Object> map) {
430             this.map = map;
431         }
432 
433         @Override
434         public synchronized Object setProperty(String key, String value) {
435             return map.put(key, value);
436         }
437 
438         @Override
439         public String getProperty(String key) {
440             Object value = map.get(key);
441             return value != null ? String.valueOf(valuenull;
442         }
443 
444         @Override
445         public String getProperty(String key, String defaultValue) {
446             Object value = map.get(key);
447             return value != null ? String.valueOf(value: defaultValue;
448         }
449 
450         @Override
451         public Enumeration<?> propertyNames() {
452             return keys();
453         }
454 
455         @Override
456         public Set<String> stringPropertyNames() {
457             return map.keySet();
458         }
459 
460         @Override
461         public synchronized int size() {
462             return map.size();
463         }
464 
465         @Override
466         public synchronized boolean isEmpty() {
467             return map.isEmpty();
468         }
469 
470         @Override
471         public synchronized Enumeration<Object> keys() {
472             return new Enumeration<Object>() {
473                 private Iterator<String> keys = new ArrayList<>(map.keySet()).iterator();
474 
475                 @Override
476                 public boolean hasMoreElements() {
477                     return keys.hasNext();
478                 }
479 
480                 @Override
481                 public String nextElement() {
482                     return keys.next();
483                 }
484             };
485         }
486 
487         @Override
488         public synchronized Enumeration<Object> elements() {
489             return new Enumeration<Object>() {
490                 private Iterator<Object> values = new ArrayList<>(map.values()).iterator();
491 
492                 @Override
493                 public boolean hasMoreElements() {
494                     return values.hasNext();
495                 }
496 
497                 @Override
498                 public Object nextElement() {
499                     return values.next();
500                 }
501             };
502         }
503 
504         @Override
505         public synchronized boolean contains(Object value) {
506             return map.containsValue(value);
507         }
508 
509         @Override
510         public boolean containsValue(Object value) {
511             return map.containsValue(value);
512         }
513 
514         @Override
515         public synchronized boolean containsKey(Object key) {
516             return map.containsKey(key);
517         }
518 
519         @Override
520         public synchronized Object get(Object key) {
521             return map.get(key);
522         }
523 
524         @Override
525         public synchronized Object put(Object key, Object value) {
526             return map.put(String.valueOf(key), value);
527         }
528 
529         @Override
530         public synchronized Object remove(Object key) {
531             return map.remove(key);
532         }
533 
534         @Override
535         public synchronized void putAll(Map<?, ?> t) {
536             map.putAll((Map<String, Object>t);
537         }
538 
539         @Override
540         public synchronized void clear() {
541             map.clear();
542         }
543 
544         @Override
545         public Set<Object> keySet() {
546             return new LinkedHashSet<Object>(map.keySet());
547         }
548 
549         @Override
550         public Set<Map.Entry<Object, Object>> entrySet() {
551             Set<Map.Entry<Object, Object>> set = new LinkedHashSet<>((Setmap.entrySet());
552             return new LinkedHashSet<>(set);
553         }
554 
555         @Override
556         public Collection<Object> values() {
557             return map.values();
558         }
559 
560         @Override
561         public synchronized Object clone() {
562             Map<String, Object> m = new LinkedHashMap<>(map);
563             return new MapToPropertiesAdapter(m);
564         }
565     }
566 }