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