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