1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.api.model;
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 if (map != null) {
489 entries = new Object[map.size()];
490 int idx = 0;
491 for (Map.Entry<K, V> e : map.entrySet()) {
492 entries[idx++] = new SimpleImmutableEntry<>(e.getKey(), e.getValue());
493 }
494 } else {
495 entries = new Object[0];
496 }
497 }
498
499 @Override
500 public Set<Entry<K, V>> entrySet() {
501 return new AbstractImmutableSet<Entry<K, V>>() {
502 @Override
503 public Iterator<Entry<K, V>> iterator() {
504 return new Iterator<Entry<K, V>>() {
505 int index = 0;
506
507 @Override
508 public boolean hasNext() {
509 return index < entries.length;
510 }
511
512 @SuppressWarnings("unchecked")
513 @Override
514 public Entry<K, V> next() {
515 if (index < entries.length) {
516 return (Entry<K, V>) entries[index++];
517 }
518 throw new NoSuchElementException();
519 }
520 };
521 }
522
523 @Override
524 public int size() {
525 return entries.length;
526 }
527 };
528 }
529 }
530
531 private abstract static class AbstractImmutableMap<K, V> extends AbstractMap<K, V> implements Serializable {
532 @Override
533 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
534 throw uoe();
535 }
536
537 @Override
538 public V putIfAbsent(K key, V value) {
539 throw uoe();
540 }
541
542 @Override
543 public boolean remove(Object key, Object value) {
544 throw uoe();
545 }
546
547 @Override
548 public boolean replace(K key, V oldValue, V newValue) {
549 throw uoe();
550 }
551
552 @Override
553 public V replace(K key, V value) {
554 throw uoe();
555 }
556
557 @Override
558 public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
559 throw uoe();
560 }
561
562 @Override
563 public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
564 throw uoe();
565 }
566
567 @Override
568 public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
569 throw uoe();
570 }
571
572 @Override
573 public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
574 throw uoe();
575 }
576 }
577
578 private abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
579 @Override
580 public boolean removeAll(Collection<?> c) {
581 throw uoe();
582 }
583
584 @Override
585 public boolean add(E e) {
586 throw uoe();
587 }
588
589 @Override
590 public boolean remove(Object o) {
591 throw uoe();
592 }
593
594 @Override
595 public boolean retainAll(Collection<?> c) {
596 throw uoe();
597 }
598
599 @Override
600 public void clear() {
601 throw uoe();
602 }
603
604 @Override
605 public boolean removeIf(Predicate<? super E> filter) {
606 throw uoe();
607 }
608 }
609
610 private static UnsupportedOperationException uoe() {
611 return new UnsupportedOperationException();
612 }
613 }