1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.lifecycle;
20
21 import java.io.Serializable;
22 import java.util.AbstractList;
23 import java.util.AbstractMap;
24 import java.util.AbstractSet;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.ListIterator;
30 import java.util.Map;
31 import java.util.NoSuchElementException;
32 import java.util.Properties;
33 import java.util.RandomAccess;
34 import java.util.Set;
35 import java.util.function.BiFunction;
36 import java.util.function.Function;
37 import java.util.function.Predicate;
38 import java.util.function.UnaryOperator;
39
40 class ImmutableCollections {
41
42 private static final List<?> EMPTY_LIST = new AbstractImmutableList<Object>() {
43 @Override
44 public Object get(int index) {
45 throw new IndexOutOfBoundsException();
46 }
47
48 @Override
49 public int size() {
50 return 0;
51 }
52 };
53
54 private static final Map<?, ?> EMPTY_MAP = new AbstractImmutableMap<Object, Object>() {
55 @Override
56 public Set<Entry<Object, Object>> entrySet() {
57 return new AbstractImmutableSet<Entry<Object, Object>>() {
58 @Override
59 public Iterator<Entry<Object, Object>> iterator() {
60 return new Iterator<Entry<Object, Object>>() {
61 @Override
62 public boolean hasNext() {
63 return false;
64 }
65
66 @Override
67 public Entry<Object, Object> next() {
68 throw new NoSuchElementException();
69 }
70 };
71 }
72
73 @Override
74 public int size() {
75 return 0;
76 }
77 };
78 }
79 };
80
81 static <E> List<E> copy(Collection<E> collection) {
82 if (collection == null) {
83 return emptyList();
84 } else if (collection instanceof AbstractImmutableList) {
85 return (List<E>) collection;
86 } else {
87 switch (collection.size()) {
88 case 0:
89 return emptyList();
90 case 1:
91 return singletonList(collection.iterator().next());
92 case 2:
93 Iterator<E> it = collection.iterator();
94 return new List2<>(it.next(), it.next());
95 default:
96 return new ListN<>(collection);
97 }
98 }
99 }
100
101 @SuppressWarnings("unchecked")
102 static <E> List<E> emptyList() {
103 return (List<E>) EMPTY_LIST;
104 }
105
106 static <E> List<E> singletonList(E element) {
107 return new List1<>(element);
108 }
109
110 static <K, V> Map<K, V> copy(Map<K, V> map) {
111 if (map == null) {
112 return emptyMap();
113 } else if (map instanceof AbstractImmutableMap) {
114 return map;
115 } else {
116 switch (map.size()) {
117 case 0:
118 return emptyMap();
119 case 1:
120 Map.Entry<K, V> entry = map.entrySet().iterator().next();
121 return singletonMap(entry.getKey(), entry.getValue());
122 default:
123 return new MapN<>(map);
124 }
125 }
126 }
127
128 @SuppressWarnings("unchecked")
129 static <K, V> Map<K, V> emptyMap() {
130 return (Map<K, V>) EMPTY_MAP;
131 }
132
133 static <K, V> Map<K, V> singletonMap(K key, V value) {
134 return new Map1<>(key, value);
135 }
136
137 static Properties copy(Properties properties) {
138 if (properties instanceof ROProperties) {
139 return properties;
140 }
141 return new ROProperties(properties);
142 }
143
144 private static class List1<E> extends AbstractImmutableList<E> {
145 private final E element;
146
147 private List1(E element) {
148 this.element = element;
149 }
150
151 @Override
152 public E get(int index) {
153 if (index == 0) {
154 return element;
155 }
156 throw outOfBounds(index);
157 }
158
159 @Override
160 public int size() {
161 return 1;
162 }
163 }
164
165 private static class List2<E> extends AbstractImmutableList<E> {
166 private final E element1;
167 private final E element2;
168
169 private List2(E element1, E element2) {
170 this.element1 = element1;
171 this.element2 = element2;
172 }
173
174 @Override
175 public E get(int index) {
176 if (index == 0) {
177 return element1;
178 } else if (index == 1) {
179 return element2;
180 }
181 throw outOfBounds(index);
182 }
183
184 @Override
185 public int size() {
186 return 2;
187 }
188 }
189
190 private static class ListN<E> extends AbstractImmutableList<E> {
191 private final Object[] elements;
192
193 private ListN(Collection<E> elements) {
194 this.elements = elements.toArray();
195 }
196
197 @SuppressWarnings("unchecked")
198 @Override
199 public E get(int index) {
200 return (E) elements[index];
201 }
202
203 @Override
204 public int size() {
205 return elements.length;
206 }
207 }
208
209 private abstract static class AbstractImmutableList<E> extends AbstractList<E>
210 implements RandomAccess, Serializable {
211 @Override
212 public boolean add(E e) {
213 throw uoe();
214 }
215
216 @Override
217 public boolean remove(Object o) {
218 throw uoe();
219 }
220
221 @Override
222 public boolean addAll(Collection<? extends E> c) {
223 throw uoe();
224 }
225
226 @Override
227 public boolean removeAll(Collection<?> c) {
228 throw uoe();
229 }
230
231 @Override
232 public boolean retainAll(Collection<?> c) {
233 throw uoe();
234 }
235
236 @Override
237 public void clear() {
238 throw uoe();
239 }
240
241 @Override
242 public boolean removeIf(Predicate<? super E> filter) {
243 throw uoe();
244 }
245
246 @Override
247 public void replaceAll(UnaryOperator<E> operator) {
248 throw uoe();
249 }
250
251 @Override
252 public void sort(Comparator<? super E> c) {
253 throw uoe();
254 }
255
256 @Override
257 public Iterator<E> iterator() {
258 return new Itr(0);
259 }
260
261 @Override
262 public ListIterator<E> listIterator() {
263 return new Itr(0);
264 }
265
266 @Override
267 public ListIterator<E> listIterator(int index) {
268 if (index < 0 || index > size()) {
269 throw outOfBounds(index);
270 }
271 return new Itr(index);
272 }
273
274 @Override
275 public List<E> subList(int fromIndex, int toIndex) {
276 if (fromIndex < 0) {
277 throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
278 }
279 if (toIndex > size()) {
280 throw new IndexOutOfBoundsException("toIndex = " + toIndex);
281 }
282 if (fromIndex > toIndex) {
283 throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
284 }
285 return new SubList(fromIndex, toIndex);
286 }
287
288 protected IndexOutOfBoundsException outOfBounds(int index) {
289 return new IndexOutOfBoundsException("Index: " + index + ", Size: " + size());
290 }
291
292 private class SubList extends AbstractImmutableList<E> {
293 private final int fromIndex;
294 private final int toIndex;
295
296 private SubList(int fromIndex, int toIndex) {
297 this.fromIndex = fromIndex;
298 this.toIndex = toIndex;
299 }
300
301 @Override
302 public E get(int index) {
303 if (index < 0 || index > size()) {
304 throw outOfBounds(index);
305 }
306 return AbstractImmutableList.this.get(fromIndex + index);
307 }
308
309 @Override
310 public int size() {
311 return toIndex - fromIndex;
312 }
313 }
314
315 private class Itr implements ListIterator<E> {
316 int index;
317
318 private Itr(int index) {
319 this.index = index;
320 }
321
322 @Override
323 public boolean hasNext() {
324 return index < size();
325 }
326
327 @Override
328 public E next() {
329 return get(index++);
330 }
331
332 @Override
333 public boolean hasPrevious() {
334 return index > 0;
335 }
336
337 @Override
338 public E previous() {
339 return get(--index);
340 }
341
342 @Override
343 public int nextIndex() {
344 return index;
345 }
346
347 @Override
348 public int previousIndex() {
349 return index - 1;
350 }
351
352 @Override
353 public void remove() {
354 throw uoe();
355 }
356
357 @Override
358 public void set(E e) {
359 throw uoe();
360 }
361
362 @Override
363 public void add(E e) {
364 throw uoe();
365 }
366 }
367 }
368
369 private static class ROProperties extends Properties {
370 private ROProperties(Properties props) {
371 super();
372 if (props != null) {
373
374 for (Map.Entry<Object, Object> e : props.entrySet()) {
375 super.put(e.getKey(), e.getValue());
376 }
377 }
378 }
379
380 @Override
381 public Object put(Object key, Object value) {
382 throw uoe();
383 }
384
385 @Override
386 public Object remove(Object key) {
387 throw uoe();
388 }
389
390 @Override
391 public void putAll(Map<?, ?> t) {
392 throw uoe();
393 }
394
395 @Override
396 public void clear() {
397 throw uoe();
398 }
399
400 @Override
401 public void replaceAll(BiFunction<? super Object, ? super Object, ?> function) {
402 throw uoe();
403 }
404
405 @Override
406 public Object putIfAbsent(Object key, Object value) {
407 throw uoe();
408 }
409
410 @Override
411 public boolean remove(Object key, Object value) {
412 throw uoe();
413 }
414
415 @Override
416 public boolean replace(Object key, Object oldValue, Object newValue) {
417 throw uoe();
418 }
419
420 @Override
421 public Object replace(Object key, Object value) {
422 throw uoe();
423 }
424
425 @Override
426 public Object computeIfAbsent(Object key, Function<? super Object, ?> mappingFunction) {
427 throw uoe();
428 }
429
430 @Override
431 public Object computeIfPresent(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
432 throw uoe();
433 }
434
435 @Override
436 public Object compute(Object key, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
437 throw uoe();
438 }
439
440 @Override
441 public Object merge(Object key, Object value, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
442 throw uoe();
443 }
444 }
445
446 private static class Map1<K, V> extends AbstractImmutableMap<K, V> {
447 private final Entry<K, V> entry;
448
449 private Map1(K key, V value) {
450 this.entry = new SimpleImmutableEntry<>(key, value);
451 }
452
453 @Override
454 public Set<Entry<K, V>> entrySet() {
455 return new AbstractImmutableSet<Entry<K, V>>() {
456 @Override
457 public Iterator<Entry<K, V>> iterator() {
458 return new Iterator<Entry<K, V>>() {
459 int index = 0;
460
461 @Override
462 public boolean hasNext() {
463 return index == 0;
464 }
465
466 @Override
467 public Entry<K, V> next() {
468 if (index++ == 0) {
469 return entry;
470 }
471 throw new NoSuchElementException();
472 }
473 };
474 }
475
476 @Override
477 public int size() {
478 return 1;
479 }
480 };
481 }
482 }
483
484 private static class MapN<K, V> extends AbstractImmutableMap<K, V> {
485 private final Object[] entries;
486
487 private MapN(Map<K, V> map) {
488 entries = map != null ? map.entrySet().toArray() : new Object[0];
489 }
490
491 @Override
492 public Set<Entry<K, V>> entrySet() {
493 return new AbstractImmutableSet<Entry<K, V>>() {
494 @Override
495 public Iterator<Entry<K, V>> iterator() {
496 return new Iterator<Entry<K, V>>() {
497 int index = 0;
498
499 @Override
500 public boolean hasNext() {
501 return index < entries.length;
502 }
503
504 @SuppressWarnings("unchecked")
505 @Override
506 public Entry<K, V> next() {
507 if (index < entries.length) {
508 return (Entry<K, V>) entries[index++];
509 }
510 throw new NoSuchElementException();
511 }
512 };
513 }
514
515 @Override
516 public int size() {
517 return entries.length;
518 }
519 };
520 }
521 }
522
523 private abstract static class AbstractImmutableMap<K, V> extends AbstractMap<K, V> implements Serializable {
524 @Override
525 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
526 throw uoe();
527 }
528
529 @Override
530 public V putIfAbsent(K key, V value) {
531 throw uoe();
532 }
533
534 @Override
535 public boolean remove(Object key, Object value) {
536 throw uoe();
537 }
538
539 @Override
540 public boolean replace(K key, V oldValue, V newValue) {
541 throw uoe();
542 }
543
544 @Override
545 public V replace(K key, V value) {
546 throw uoe();
547 }
548
549 @Override
550 public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
551 throw uoe();
552 }
553
554 @Override
555 public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
556 throw uoe();
557 }
558
559 @Override
560 public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
561 throw uoe();
562 }
563
564 @Override
565 public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
566 throw uoe();
567 }
568 }
569
570 private abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
571 @Override
572 public boolean removeAll(Collection<?> c) {
573 throw uoe();
574 }
575
576 @Override
577 public boolean add(E e) {
578 throw uoe();
579 }
580
581 @Override
582 public boolean remove(Object o) {
583 throw uoe();
584 }
585
586 @Override
587 public boolean retainAll(Collection<?> c) {
588 throw uoe();
589 }
590
591 @Override
592 public void clear() {
593 throw uoe();
594 }
595
596 @Override
597 public boolean removeIf(Predicate<? super E> filter) {
598 throw uoe();
599 }
600 }
601
602 private static UnsupportedOperationException uoe() {
603 return new UnsupportedOperationException();
604 }
605 }