CollectionUtils.java
001 /*
002  * Copyright 2008-2017 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     private static final String ERROR_MAP_NULL = "Argument 'map' must not be null";
065 
066     private CollectionUtils() {
067         // prevent instantiation
068     }
069 
070     public static <T> List<T> reverse(List<T> input) {
071         List<T> output = new ArrayList<>(input);
072         Collections.reverse(output);
073         return output;
074     }
075 
076     public static <T> List<T> reverse(Collection<T> input) {
077         List<T> output = new ArrayList<>(input);
078         Collections.reverse(output);
079         return output;
080     }
081 
082     @SuppressWarnings({"rawtypes""unchecked"})
083     public static <K, V> Map newMap(Object... keysAndValues) {
084         if (keysAndValues == null) {
085             return Collections.emptyMap();
086         }
087         if (keysAndValues.length % == 1) {
088             throw new IllegalArgumentException("Must have an even number of keys and values");
089         }
090 
091         Map<K, V> map = new HashMap<>();
092         for (int i = 0; i < keysAndValues.length; i += 2) {
093             map.put((KkeysAndValues[i](VkeysAndValues[i + 1]);
094         }
095         return map;
096     }
097 
098     @SafeVarargs
099     public static <T> Set<T> newSet(T... values) {
100         if (values == null) {
101             return Collections.emptySet();
102         }
103 
104         return new HashSet<>(Arrays.asList(values));
105     }
106 
107     @SafeVarargs
108     public static <T> List<T> newList(T... values) {
109         if (values == null) {
110             return Collections.emptyList();
111         }
112 
113         return new ArrayList<>(Arrays.asList(values));
114     }
115 
116     public static <K, V> MapBuilder<K, V> map() {
117         return map(new LinkedHashMap<K, V>());
118     }
119 
120     public static <K, V> MapBuilder<K, V> map(Map<K, V> delegate) {
121         return new MapBuilder<>(delegate);
122     }
123 
124     public static <E> ListBuilder<E> list() {
125         return list(new ArrayList<E>());
126     }
127 
128     public static <E> ListBuilder<E> list(List<E> delegate) {
129         return new ListBuilder<>(delegate);
130     }
131 
132     public static <E> SetBuilder<E> set() {
133         return set(new HashSet<E>());
134     }
135 
136     public static <E> SetBuilder<E> set(Set<E> delegate) {
137         return new SetBuilder<>(delegate);
138     }
139 
140     /**
141      * Returns an adapted Map as a Properties instance.
142      <p>
143      * The Map is used live, which means changes made to it will affect the
144      * Properties instance directly.
145      *
146      @param map the Map instance to adapt as a Properties instance
147      *
148      @return a new Properties instance backed by the supplied Map.
149      *
150      @since 2.1.0
151      */
152     @Nonnull
153     public static Properties toProperties(@Nonnull Map<String, Object> map) {
154         requireNonNull(map, ERROR_MAP_NULL);
155         return new MapToPropertiesAdapter(map);
156     }
157 
158     /**
159      * Creates a Properties instances based on the given Map.
160      *
161      @param map the Map instance to convert as a Properties instance
162      *
163      @return a new Properties instance based by the supplied Map.
164      *
165      @since 2.10.0
166      */
167     @Nonnull
168     public static Properties toPropertiesDeep(@Nonnull Map<String, Object> map) {
169         requireNonNull(map, ERROR_MAP_NULL);
170         Properties properties = new Properties();
171 
172         for (Map.Entry<String, Object> e : map.entrySet()) {
173             createKey(properties, e.getKey(), e.getValue());
174         }
175 
176         return properties;
177     }
178 
179     @SuppressWarnings("unchecked")
180     private static void createKey(@Nonnull Properties properties, @Nonnull String key, @Nonnull Object value) {
181         if (value instanceof Map) {
182             Map<String, Object> map = (Map<String, Object>value;
183             for (Map.Entry<String, Object> e : map.entrySet()) {
184                 createKey(properties, key + "." + e.getKey(), e.getValue());
185             }
186         else {
187             properties.put(key, value);
188         }
189     }
190 
191     public static class MapBuilder<K, V> implements Map<K, V> {
192         private final Map<K, V> delegate;
193 
194         public MapBuilder(Map<K, V> delegate) {
195             this.delegate = delegate;
196         }
197 
198         public MapBuilder<K, V> e(K k, V v) {
199             delegate.put(k, v);
200             return this;
201         }
202 
203         public int size() {
204             return delegate.size();
205         }
206 
207         public boolean isEmpty() {
208             return delegate.isEmpty();
209         }
210 
211         public boolean containsKey(Object o) {
212             return delegate.containsKey(o);
213         }
214 
215         public boolean containsValue(Object o) {
216             return delegate.containsValue(o);
217         }
218 
219         public V get(Object o) {
220             return delegate.get(o);
221         }
222 
223         public V put(K k, V v) {
224             return delegate.put(k, v);
225         }
226 
227         public V remove(Object o) {
228             return delegate.remove(o);
229         }
230 
231         public void putAll(Map<? extends K, ? extends V> map) {
232             delegate.putAll(map);
233         }
234 
235         public void clear() {
236             delegate.clear();
237         }
238 
239         public Set<K> keySet() {
240             return delegate.keySet();
241         }
242 
243         public Collection<V> values() {
244             return delegate.values();
245         }
246 
247         public Set<Entry<K, V>> entrySet() {
248             return delegate.entrySet();
249         }
250 
251         @Override
252         public boolean equals(Object o) {
253             return delegate.equals(o);
254         }
255 
256         @Override
257         public int hashCode() {
258             return delegate.hashCode();
259         }
260 
261         @Override
262         public String toString() {
263             return delegate.toString();
264         }
265     }
266 
267     public static class ListBuilder<E> implements List<E> {
268         private final List<E> delegate;
269 
270         public ListBuilder(List<E> delegate) {
271             this.delegate = delegate;
272         }
273 
274         public ListBuilder<E> e(E e) {
275             delegate.add(e);
276             return this;
277         }
278 
279         public int size() {
280             return delegate.size();
281         }
282 
283         public boolean isEmpty() {
284             return delegate.isEmpty();
285         }
286 
287         public boolean contains(Object o) {
288             return delegate.contains(o);
289         }
290 
291         public Iterator<E> iterator() {
292             return delegate.iterator();
293         }
294 
295         public Object[] toArray() {
296             return delegate.toArray();
297         }
298 
299         public <T> T[] toArray(T[] ts) {
300             return delegate.toArray(ts);
301         }
302 
303         public boolean add(E e) {
304             return delegate.add(e);
305         }
306 
307         public boolean remove(Object o) {
308             return delegate.remove(o);
309         }
310 
311         public boolean containsAll(Collection<?> objects) {
312             return delegate.containsAll(objects);
313         }
314 
315         public boolean addAll(Collection<? extends E> es) {
316             return delegate.addAll(es);
317         }
318 
319         public boolean addAll(int i, Collection<? extends E> es) {
320             return delegate.addAll(i, es);
321         }
322 
323         public boolean removeAll(Collection<?> objects) {
324             return delegate.removeAll(objects);
325         }
326 
327         public boolean retainAll(Collection<?> objects) {
328             return delegate.retainAll(objects);
329         }
330 
331         public void clear() {
332             delegate.clear();
333         }
334 
335         @Override
336         public boolean equals(Object o) {
337             return delegate.equals(o);
338         }
339 
340         @Override
341         public int hashCode() {
342             return delegate.hashCode();
343         }
344 
345         @Override
346         public String toString() {
347             return delegate.toString();
348         }
349 
350         public E get(int i) {
351             return delegate.get(i);
352         }
353 
354         public E set(int i, E e) {
355             return delegate.set(i, e);
356         }
357 
358         public void add(int i, E e) {
359             delegate.add(i, e);
360         }
361 
362         public E remove(int i) {
363             return delegate.remove(i);
364         }
365 
366         public int indexOf(Object o) {
367             return delegate.indexOf(o);
368         }
369 
370         public int lastIndexOf(Object o) {
371             return delegate.lastIndexOf(o);
372         }
373 
374         public ListIterator<E> listIterator() {
375             return delegate.listIterator();
376         }
377 
378         public ListIterator<E> listIterator(int i) {
379             return delegate.listIterator(i);
380         }
381 
382         public List<E> subList(int i, int i1) {
383             return delegate.subList(i, i1);
384         }
385     }
386 
387     public static class SetBuilder<E> implements Set<E> {
388         private final Set<E> delegate;
389 
390         public SetBuilder(Set<E> delegate) {
391             this.delegate = delegate;
392         }
393 
394         public SetBuilder<E> e(E e) {
395             delegate.add(e);
396             return this;
397         }
398 
399         public int size() {
400             return delegate.size();
401         }
402 
403         public boolean isEmpty() {
404             return delegate.isEmpty();
405         }
406 
407         public boolean contains(Object o) {
408             return delegate.contains(o);
409         }
410 
411         public Iterator<E> iterator() {
412             return delegate.iterator();
413         }
414 
415         public Object[] toArray() {
416             return delegate.toArray();
417         }
418 
419         public <T> T[] toArray(T[] ts) {
420             return delegate.toArray(ts);
421         }
422 
423         public boolean add(E e) {
424             return delegate.add(e);
425         }
426 
427         public boolean remove(Object o) {
428             return delegate.remove(o);
429         }
430 
431         public boolean containsAll(Collection<?> objects) {
432             return delegate.containsAll(objects);
433         }
434 
435         public boolean addAll(Collection<? extends E> es) {
436             return delegate.addAll(es);
437         }
438 
439         public boolean retainAll(Collection<?> objects) {
440             return delegate.retainAll(objects);
441         }
442 
443         public boolean removeAll(Collection<?> objects) {
444             return delegate.removeAll(objects);
445         }
446 
447         public void clear() {
448             delegate.clear();
449         }
450 
451         @Override
452         public boolean equals(Object o) {
453             return delegate.equals(o);
454         }
455 
456         @Override
457         public int hashCode() {
458             return delegate.hashCode();
459         }
460 
461         @Override
462         public String toString() {
463             return delegate.toString();
464         }
465     }
466 
467     private static class MapToPropertiesAdapter extends Properties {
468         private final transient Map<String, Object> map;
469 
470         private MapToPropertiesAdapter(@Nonnull Map<String, Object> map) {
471             this.map = map;
472         }
473 
474         @Override
475         public synchronized Object setProperty(String key, String value) {
476             return map.put(key, value);
477         }
478 
479         @Override
480         public String getProperty(String key) {
481             Object value = map.get(key);
482             return value != null ? String.valueOf(valuenull;
483         }
484 
485         @Override
486         public String getProperty(String key, String defaultValue) {
487             Object value = map.get(key);
488             return value != null ? String.valueOf(value: defaultValue;
489         }
490 
491         @Override
492         public Enumeration<?> propertyNames() {
493             return keys();
494         }
495 
496         @Override
497         public Set<String> stringPropertyNames() {
498             return map.keySet();
499         }
500 
501         @Override
502         public synchronized int size() {
503             return map.size();
504         }
505 
506         @Override
507         public synchronized boolean isEmpty() {
508             return map.isEmpty();
509         }
510 
511         @Override
512         public synchronized Enumeration<Object> keys() {
513             return new Enumeration<Object>() {
514                 private Iterator<String> keys = new ArrayList<>(map.keySet()).iterator();
515 
516                 @Override
517                 public boolean hasMoreElements() {
518                     return keys.hasNext();
519                 }
520 
521                 @Override
522                 public String nextElement() {
523                     return keys.next();
524                 }
525             };
526         }
527 
528         @Override
529         public synchronized Enumeration<Object> elements() {
530             return new Enumeration<Object>() {
531                 private Iterator<Object> values = new ArrayList<>(map.values()).iterator();
532 
533                 @Override
534                 public boolean hasMoreElements() {
535                     return values.hasNext();
536                 }
537 
538                 @Override
539                 public Object nextElement() {
540                     return values.next();
541                 }
542             };
543         }
544 
545         @Override
546         public synchronized boolean contains(Object value) {
547             return map.containsValue(value);
548         }
549 
550         @Override
551         public boolean containsValue(Object value) {
552             return map.containsValue(value);
553         }
554 
555         @Override
556         public synchronized boolean containsKey(Object key) {
557             return map.containsKey(key);
558         }
559 
560         @Override
561         public synchronized Object get(Object key) {
562             return map.get(key);
563         }
564 
565         @Override
566         public synchronized Object put(Object key, Object value) {
567             return map.put(String.valueOf(key), value);
568         }
569 
570         @Override
571         public synchronized Object remove(Object key) {
572             return map.remove(key);
573         }
574 
575         @Override
576         public synchronized void putAll(Map<?, ?> t) {
577             map.putAll((Map<String, Object>t);
578         }
579 
580         @Override
581         public synchronized void clear() {
582             map.clear();
583         }
584 
585         @Override
586         public Set<Object> keySet() {
587             return new LinkedHashSet<Object>(map.keySet());
588         }
589 
590         @Override
591         public Set<Map.Entry<Object, Object>> entrySet() {
592             Set<Map.Entry<Object, Object>> set = new LinkedHashSet<>((Setmap.entrySet());
593             return new LinkedHashSet<>(set);
594         }
595 
596         @Override
597         public Collection<Object> values() {
598             return map.values();
599         }
600 
601         @Override
602         public synchronized Object clone() {
603             Map<String, Object> m = new LinkedHashMap<>(map);
604             return new MapToPropertiesAdapter(m);
605         }
606     }
607 }