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