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 % 2 == 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((K) keysAndValues[i], (V) keysAndValues[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(value) : null;
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<>((Set) map.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 }
|