1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.map;
18
19 import java.io.Serializable;
20 import java.util.AbstractSet;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.Map;
25 import java.util.NoSuchElementException;
26 import java.util.Objects;
27 import java.util.Set;
28
29 import org.apache.commons.collections4.BoundedMap;
30 import org.apache.commons.collections4.KeyValue;
31 import org.apache.commons.collections4.OrderedMap;
32 import org.apache.commons.collections4.OrderedMapIterator;
33 import org.apache.commons.collections4.ResettableIterator;
34 import org.apache.commons.collections4.iterators.SingletonIterator;
35 import org.apache.commons.collections4.keyvalue.TiedMapEntry;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 public class SingletonMap<K, V>
65 implements OrderedMap<K, V>, BoundedMap<K, V>, KeyValue<K, V>, Serializable, Cloneable {
66
67
68
69
70 static class SingletonMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
71 private final SingletonMap<K, V> parent;
72 private boolean hasNext = true;
73 private boolean canGetSet;
74
75 SingletonMapIterator(final SingletonMap<K, V> parent) {
76 this.parent = parent;
77 }
78
79 @Override
80 public K getKey() {
81 if (!canGetSet) {
82 throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
83 }
84 return parent.getKey();
85 }
86
87 @Override
88 public V getValue() {
89 if (!canGetSet) {
90 throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
91 }
92 return parent.getValue();
93 }
94
95 @Override
96 public boolean hasNext() {
97 return hasNext;
98 }
99
100 @Override
101 public boolean hasPrevious() {
102 return !hasNext;
103 }
104
105 @Override
106 public K next() {
107 if (!hasNext) {
108 throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
109 }
110 hasNext = false;
111 canGetSet = true;
112 return parent.getKey();
113 }
114
115 @Override
116 public K previous() {
117 if (hasNext) {
118 throw new NoSuchElementException(AbstractHashedMap.NO_PREVIOUS_ENTRY);
119 }
120 hasNext = true;
121 return parent.getKey();
122 }
123
124 @Override
125 public void remove() {
126 throw new UnsupportedOperationException();
127 }
128
129 @Override
130 public void reset() {
131 hasNext = true;
132 }
133
134 @Override
135 public V setValue(final V value) {
136 if (!canGetSet) {
137 throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
138 }
139 return parent.setValue(value);
140 }
141
142 @Override
143 public String toString() {
144 if (hasNext) {
145 return "Iterator[]";
146 }
147 return "Iterator[" + getKey() + "=" + getValue() + "]";
148 }
149 }
150
151
152
153
154
155
156
157 static class SingletonValues<V> extends AbstractSet<V> implements Serializable {
158 private static final long serialVersionUID = -3689524741863047872L;
159 private final SingletonMap<?, V> parent;
160
161 SingletonValues(final SingletonMap<?, V> parent) {
162 this.parent = parent;
163 }
164
165 @Override
166 public void clear() {
167 throw new UnsupportedOperationException();
168 }
169 @Override
170 public boolean contains(final Object object) {
171 return parent.containsValue(object);
172 }
173 @Override
174 public boolean isEmpty() {
175 return false;
176 }
177 @Override
178 public Iterator<V> iterator() {
179 return new SingletonIterator<>(parent.getValue(), false);
180 }
181 @Override
182 public int size() {
183 return 1;
184 }
185 }
186
187 private static final long serialVersionUID = -8931271118676803261L;
188
189
190 private final K key;
191
192
193 private V value;
194
195
196
197
198 public SingletonMap() {
199 this.key = null;
200 }
201
202
203
204
205
206
207
208 public SingletonMap(final K key, final V value) {
209 this.key = key;
210 this.value = value;
211 }
212
213
214
215
216
217
218 public SingletonMap(final KeyValue<K, V> keyValue) {
219 this.key = keyValue.getKey();
220 this.value = keyValue.getValue();
221 }
222
223
224
225
226
227
228 public SingletonMap(final Map.Entry<? extends K, ? extends V> mapEntry) {
229 this.key = mapEntry.getKey();
230 this.value = mapEntry.getValue();
231 }
232
233
234
235
236
237
238
239
240 public SingletonMap(final Map<? extends K, ? extends V> map) {
241 if (map.size() != 1) {
242 throw new IllegalArgumentException("The map size must be 1");
243 }
244 final Map.Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next();
245 this.key = entry.getKey();
246 this.value = entry.getValue();
247 }
248
249
250
251
252 @Override
253 public void clear() {
254 throw new UnsupportedOperationException();
255 }
256
257
258
259
260
261
262 @Override
263 @SuppressWarnings("unchecked")
264 public SingletonMap<K, V> clone() {
265 try {
266 return (SingletonMap<K, V>) super.clone();
267 } catch (final CloneNotSupportedException ex) {
268 throw new UnsupportedOperationException(ex);
269 }
270 }
271
272
273
274
275
276
277
278 @Override
279 public boolean containsKey(final Object key) {
280 return isEqualKey(key);
281 }
282
283
284
285
286
287
288
289 @Override
290 public boolean containsValue(final Object value) {
291 return isEqualValue(value);
292 }
293
294
295
296
297
298
299
300
301 @Override
302 public Set<Map.Entry<K, V>> entrySet() {
303 final Map.Entry<K, V> entry = new TiedMapEntry<>(this, getKey());
304 return Collections.singleton(entry);
305 }
306
307
308
309
310
311
312
313 @Override
314 public boolean equals(final Object obj) {
315 if (obj == this) {
316 return true;
317 }
318 if (!(obj instanceof Map)) {
319 return false;
320 }
321 final Map<?, ?> other = (Map<?, ?>) obj;
322 if (other.size() != 1) {
323 return false;
324 }
325 final Map.Entry<?, ?> entry = other.entrySet().iterator().next();
326 return isEqualKey(entry.getKey()) && isEqualValue(entry.getValue());
327 }
328
329
330
331
332
333
334 @Override
335 public K firstKey() {
336 return getKey();
337 }
338
339
340
341
342
343
344
345
346 @Override
347 public V get(final Object key) {
348 if (isEqualKey(key)) {
349 return value;
350 }
351 return null;
352 }
353
354
355
356
357
358
359
360 @Override
361 public K getKey() {
362 return key;
363 }
364
365
366
367
368
369
370 @Override
371 public V getValue() {
372 return value;
373 }
374
375
376
377
378
379
380 @Override
381 public int hashCode() {
382 return (getKey() == null ? 0 : getKey().hashCode()) ^
383 (getValue() == null ? 0 : getValue().hashCode());
384 }
385
386
387
388
389
390
391 @Override
392 public boolean isEmpty() {
393 return false;
394 }
395
396
397
398
399
400
401
402 protected boolean isEqualKey(final Object key) {
403 return Objects.equals(key, getKey());
404 }
405
406
407
408
409
410
411
412 protected boolean isEqualValue(final Object value) {
413 return Objects.equals(value, getValue());
414 }
415
416
417
418
419
420
421
422 @Override
423 public boolean isFull() {
424 return true;
425 }
426
427
428
429
430
431
432
433
434 @Override
435 public Set<K> keySet() {
436 return Collections.singleton(key);
437 }
438
439
440
441
442
443
444 @Override
445 public K lastKey() {
446 return getKey();
447 }
448
449
450
451
452 @Override
453 public OrderedMapIterator<K, V> mapIterator() {
454 return new SingletonMapIterator<>(this);
455 }
456
457
458
459
460
461
462 @Override
463 public int maxSize() {
464 return 1;
465 }
466
467
468
469
470
471
472
473 @Override
474 public K nextKey(final K key) {
475 return null;
476 }
477
478
479
480
481
482
483
484 @Override
485 public K previousKey(final K key) {
486 return null;
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501 @Override
502 public V put(final K key, final V value) {
503 if (isEqualKey(key)) {
504 return setValue(value);
505 }
506 throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size singleton");
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521 @Override
522 public void putAll(final Map<? extends K, ? extends V> map) {
523 switch (map.size()) {
524 case 0:
525 return;
526
527 case 1:
528 final Map.Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next();
529 put(entry.getKey(), entry.getValue());
530 return;
531
532 default:
533 throw new IllegalArgumentException("The map size must be 0 or 1");
534 }
535 }
536
537
538
539
540
541
542
543
544 @Override
545 public V remove(final Object key) {
546 throw new UnsupportedOperationException();
547 }
548
549
550
551
552
553
554
555 public V setValue(final V value) {
556 final V old = this.value;
557 this.value = value;
558 return old;
559 }
560
561
562
563
564
565
566 @Override
567 public int size() {
568 return 1;
569 }
570
571
572
573
574
575
576 @Override
577 public String toString() {
578 return new StringBuilder(128)
579 .append('{')
580 .append(getKey() == this ? "(this Map)" : getKey())
581 .append('=')
582 .append(getValue() == this ? "(this Map)" : getValue())
583 .append('}')
584 .toString();
585 }
586
587
588
589
590
591
592
593
594 @Override
595 public Collection<V> values() {
596 return new SingletonValues<>(this);
597 }
598
599 }