1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.bidimap;
18
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.ObjectOutputStream;
22 import java.io.Serializable;
23 import java.util.ArrayList;
24 import java.util.Comparator;
25 import java.util.Iterator;
26 import java.util.ListIterator;
27 import java.util.Map;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30
31 import org.apache.commons.collections4.BidiMap;
32 import org.apache.commons.collections4.OrderedBidiMap;
33 import org.apache.commons.collections4.OrderedMap;
34 import org.apache.commons.collections4.OrderedMapIterator;
35 import org.apache.commons.collections4.ResettableIterator;
36 import org.apache.commons.collections4.SortedBidiMap;
37 import org.apache.commons.collections4.map.AbstractSortedMapDecorator;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class DualTreeBidiMap<K, V> extends AbstractDualBidiMap<K, V>
60 implements SortedBidiMap<K, V>, Serializable {
61
62
63
64
65
66
67
68 protected static class BidiOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
69
70
71 private final AbstractDualBidiMap<K, V> parent;
72
73
74 private ListIterator<Map.Entry<K, V>> iterator;
75
76
77 private Map.Entry<K, V> last;
78
79
80
81
82
83
84 protected BidiOrderedMapIterator(final AbstractDualBidiMap<K, V> parent) {
85 this.parent = parent;
86 iterator = new ArrayList<>(parent.entrySet()).listIterator();
87 }
88
89 @Override
90 public K getKey() {
91 if (last == null) {
92 throw new IllegalStateException(
93 "Iterator getKey() can only be called after next() and before remove()");
94 }
95 return last.getKey();
96 }
97
98 @Override
99 public V getValue() {
100 if (last == null) {
101 throw new IllegalStateException(
102 "Iterator getValue() can only be called after next() and before remove()");
103 }
104 return last.getValue();
105 }
106
107 @Override
108 public boolean hasNext() {
109 return iterator.hasNext();
110 }
111
112 @Override
113 public boolean hasPrevious() {
114 return iterator.hasPrevious();
115 }
116
117 @Override
118 public K next() {
119 last = iterator.next();
120 return last.getKey();
121 }
122
123 @Override
124 public K previous() {
125 last = iterator.previous();
126 return last.getKey();
127 }
128
129 @Override
130 public void remove() {
131 iterator.remove();
132 parent.remove(last.getKey());
133 last = null;
134 }
135
136 @Override
137 public void reset() {
138 iterator = new ArrayList<>(parent.entrySet()).listIterator();
139 last = null;
140 }
141
142 @Override
143 public V setValue(final V value) {
144 if (last == null) {
145 throw new IllegalStateException(
146 "Iterator setValue() can only be called after next() and before remove()");
147 }
148 if (parent.reverseMap.containsKey(value) &&
149 parent.reverseMap.get(value) != last.getKey()) {
150 throw new IllegalArgumentException(
151 "Cannot use setValue() when the object being set is already in the map");
152 }
153 final V oldValue = parent.put(last.getKey(), value);
154
155
156 last.setValue(value);
157 return oldValue;
158 }
159
160 @Override
161 public String toString() {
162 if (last != null) {
163 return "MapIterator[" + getKey() + "=" + getValue() + "]";
164 }
165 return "MapIterator[]";
166 }
167 }
168
169
170
171
172
173
174
175 protected static class ViewMap<K, V> extends AbstractSortedMapDecorator<K, V> {
176
177
178
179
180
181
182
183 protected ViewMap(final DualTreeBidiMap<K, V> bidi, final SortedMap<K, V> sm) {
184
185
186
187 super(new DualTreeBidiMap<>(sm, bidi.reverseMap, bidi.inverseBidiMap));
188 }
189
190 @Override
191 public void clear() {
192
193 for (final Iterator<K> it = keySet().iterator(); it.hasNext();) {
194 it.next();
195 it.remove();
196 }
197 }
198
199 @Override
200 public boolean containsValue(final Object value) {
201
202 return decorated().normalMap.containsValue(value);
203 }
204
205 @Override
206 protected DualTreeBidiMap<K, V> decorated() {
207 return (DualTreeBidiMap<K, V>) super.decorated();
208 }
209
210 @Override
211 public SortedMap<K, V> headMap(final K toKey) {
212 return new ViewMap<>(decorated(), super.headMap(toKey));
213 }
214
215 @Override
216 public K nextKey(final K key) {
217 return decorated().nextKey(key);
218 }
219
220 @Override
221 public K previousKey(final K key) {
222 return decorated().previousKey(key);
223 }
224
225 @Override
226 public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
227 return new ViewMap<>(decorated(), super.subMap(fromKey, toKey));
228 }
229
230 @Override
231 public SortedMap<K, V> tailMap(final K fromKey) {
232 return new ViewMap<>(decorated(), super.tailMap(fromKey));
233 }
234 }
235
236
237 private static final long serialVersionUID = 721969328361809L;
238
239
240 private final Comparator<? super K> comparator;
241
242
243 private final Comparator<? super V> valueComparator;
244
245
246
247
248 public DualTreeBidiMap() {
249 super(new TreeMap<>(), new TreeMap<>());
250 this.comparator = null;
251 this.valueComparator = null;
252 }
253
254
255
256
257
258
259
260 public DualTreeBidiMap(final Comparator<? super K> keyComparator, final Comparator<? super V> valueComparator) {
261 super(new TreeMap<>(keyComparator), new TreeMap<>(valueComparator));
262 this.comparator = keyComparator;
263 this.valueComparator = valueComparator;
264 }
265
266
267
268
269
270
271
272 public DualTreeBidiMap(final Map<? extends K, ? extends V> map) {
273 super(new TreeMap<>(), new TreeMap<>());
274 putAll(map);
275 this.comparator = null;
276 this.valueComparator = null;
277 }
278
279
280
281
282
283
284
285
286 protected DualTreeBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap,
287 final BidiMap<V, K> inverseBidiMap) {
288 super(normalMap, reverseMap, inverseBidiMap);
289 this.comparator = ((SortedMap<K, V>) normalMap).comparator();
290 this.valueComparator = ((SortedMap<V, K>) reverseMap).comparator();
291 }
292
293 @Override
294 public Comparator<? super K> comparator() {
295 return ((SortedMap<K, V>) normalMap).comparator();
296 }
297
298
299
300
301
302
303
304
305
306 @Override
307 protected DualTreeBidiMap<V, K> createBidiMap(final Map<V, K> normalMap, final Map<K, V> reverseMap,
308 final BidiMap<K, V> inverseMap) {
309 return new DualTreeBidiMap<>(normalMap, reverseMap, inverseMap);
310 }
311
312 @Override
313 public K firstKey() {
314 return ((SortedMap<K, V>) normalMap).firstKey();
315 }
316
317 @Override
318 public SortedMap<K, V> headMap(final K toKey) {
319 final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).headMap(toKey);
320 return new ViewMap<>(this, sub);
321 }
322
323 @Override
324 public SortedBidiMap<V, K> inverseBidiMap() {
325 return (SortedBidiMap<V, K>) super.inverseBidiMap();
326 }
327
328
329
330
331
332
333 public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
334 return inverseBidiMap();
335 }
336
337
338
339
340
341
342 public SortedBidiMap<V, K> inverseSortedBidiMap() {
343 return inverseBidiMap();
344 }
345
346 @Override
347 public K lastKey() {
348 return ((SortedMap<K, V>) normalMap).lastKey();
349 }
350
351
352
353
354
355
356
357
358
359
360 @Override
361 public OrderedMapIterator<K, V> mapIterator() {
362 return new BidiOrderedMapIterator<>(this);
363 }
364
365 @Override
366 public K nextKey(final K key) {
367 if (isEmpty()) {
368 return null;
369 }
370 if (normalMap instanceof OrderedMap) {
371 return ((OrderedMap<K, ?>) normalMap).nextKey(key);
372 }
373 final SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
374 final Iterator<K> it = sm.tailMap(key).keySet().iterator();
375 it.next();
376 if (it.hasNext()) {
377 return it.next();
378 }
379 return null;
380 }
381
382 @Override
383 public K previousKey(final K key) {
384 if (isEmpty()) {
385 return null;
386 }
387 if (normalMap instanceof OrderedMap) {
388 return ((OrderedMap<K, V>) normalMap).previousKey(key);
389 }
390 final SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
391 final SortedMap<K, V> hm = sm.headMap(key);
392 if (hm.isEmpty()) {
393 return null;
394 }
395 return hm.lastKey();
396 }
397
398
399
400
401
402
403
404
405 private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
406 in.defaultReadObject();
407 normalMap = new TreeMap<>(comparator);
408 reverseMap = new TreeMap<>(valueComparator);
409 @SuppressWarnings("unchecked")
410 final Map<K, V> map = (Map<K, V>) in.readObject();
411 putAll(map);
412 }
413
414 @Override
415 public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
416 final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).subMap(fromKey, toKey);
417 return new ViewMap<>(this, sub);
418 }
419
420 @Override
421 public SortedMap<K, V> tailMap(final K fromKey) {
422 final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).tailMap(fromKey);
423 return new ViewMap<>(this, sub);
424 }
425
426 @Override
427 public Comparator<? super V> valueComparator() {
428 return ((SortedMap<V, K>) reverseMap).comparator();
429 }
430
431
432
433
434
435
436
437 private void writeObject(final ObjectOutputStream out) throws IOException {
438 out.defaultWriteObject();
439 out.writeObject(normalMap);
440 }
441
442 }