1 /* Taken 2008 from Limewire-project under the following terms:
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16 package net.sf.eos.trie;
17
18 import java.io.Serializable;
19 import java.util.AbstractCollection;
20 import java.util.AbstractMap;
21 import java.util.AbstractSet;
22 import java.util.Collection;
23 import java.util.Comparator;
24 import java.util.ConcurrentModificationException;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.NoSuchElementException;
28 import java.util.Set;
29 import java.util.SortedMap;
30
31 /**
32 * A PATRICIA Trie.
33 * <p>
34 * PATRICIA = Practical Algorithm to Retrieve Information Coded in Alphanumeric
35 * <p>
36 * A PATRICIA Trie is a compressed Trie. Instead of storing all data at the
37 * edges of the Trie (and having empty internal nodes), PATRICIA stores data
38 * in every node. This allows for very efficient traversal, insert, delete,
39 * predecessor, successor, prefix, range, and 'select' operations. All operations
40 * are performed at worst in O(K) time, where K is the number of bits in the
41 * largest item in the tree. In practice, operations actually take O(A(K))
42 * time, where A(K) is the average number of bits of all items in the tree.
43 * <p>
44 * Most importantly, PATRICIA requires very few comparisons to keys while
45 * doing any operation. While performing a lookup, each comparison
46 * (at most K of them, described above) will perform a single bit comparison
47 * against the given key, instead of comparing the entire key to another key.
48 * <p>
49 * The Trie can return operations in lexicographical order using the 'traverse',
50 * 'prefix', 'submap', or 'iterator' methods. The Trie can also scan for items
51 * that are 'bitwise' (using an XOR metric) by the 'select' method. Bitwise
52 * closeness is determined by the {@link KeyAnalyzer} returning true or
53 * false for a bit being set or not in a given key.
54 * <p>
55 * This PATRICIA Trie supports both variable length & fixed length keys.
56 * Some methods, such as <code>getPrefixedBy(...)</code> are suited only to
57 * variable length keys, whereas <code>getPrefixedByBits(...)</code> is suited
58 * to fixed-size keys.
59 * <p>
60 * Additionally see <a
61 * href="http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/PATRICIA/">PATRICIA</a>
62 * for more information.
63 * <p>
64 * Any methods here that take an <code>Object</code> may throw a
65 * <code>ClassCastException<code> if the method is expecting an instance of K
66 * (and it isn't K).
67 *
68 * <pre>
69 PatriciaTrie<String, String> trie = new PatriciaTrie<String, String>
70 (new CharSequenceKeyAnalyzer());
71
72 trie.put("Lime", "Lime");
73 trie.put("LimeWire", "LimeWire");
74 trie.put("LimeRadio", "LimeRadio");
75 trie.put("Lax", "Lax");
76 trie.put("Lake", "Lake");
77 trie.put("Lovely", "Lovely");
78
79 System.out.println(trie.select("Lo"));
80 System.out.println(trie.select("Lime"));
81
82 System.out.println(trie.getPrefixedBy("La").toString());
83
84 Output:
85 Lovely
86 Lime
87 {Lake=Lake, Lax=Lax}
88
89 * </pre>
90 * <p><strong>Note:</strong> Taken from
91 * <a href='http://www.limewire.org/'>Limewire</a> sourcecode and repackaged by
92 * Sascha Kohlmann.</p>
93 * @author Roger Kapsi
94 * @author Sam Berlin
95 */
96 public class PatriciaTrie<K, V> extends AbstractMap<K, V>
97 implements Trie<K, V>, Serializable {
98
99 private static final long serialVersionUID = 110232526181493307L;
100
101 /** The root element of the Trie. */
102 private final TrieEntry<K, V> root = new TrieEntry<K, V>(null, null, -1);
103
104 /** The current size (total number of elements) of the Trie. */
105 private int size = 0;
106
107 /** The number of times this has been modified (to fail-fast the iterators). */
108 private transient int modCount = 0;
109
110 /** The keyAnalyzer used to analyze bit values of keys. */
111 private final KeyAnalyzer<? super K> keyAnalyzer;
112
113 /** Constructs a new PatriciaTrie using the given keyAnalyzer. */
114 public PatriciaTrie(KeyAnalyzer<? super K> keyAnalyzer) {
115 this.keyAnalyzer = keyAnalyzer;
116 }
117
118 /** Returns the KeyAnalyzer that constructed the trie. */
119 public KeyAnalyzer<? super K> getKeyAnalyzer() {
120 return keyAnalyzer;
121 }
122
123 /** Returns the KeyAnalyzer as a comparator. */
124 public Comparator<? super K> comparator() {
125 return keyAnalyzer;
126 }
127
128 /** Clears the Trie (i.e. removes all elements). */
129 @Override
130 public void clear() {
131 root.key = null;
132 root.bitIndex = -1;
133 root.value = null;
134
135 root.parent = null;
136 root.left = root;
137 root.right = null;
138 root.predecessor = root;
139
140 size = 0;
141 incrementModCount();
142 }
143
144 /** Returns true if the Trie is empty */
145 @Override
146 public boolean isEmpty() {
147 return size == 0;
148 }
149
150 /** Returns the number items in the Trie */
151 @Override
152 public int size() {
153 return size;
154 }
155
156 /** Increments both the size and mod counter. */
157 private void incrementSize() {
158 size++;
159 incrementModCount();
160 }
161
162 /** Decrements the size and increments the mod counter. */
163 private void decrementSize() {
164 size--;
165 incrementModCount();
166 }
167
168 /** Increments the mod counter. */
169 private void incrementModCount() {
170 modCount++;
171 }
172
173 /**
174 * Adds a new <key, value> pair to the Trie and if a pair already
175 * exists it will be replaced. In the latter case it will return
176 * the old value.
177 */
178 @Override
179 public V put(K key, V value) {
180 if (key == null) {
181 throw new NullPointerException("Key cannot be null");
182 }
183
184 int keyLength = length(key);
185
186 // The only place to store a key with a length
187 // of zero bits is the root node
188 if (keyLength == 0) {
189 if (root.isEmpty()) {
190 incrementSize();
191 } else {
192 incrementModCount();
193 }
194 return root.setKeyValue(key, value);
195 }
196
197 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
198 if (key.equals(found.key)) {
199 if (found.isEmpty()) { // <- must be the root
200 incrementSize();
201 } else {
202 incrementModCount();
203 }
204 return found.setKeyValue(key, value);
205 }
206
207 int bitIndex = bitIndex(key, found.key);
208 if (isValidBitIndex(bitIndex)) { // in 99.999...9% the case
209 /* NEW KEY+VALUE TUPLE */
210 TrieEntry<K, V> t = new TrieEntry<K, V>(key, value, bitIndex);
211 addEntry(t, keyLength);
212 incrementSize();
213 return null;
214 } else if (isNullBitKey(bitIndex)) {
215 // A bits of the Key are zero. The only place to
216 // store such a Key is the root Node!
217
218 /* NULL BIT KEY */
219 if (root.isEmpty()) {
220 incrementSize();
221 } else {
222 incrementModCount();
223 }
224 return root.setKeyValue(key, value);
225
226 } else if (isEqualBitKey(bitIndex)) {
227 // This is a very special and rare case.
228
229 /* REPLACE OLD KEY+VALUE */
230 if (found != root) {
231 incrementModCount();
232 return found.setKeyValue(key, value);
233 }
234 }
235
236 throw new IndexOutOfBoundsException("Failed to put: " + key
237 + " -> " + value
238 + ", " + bitIndex);
239 }
240
241 /** Adds the given entry into the Trie. */
242 private TrieEntry<K, V> addEntry(TrieEntry<K, V> toAdd, int keyLength) {
243 TrieEntry<K, V> current = root.left;
244 TrieEntry<K, V> path = root;
245 while(true) {
246 if(current.bitIndex >= toAdd.bitIndex || current.bitIndex <= path.bitIndex) {
247 toAdd.predecessor = toAdd;
248
249 if (!isBitSet(toAdd.key, keyLength, toAdd.bitIndex)) {
250 toAdd.left = toAdd;
251 toAdd.right = current;
252 } else {
253 toAdd.left = current;
254 toAdd.right = toAdd;
255 }
256
257 toAdd.parent = path;
258 if (current.bitIndex >= toAdd.bitIndex) {
259 current.parent = toAdd;
260 }
261
262 // if we inserted an uplink, set the predecessor on it
263 if(current.bitIndex <= path.bitIndex) {
264 current.predecessor = toAdd;
265 }
266
267 if (path == root || !isBitSet(toAdd.key, keyLength, path.bitIndex))
268 path.left = toAdd;
269 else
270 path.right = toAdd;
271 return toAdd;
272 }
273
274 path = current;
275 if(!isBitSet(toAdd.key, keyLength, current.bitIndex))
276 current = current.left;
277 else
278 current = current.right;
279 }
280 }
281
282 @Override
283 public Set<Map.Entry<K,V>> entrySet() {
284 Set<Map.Entry<K,V>> es = entrySet;
285 return (es != null ? es : (entrySet = new EntrySet()));
286 }
287
288 /**
289 * Returns the Value whose Key equals our lookup Key
290 * or null if no such key exists.
291 */
292 @Override
293 public V get(Object k) {
294 TrieEntry<K, V> entry = getEntry(k);
295 return entry != null ? entry.getValue() : null;
296 }
297
298 /**
299 * Returns the entry associated with the specified key in the
300 * PatriciaTrie. Returns null if the map contains no mapping
301 * for this key.
302 *
303 * This may throw ClassCastException if the object is not of type K.
304 */
305 TrieEntry<K,V> getEntry(Object k) {
306 K key = asKey(k);
307 if(key == null)
308 return null;
309
310 int keyLength = length(key);
311 TrieEntry<K,V> entry = getNearestEntryForKey(key, keyLength);
312 return !entry.isEmpty() && key.equals(entry.key) ? entry : null;
313 }
314
315 /** Gets the key as a 'K'. */
316 @SuppressWarnings("unchecked")
317 protected final K asKey(Object key) {
318 try {
319 return (K)key;
320 } catch(ClassCastException cce) {
321 // Because the type is erased, the cast & return are
322 // actually doing nothing, making this CCE impossible.
323 // However, it's still here on the off-chance it may
324 // work.
325 return null;
326 }
327 }
328
329 /**
330 * Returns the nearest entry for a given key. This is useful
331 * for finding knowing if a given key exists (and finding the value
332 * for it), or for inserting the key.
333 *
334 * The actual get implementation. This is very similar to
335 * selectR but with the exception that it might return the
336 * root Entry even if it's empty.
337 */
338 private TrieEntry<K, V> getNearestEntryForKey(K key, int keyLength) {
339 TrieEntry<K, V> current = root.left;
340 TrieEntry<K, V> path = root;
341 while(true) {
342 if(current.bitIndex <= path.bitIndex)
343 return current;
344
345 path = current;
346 if(!isBitSet(key, keyLength, current.bitIndex))
347 current = current.left;
348 else
349 current = current.right;
350 }
351 }
352
353 /**
354 * Returns the Value whose Key has the longest prefix
355 * in common with our lookup key.
356 */
357 @SuppressWarnings("unchecked")
358 public V select(K key) {
359 int keyLength = length(key);
360 TrieEntry[] result = new TrieEntry[1];
361 if (!selectR(root.left, -1, key, keyLength, result)) {
362 TrieEntry<K, V> e = result[0];
363 return e.getValue();
364 }
365 return null;
366 }
367
368 /**
369 * This is equivalent to the other selectR() method but without
370 * its overhead because we're selecting only one best matching
371 * Entry from the Trie.
372 */
373 private boolean selectR(TrieEntry<K, V> h, int bitIndex,
374 final K key, final int keyLength, final TrieEntry[] result) {
375
376 if (h.bitIndex <= bitIndex) {
377 // If we hit the root Node and it is empty
378 // we have to look for an alternative best
379 // matching node.
380 if (!h.isEmpty()) {
381 result[0] = h;
382 return false;
383 }
384 return true;
385 }
386
387 if (!isBitSet(key, keyLength, h.bitIndex)) {
388 if (selectR(h.left, h.bitIndex, key, keyLength, result)) {
389 return selectR(h.right, h.bitIndex, key, keyLength, result);
390 }
391 } else {
392 if (selectR(h.right, h.bitIndex, key, keyLength, result)) {
393 return selectR(h.left, h.bitIndex, key, keyLength, result);
394 }
395 }
396 return false;
397 }
398
399 @SuppressWarnings("unchecked")
400 public Map.Entry<K,V> select(K key, Cursor<? super K, ? super V> cursor) {
401 int keyLength = length(key);
402 TrieEntry[] result = new TrieEntry[]{ null };
403 selectR(root.left, -1, key, keyLength, cursor, result);
404 return result[0];
405 }
406
407 private boolean selectR(TrieEntry<K,V> h, int bitIndex,
408 final K key,
409 final int keyLength,
410 final Cursor<? super K, ? super V> cursor,
411 final TrieEntry[] result) {
412
413 if (h.bitIndex <= bitIndex) {
414 if(!h.isEmpty()) {
415 Cursor.SelectStatus ret = cursor.select(h);
416 switch(ret) {
417 case REMOVE:
418 throw new UnsupportedOperationException("cannot remove during select");
419 case EXIT:
420 result[0] = h;
421 return false; // exit
422 case REMOVE_AND_EXIT:
423 TrieEntry<K, V> entry = new TrieEntry<K, V>(h.getKey(), h.getValue(), -1);
424 result[0] = entry;
425 removeEntry(h);
426 return false;
427 case CONTINUE:
428 // fall through.
429 }
430 }
431 return true; // continue
432 }
433
434 if (!isBitSet(key, keyLength, h.bitIndex)) {
435 if (selectR(h.left, h.bitIndex, key, keyLength, cursor, result)) {
436 return selectR(h.right, h.bitIndex, key, keyLength, cursor, result);
437 }
438 } else {
439 if (selectR(h.right, h.bitIndex, key, keyLength, cursor, result)) {
440 return selectR(h.left, h.bitIndex, key, keyLength, cursor, result);
441 }
442 }
443
444 return false;
445 }
446
447 /**
448 * Returns a view of this Trie of all elements that are
449 * prefixed by the given key.
450 *
451 * In a fixed-keysize Trie, this is essentially a 'get' operation.
452 *
453 * For example, if the trie contains 'Lime', 'LimeWire',
454 * 'LimeRadio', 'Lax', 'Later', 'Lake', and 'Lovely', then
455 * a lookup of 'Lime' would return 'Lime', 'LimeRadio', and 'LimeWire'.
456 *
457 * The view that this returns is optimized to have a very efficient
458 * Iterator. The firstKey, lastKey & size methods must iterate
459 * over all possible values in order to determine the results. This
460 * information is cached until the Patricia tree changes. All other
461 * methods (except Iterator) must compare the given key to the prefix
462 * to ensure that it is within the range of the view. The Iterator's
463 * remove method must also relocate the subtree that contains the
464 * prefixes if the entry holding the subtree is removed or changes.
465 * Changing the subtree takes O(K) time.
466 *
467 * @param key
468 */
469 public SortedMap<K, V> getPrefixedBy(K key) {
470 return getPrefixedByBits(key, 0, keyAnalyzer.length(key));
471 }
472
473 /**
474 * Returns a view of this Trie of all elements that are
475 * prefixed by the length of the key.
476 *
477 * Fixed-keysize Tries will not support this operation
478 * (because all keys will be the same length).
479 *
480 * For example, if the trie contains 'Lime', 'LimeWire',
481 * 'LimeRadio', 'Lax', 'Later', 'Lake', and 'Lovely', then
482 * a lookup of 'LimePlastics' with a length of 4 would
483 * return 'Lime', 'LimeRadio', and 'LimeWire'.
484 *
485 * The view that this returns is optimized to have a very efficient
486 * Iterator. The firstKey, lastKey & size methods must iterate
487 * over all possible values in order to determine the results. This
488 * information is cached until the Patricia tree changes. All other
489 * methods (except Iterator) must compare the given key to the prefix
490 * to ensure that it is within the range of the view. The Iterator's
491 * remove method must also relocate the subtree that contains the
492 * prefixes if the entry holding the subtree is removed or changes.
493 * Changing the subtree takes O(K) time.
494 *
495 * @param key
496 * @param length
497 */
498 public SortedMap<K, V> getPrefixedBy(K key, int length) {
499 return getPrefixedByBits(key, 0, length * keyAnalyzer.bitsPerElement());
500 }
501
502 /**
503 * Returns a view of this Trie of all elements that are prefixed
504 * by the key, starting at the given offset and for the given length.
505 *
506 * Fixed-keysize Tries will not support this operation
507 * (because all keys are the same length).
508 *
509 * For example, if the trie contains 'Lime', 'LimeWire',
510 * 'LimeRadio', 'Lax', 'Later', 'Lake', and 'Lovely', then
511 * a lookup of 'The Lime Plastics' with an offset of 4 and a
512 * length of 4 would return 'Lime', 'LimeRadio', and 'LimeWire'.
513 *
514 * The view that this returns is optimized to have a very efficient
515 * Iterator. The firstKey, lastKey & size methods must iterate
516 * over all possible values in order to determine the results. This
517 * information is cached until the Patricia tree changes. All other
518 * methods (except Iterator) must compare the given key to the prefix
519 * to ensure that it is within the range of the view. The Iterator's
520 * remove method must also relocate the subtree that contains the
521 * prefixes if the entry holding the subtree is removed or changes.
522 * Changing the subtree takes O(K) time.
523 *
524 * @param key
525 * @param offset
526 * @param length
527 */
528 public SortedMap<K, V> getPrefixedBy(K key, int offset, int length) {
529 return getPrefixedByBits(key, offset * keyAnalyzer.bitsPerElement(), length * keyAnalyzer.bitsPerElement());
530 }
531
532 /**
533 * Returns a view of this Trie of all elements that are prefixed
534 * by the number of bits in the given Key.
535 *
536 * Fixed-keysize Tries can support this operation as a way to do
537 * lookups of partial keys. That is, if the Trie is storing IP
538 * addresses, you can lookup all addresses that begin with
539 * '192.168' by providing the key '192.168.X.X' and a length of 16
540 * would return all addresses that begin with '192.168'.
541 *
542 * The view that this returns is optimized to have a very efficient
543 * Iterator. The firstKey, lastKey & size methods must iterate
544 * over all possible values in order to determine the results. This
545 * information is cached until the Patricia tree changes. All other
546 * methods (except Iterator) must compare the given key to the prefix
547 * to ensure that it is within the range of the view. The Iterator's
548 * remove method must also relocate the subtree that contains the
549 * prefixes if the entry holding the subtree is removed or changes.
550 * Changing the subtree takes O(K) time.
551 *
552 * @param key
553 * @param bitLength
554 */
555 public SortedMap<K, V> getPrefixedByBits(K key, int bitLength) {
556 return getPrefixedByBits(key, 0, bitLength);
557 }
558
559 /**
560 * Returns a view of this map, with entries containing only those that
561 * are prefixed by a value whose bits matches the bits between 'offset'
562 * and 'length' in the given key.
563 *
564 * The view that this returns is optimized to have a very efficient
565 * Iterator. The firstKey, lastKey & size methods must iterate
566 * over all possible values in order to determine the results. This
567 * information is cached until the Patricia tree changes. All other
568 * methods (except Iterator) must compare the given key to the prefix
569 * to ensure that it is within the range of the view. The Iterator's
570 * remove method must also relocate the subtree that contains the
571 * prefixes if the entry holding the subtree is removed or changes.
572 * Changing the subtree takes O(K) time.
573 *
574 * @param key
575 * @param offset
576 * @param length
577 */
578 private SortedMap<K, V> getPrefixedByBits(K key, int offset, int length) {
579 int offsetLength = offset + length;
580 if (offsetLength > length(key)) {
581 throw new IllegalArgumentException(offset + " + " + length + " > " + length(key));
582 }
583
584 if(offsetLength == 0)
585 return this;
586
587 return new PrefixSubMap(key, offset, length);
588 }
589
590 /**
591 * Returns true if this trie contains the specified Key
592 *
593 * This may throw ClassCastException if the object is not
594 * of type K.
595 */
596 @Override
597 public boolean containsKey(Object k) {
598 K key = asKey(k);
599 if(key == null)
600 return false;
601
602 int keyLength = length(key);
603 TrieEntry entry = getNearestEntryForKey(key, keyLength);
604 return !entry.isEmpty() && key.equals(entry.key);
605 }
606
607 /** Returns true if this Trie contains the specified value. */
608 @Override
609 public boolean containsValue(Object o) {
610 for(V v : values())
611 if(valEquals(v, o))
612 return true;
613 return false;
614 }
615
616 /**
617 * Removes a Key from the Trie if one exists
618 *
619 * This may throw ClassCastException if the object is not of type K.
620 *
621 * @param k the Key to delete
622 * @return Returns the deleted Value
623 */
624 @Override
625 public V remove(Object k) {
626 K key = asKey(k);
627 if(key == null)
628 return null;
629
630 int keyLength = length(key);
631 TrieEntry<K, V> current = root.left;
632 TrieEntry<K, V> path = root;
633 while(true) {
634 if(current.bitIndex <= path.bitIndex) {
635 if(!current.isEmpty() && key.equals(current.key)) {
636 return removeEntry(current);
637 }
638 return null;
639 }
640
641 path = current;
642 if(!isBitSet(key, keyLength, current.bitIndex))
643 current = current.left;
644 else
645 current = current.right;
646 }
647 }
648
649 /**
650 * Removes a single entry from the Trie.
651 *
652 * If we found a Key (Entry h) then figure out if it's
653 * an internal (hard to remove) or external Entry (easy
654 * to remove)
655 */
656 private V removeEntry(TrieEntry<K, V> h) {
657 if (h != root) {
658 if (h.isInternalNode()) {
659 removeInternalEntry(h);
660 } else {
661 removeExternalEntry(h);
662 }
663 }
664
665 decrementSize();
666 return h.setKeyValue(null, null);
667 }
668
669 /**
670 * Removes an external entry from the Trie.
671 *
672 * If it's an external Entry then just remove it.
673 * This is very easy and straight forward.
674 */
675 private void removeExternalEntry(TrieEntry<K, V> h) {
676 if (h == root) {
677 throw new IllegalArgumentException("Cannot delete root Entry!");
678 } else if (!h.isExternalNode()) {
679 throw new IllegalArgumentException(h + " is not an external Entry!");
680 }
681
682 TrieEntry<K, V> parent = h.parent;
683 TrieEntry<K, V> child = (h.left == h) ? h.right : h.left;
684
685 if (parent.left == h) {
686 parent.left = child;
687 } else {
688 parent.right = child;
689 }
690
691 // either the parent is changing, or the predecessor is changing.
692 if (child.bitIndex > parent.bitIndex) {
693 child.parent = parent;
694 } else {
695 child.predecessor = parent;
696 }
697
698 }
699
700 /**
701 * Removes an internal entry from the Trie.
702 *
703 * If it's an internal Entry then "good luck" with understanding
704 * this code. The Idea is essentially that Entry p takes Entry h's
705 * place in the trie which requires some re-wiring.
706 */
707 private void removeInternalEntry(TrieEntry<K, V> h) {
708 if (h == root) {
709 throw new IllegalArgumentException("Cannot delete root Entry!");
710 } else if (!h.isInternalNode()) {
711 throw new IllegalArgumentException(h + " is not an internal Entry!");
712 }
713
714 TrieEntry<K, V> p = h.predecessor;
715
716 // Set P's bitIndex
717 p.bitIndex = h.bitIndex;
718
719 // Fix P's parent, predecessor and child Nodes
720 {
721 TrieEntry<K, V> parent = p.parent;
722 TrieEntry<K, V> child = (p.left == h) ? p.right : p.left;
723
724 // if it was looping to itself previously,
725 // it will now be pointed from it's parent
726 // (if we aren't removing it's parent --
727 // in that case, it remains looping to itself).
728 // otherwise, it will continue to have the same
729 // predecessor.
730 if(p.predecessor == p && p.parent != h)
731 p.predecessor = p.parent;
732
733 if (parent.left == p) {
734 parent.left = child;
735 } else {
736 parent.right = child;
737 }
738
739 if (child.bitIndex > parent.bitIndex) {
740 child.parent = parent;
741 }
742 };
743
744 // Fix H's parent and child Nodes
745 {
746 // If H is a parent of its left and right child
747 // then change them to P
748 if (h.left.parent == h) {
749 h.left.parent = p;
750 }
751
752 if (h.right.parent == h) {
753 h.right.parent = p;
754 }
755
756 // Change H's parent
757 if (h.parent.left == h) {
758 h.parent.left = p;
759 } else {
760 h.parent.right = p;
761 }
762 };
763
764 // Copy the remaining fields from H to P
765 //p.bitIndex = h.bitIndex;
766 p.parent = h.parent;
767 p.left = h.left;
768 p.right = h.right;
769
770 // Make sure that if h was pointing to any uplinks,
771 // p now points to them.
772 if(isValidUplink(p.left, p))
773 p.left.predecessor = p;
774 if(isValidUplink(p.right, p))
775 p.right.predecessor = p;
776
777 }
778
779 /**
780 * Returns the node lexicographically before the given node (or null if none).
781 *
782 * This follows four simple branches:
783 * - If the uplink that returned us was a right uplink:
784 * - If predecessor's left is a valid uplink from predecessor, return it.
785 * - Else, follow the right path from the predecessor's left.
786 * - If the uplink that returned us was a left uplink:
787 * - Loop back through parents until we encounter a node where
788 * node != node.parent.left.
789 * - If node.parent.left is uplink from node.parent:
790 * - If node.parent.left is not root, return it.
791 * - If it is root & root isEmpty, return null.
792 * - If it is root & root !isEmpty, return root.
793 * - If node.parent.left is not uplink from node.parent:
794 * - Follow right path for first right child from node.parent.left
795 *
796 * @param start
797 */
798 private TrieEntry<K, V> previousEntry(TrieEntry<K, V> start) {
799 if(start.predecessor == null)
800 throw new IllegalArgumentException("must have come from somewhere!");
801
802 if(start.predecessor.right == start) {
803 if(isValidUplink(start.predecessor.left, start.predecessor)) {
804 return start.predecessor.left;
805 }
806 return followRight(start.predecessor.left);
807 }
808 TrieEntry<K, V> node = start.predecessor;
809 while(node.parent != null && node == node.parent.left)
810 node = node.parent;
811 if(node.parent == null) // can be null if we're looking up root.
812 return null;
813 if(isValidUplink(node.parent.left, node.parent)) {
814 if(node.parent.left == root) {
815 if(root.isEmpty()) {
816 return null;
817 }
818 return root;
819 }
820 return node.parent.left;
821 }
822 return followRight(node.parent.left);
823 }
824
825 /**
826 * Returns the entry lexicographically after the given entry.
827 * If the given entry is null, returns the first node.
828 */
829 private TrieEntry<K, V> nextEntry(TrieEntry<K, V> node) {
830 if(node == null) {
831 return firstEntry();
832 }
833 return nextEntryImpl(node.predecessor, node, null);
834 }
835
836 /**
837 * Returns the entry lexicographically after the given entry.
838 * If the given entry is null, returns the first node.
839 *
840 * This will traverse only within the subtree. If the given node
841 * is not within the subtree, this will have undefined results.
842 */
843 private TrieEntry<K, V> nextEntryInSubtree(
844 final TrieEntry<K, V> node,
845 final TrieEntry<K, V> parentOfSubtree) {
846 if(node == null) {
847 return firstEntry();
848 }
849 return nextEntryImpl(node.predecessor, node, parentOfSubtree);
850 }
851
852 /**
853 * Scans for the next node, starting at the specified point, and using 'previous'
854 * as a hint that the last node we returned was 'previous' (so we know not to return
855 * it again). If 'tree' is non-null, this will limit the search to the given tree.
856 *
857 * The basic premise is that each iteration can follow the following steps:
858 *
859 * 1) Scan all the way to the left.
860 * a) If we already started from this node last time, proceed to Step 2.
861 * b) If a valid uplink is found, use it.
862 * c) If the result is an empty node (root not set), break the scan.
863 * d) If we already returned the left node, break the scan.
864 *
865 * 2) Check the right.
866 * a) If we already returned the right node, proceed to Step 3.
867 * b) If it is a valid uplink, use it.
868 * c) Do Step 1 from the right node.
869 *
870 * 3) Back up through the parents until we encounter find a parent
871 * that we're not the right child of.
872 *
873 * 4) If there's no right child of that parent, the iteration is finished.
874 * Otherwise continue to Step 5.
875 *
876 * 5) Check to see if the right child is a valid uplink.
877 * a) If we already returned that child, proceed to Step 6.
878 * Otherwise, use it.
879 *
880 * 6) If the right child of the parent is the parent itself, we've
881 * already found & returned the end of the Trie, so exit.
882 *
883 * 7) Do Step 1 on the parent's right child.
884 */
885 private TrieEntry<K, V> nextEntryImpl(TrieEntry<K, V> start, TrieEntry<K, V> previous, TrieEntry<K, V> tree) {
886 TrieEntry<K, V> current = start;
887
888 // Only look at the left if this was a recursive or
889 // the first check, otherwise we know we've already looked
890 // at the left.
891 if(previous == null || start != previous.predecessor) {
892 while(!current.left.isEmpty()) {
893 // stop traversing if we've already
894 // returned the left of this node.
895 if(previous == current.left) {
896 break;
897 }
898
899 if(isValidUplink(current.left, current)) {
900 return current.left;
901 }
902
903 current = current.left;
904 }
905 }
906
907 // If there's no data at all, exit.
908 if(current.isEmpty()) {
909 return null;
910 }
911
912 // If we've already returned the left,
913 // and the immediate right is null,
914 // there's only one entry in the Trie
915 // which is stored at the root.
916 //
917 // / ("") <-- root
918 // \_/ \
919 // null <-- 'current'
920 //
921 if(current.right == null)
922 return null;
923
924 // If nothing valid on the left, try the right.
925 if(previous != current.right) {
926 // See if it immediately is valid.
927 if(isValidUplink(current.right, current)) {
928 return current.right;
929 }
930
931 // Must search on the right's side if it wasn't initially valid.
932 return nextEntryImpl(current.right, previous, tree);
933 }
934
935 // Neither left nor right are valid, find the first parent
936 // whose child did not come from the right & traverse it.
937 while(current == current.parent.right) {
938 // If we're going to traverse to above the subtree, stop.
939 if(current == tree)
940 return null;
941
942 current = current.parent;
943 }
944
945 // If we're on the top of the subtree, we can't go any higher.
946 if(current == tree)
947 return null;
948
949
950 // If there's no right, the parent must be root, so we're done.
951 if(current.parent.right == null) {
952 return null;
953 }
954
955
956 // If the parent's right points to itself, we've found one.
957 if(previous != current.parent.right && isValidUplink(current.parent.right, current.parent)) {
958 return current.parent.right;
959 }
960
961 // If the parent's right is itself, there can't be any more nodes.
962 if(current.parent.right == current.parent) {
963 return null;
964 }
965
966 // We need to traverse down the parent's right's path.
967 return nextEntryImpl(current.parent.right, previous, tree);
968 }
969
970 /** Returns each entry as a string. */
971 @Override
972 public String toString() {
973 StringBuilder buffer = new StringBuilder();
974 buffer.append("Trie[").append(size()).append("]={\n");
975 for(Iterator<Map.Entry<K, V>> i = newEntryIterator(); i.hasNext(); ) {
976 buffer.append(" ").append(i.next().toString()).append("\n");
977 }
978 buffer.append("}\n");
979 return buffer.toString();
980 }
981
982 public Map.Entry<K, V> traverse(Cursor<? super K, ? super V> cursor) {
983 TrieEntry<K, V> entry = nextEntry(null);
984 while(entry != null) {
985 TrieEntry<K, V> current = entry;
986 Cursor.SelectStatus ret = cursor.select(current);
987 entry = nextEntry(current);
988 switch(ret) {
989 case EXIT:
990 return current;
991 case REMOVE:
992 removeEntry(current);
993 break; // out of switch, stay in while loop
994 case REMOVE_AND_EXIT:
995 Map.Entry<K, V> value = new TrieEntry<K, V>(current.getKey(), current.getValue(), -1);
996 removeEntry(current);
997 return value;
998 case CONTINUE: // do nothing.
999 }
1000 }
1001
1002 return null;
1003 }
1004
1005 /** Returns true if 'next' is a valid uplink coming from 'from'. */
1006 private boolean isValidUplink(TrieEntry<K, V> next, TrieEntry<K, V> from) {
1007 return next != null && next.bitIndex <= from.bitIndex && !next.isEmpty();
1008 }
1009
1010 /** Returns true if bitIndex is a valid index */
1011 private static boolean isValidBitIndex(int bitIndex) {
1012 return 0 <= bitIndex && bitIndex <= Integer.MAX_VALUE;
1013 }
1014
1015 /** Returns true if bitIndex is a NULL_BIT_KEY */
1016 private static boolean isNullBitKey(int bitIndex) {
1017 return bitIndex == KeyAnalyzer.NULL_BIT_KEY;
1018 }
1019
1020 /** Returns true if bitIndex is a EQUAL_BIT_KEY */
1021 private static boolean isEqualBitKey(int bitIndex) {
1022 return bitIndex == KeyAnalyzer.EQUAL_BIT_KEY;
1023 }
1024
1025 /** Returns the length of the key, or 0 if the key is null. */
1026 private int length(K key) {
1027 if (key == null) {
1028 return 0;
1029 }
1030
1031 return keyAnalyzer.length(key);
1032 }
1033
1034 /**
1035 * Returns whether or not the given bit on the
1036 * key is set, or false if the key is null
1037 */
1038 private boolean isBitSet(K key, int keyLength, int bitIndex) {
1039 if (key == null) { // root's might be null!
1040 return false;
1041 }
1042 return keyAnalyzer.isBitSet(key, keyLength, bitIndex);
1043 }
1044
1045 /**
1046 * Utility method for calling
1047 * keyAnalyzer.bitIndex(key, 0, length(key), foundKey, 0, length(foundKey))
1048 */
1049 private int bitIndex(K key, K foundKey) {
1050 return keyAnalyzer.bitIndex(key, 0, length(key), foundKey, 0, length(foundKey));
1051 }
1052
1053 /** The actual Trie nodes. */
1054 private static class TrieEntry<K,V> implements Map.Entry<K,V>, Serializable {
1055
1056 private static final long serialVersionUID = 4596023148184140013L;
1057
1058 private K key;
1059 private V value;
1060
1061 /** The index this entry is comparing. */
1062 private int bitIndex;
1063
1064 /** The parent of this entry. */
1065 private TrieEntry<K,V> parent;
1066 /** The left child of this entry. */
1067 private TrieEntry<K,V> left;
1068 /** The right child of this entry. */
1069 private TrieEntry<K,V> right;
1070 /** The entry who uplinks to this entry. */
1071 private TrieEntry<K,V> predecessor;
1072
1073 private TrieEntry(K key, V value, int bitIndex) {
1074 this.key = key;
1075 this.value = value;
1076
1077 this.bitIndex = bitIndex;
1078
1079 this.parent = null;
1080 this.left = this;
1081 this.right = null;
1082 this.predecessor = this;
1083 }
1084
1085 @Override
1086 public boolean equals(Object o) {
1087 if(o == this) {
1088 return true;
1089 } else if(o instanceof Map.Entry) {
1090 Map.Entry e = (Map.Entry)o;
1091 Object k1 = getKey();
1092 Object k2 = e.getKey();
1093 if (k1 == k2 || (k1 != null && k1.equals(k2))) {
1094 Object v1 = getValue();
1095 Object v2 = e.getValue();
1096 if (v1 == v2 || (v1 != null && v1.equals(v2)))
1097 return true;
1098 }
1099 return false;
1100 } else {
1101 return false;
1102 }
1103 }
1104
1105 /**
1106 * Whether or not the entry is storing a key.
1107 * Only the root can potentially be empty, all other
1108 * nodes must have a key.
1109 */
1110 public boolean isEmpty() {
1111 return key == null;
1112 }
1113
1114 public K getKey() {
1115 return key;
1116 }
1117
1118 public V getValue() {
1119 return value;
1120 }
1121
1122 public V setValue(V value) {
1123 V o = this.value;
1124 this.value = value;
1125 return o;
1126 }
1127
1128 /**
1129 * Replaces the old key and value with the new ones.
1130 * Returns the old vlaue.
1131 */
1132 private V setKeyValue(K key, V value) {
1133 this.key = key;
1134 return setValue(value);
1135 }
1136
1137 /** Neither the left nor right child is a loopback */
1138 private boolean isInternalNode() {
1139 return left != this && right != this;
1140 }
1141
1142 /** Either the left or right child is a loopback */
1143 private boolean isExternalNode() {
1144 return !isInternalNode();
1145 }
1146
1147 @Override
1148 public String toString() {
1149 StringBuilder buffer = new StringBuilder();
1150
1151 if (bitIndex == -1) {
1152 buffer.append("RootEntry(");
1153 } else {
1154 buffer.append("Entry(");
1155 }
1156
1157 buffer.append("key=").append(getKey()).append(" [").append(bitIndex).append("], ");
1158 buffer.append("value=").append(getValue()).append(", ");
1159 //buffer.append("bitIndex=").append(bitIndex).append(", ");
1160
1161 if (parent != null) {
1162 if (parent.bitIndex == -1) {
1163 buffer.append("parent=").append("ROOT");
1164 } else {
1165 buffer.append("parent=").append(parent.getKey()).append(" [").append(parent.bitIndex).append("]");
1166 }
1167 } else {
1168 buffer.append("parent=").append("null");
1169 }
1170 buffer.append(", ");
1171
1172 if (left != null) {
1173 if (left.bitIndex == -1) {
1174 buffer.append("left=").append("ROOT");
1175 } else {
1176 buffer.append("left=").append(left.getKey()).append(" [").append(left.bitIndex).append("]");
1177 }
1178 } else {
1179 buffer.append("left=").append("null");
1180 }
1181 buffer.append(", ");
1182
1183 if (right != null) {
1184 if (right.bitIndex == -1) {
1185 buffer.append("right=").append("ROOT");
1186 } else {
1187 buffer.append("right=").append(right.getKey()).append(" [").append(right.bitIndex).append("]");
1188 }
1189 } else {
1190 buffer.append("right=").append("null");
1191 }
1192 buffer.append(", ");
1193
1194 if(predecessor != null) {
1195 if(predecessor.bitIndex == -1) {
1196 buffer.append("predecessor=").append("ROOT");
1197 } else {
1198 buffer.append("predecessor=").append(predecessor.getKey()).append(" [").append(predecessor.bitIndex).append("]");
1199 }
1200 }
1201
1202 buffer.append(")");
1203 return buffer.toString();
1204 }
1205 }
1206
1207 /**
1208 * Defines the interface to analyze {@link Trie} keys on a bit
1209 * level. <code>KeyAnalyzer</code>'s
1210 * methods return the length of the key in bits, whether or not a bit is
1211 * set, and bits per element in the key.
1212 * <p>
1213 * Additionally, a method determines if a key is a prefix of another key and
1214 * returns the bit index where one key is different from another key (if
1215 * the key and found key are equal than the return value is EQUAL_BIT_KEY).
1216 * <p>
1217 * <code>KeyAnalyzer</code> defines:<br>
1218 * <table cellspace="5">
1219 * <tr><td>NULL_BIT_KEY</td><td>When key's bits are all zero</td></tr>
1220 * <tr><td> EQUAL_BIT_KEY </td><td>When keys are the same </td></tr>
1221 * </table>
1222 */
1223 public static interface KeyAnalyzer<K> extends Comparator<K>, Serializable {
1224
1225 /** Returned by bitIndex if key's bits are all 0 */
1226 public static final int NULL_BIT_KEY = -1;
1227
1228 /**
1229 * Returned by bitIndex if key and found key are
1230 * equal. This is a very very specific case and
1231 * shouldn't happen on a regular basis
1232 */
1233 public static final int EQUAL_BIT_KEY = -2;
1234
1235 /**
1236 * Returns the length of the Key in bits.
1237 */
1238 public int length(K key);
1239
1240 /** Returns whether or not a bit is set */
1241 public boolean isBitSet(K key, int keyLength, int bitIndex);
1242
1243 /**
1244 * Returns the n-th different bit between key and found.
1245 * This starts the comparison in key at 'keyStart' and goes
1246 * for 'keyLength' bits, and compares to the found key
1247 * starting at 'foundStart' and going for 'foundLength' bits.
1248 */
1249 public int bitIndex(K key, int keyStart, int keyLength,
1250 K found, int foundStart, int foundLength);
1251
1252 /**
1253 * Returns the number of bits per element in the key.
1254 * This is only useful for variable-length keys, such as Strings.
1255 */
1256 public int bitsPerElement();
1257
1258 /**
1259 * Determines whether or not the given prefix (from offset to length)
1260 * is a prefix of the given key.
1261 */
1262 public boolean isPrefix(K prefix, int offset, int length, K key);
1263 }
1264
1265 /** An iterator that stores a single TrieEntry. */
1266 private class SingletonIterator implements Iterator<Map.Entry<K, V>> {
1267 private final TrieEntry<K, V> entry;
1268 private int hit = 0;
1269
1270 public SingletonIterator(TrieEntry<K, V> entry) {
1271 this.entry = entry;
1272 }
1273
1274 public boolean hasNext() {
1275 return hit == 0;
1276 }
1277
1278 public Map.Entry<K, V> next() {
1279 if(hit != 0)
1280 throw new NoSuchElementException();
1281 hit++;
1282 return entry;
1283 }
1284
1285 public void remove() {
1286 if(hit != 1)
1287 throw new IllegalStateException();
1288 hit++;
1289 PatriciaTrie.this.removeEntry(entry);
1290 }
1291
1292 }
1293
1294 /** An iterator for the entries. */
1295 private abstract class NodeIterator<E> implements Iterator<E> {
1296 protected int expectedModCount = modCount; // For fast-fail
1297 protected TrieEntry<K, V> next; // the next node to return
1298 protected TrieEntry<K, V> current; // the current entry we're on
1299
1300 // Starts iteration from the beginning.
1301 protected NodeIterator() {
1302 next = PatriciaTrie.this.nextEntry(null);
1303 }
1304
1305 // Starts iteration at the given entry.
1306 protected NodeIterator(TrieEntry<K, V> firstEntry) {
1307 next = firstEntry;
1308 }
1309
1310 public boolean hasNext() {
1311 return next != null;
1312 }
1313
1314 TrieEntry<K,V> nextEntry() {
1315 if (modCount != expectedModCount)
1316 throw new ConcurrentModificationException();
1317 TrieEntry<K,V> e = next;
1318 if (e == null)
1319 throw new NoSuchElementException();
1320
1321 next = findNext(e);
1322 current = e;
1323 return e;
1324 }
1325
1326 protected TrieEntry<K, V> findNext(TrieEntry<K, V> prior) {
1327 return PatriciaTrie.this.nextEntry(prior);
1328 }
1329
1330 public void remove() {
1331 if (current == null)
1332 throw new IllegalStateException();
1333 if (modCount != expectedModCount)
1334 throw new ConcurrentModificationException();
1335
1336 TrieEntry<K, V> node = current;
1337 current = null;
1338 PatriciaTrie.this.removeEntry(node);
1339
1340 expectedModCount = modCount;
1341 }
1342 }
1343
1344 private class ValueIterator extends NodeIterator<V> {
1345 public V next() {
1346 return nextEntry().value;
1347 }
1348 }
1349
1350 private class KeyIterator extends NodeIterator<K> {
1351 public K next() {
1352 return nextEntry().getKey();
1353 }
1354 }
1355
1356 private class EntryIterator extends NodeIterator<Map.Entry<K,V>> {
1357 public Map.Entry<K,V> next() {
1358 return nextEntry();
1359 }
1360 }
1361
1362 /** An iterator for iterating over a prefix search. */
1363 private class PrefixEntryIterator extends NodeIterator<Map.Entry<K, V>> {
1364 // values to reset the subtree if we remove it.
1365 protected final K prefix;
1366 protected final int offset;
1367 protected final int length;
1368 protected boolean lastOne;
1369
1370 protected TrieEntry<K, V> subtree; // the subtree to search within
1371
1372 // Starts iteration at the given entry & search only within the given subtree.
1373 PrefixEntryIterator(TrieEntry<K, V> startScan, K prefix, int offset, int length) {
1374 subtree = startScan;
1375 next = PatriciaTrie.this.followLeft(startScan);
1376 this.prefix = prefix;
1377 this.offset = offset;
1378 this.length = length;
1379 }
1380
1381 public Map.Entry<K,V> next() {
1382 Map.Entry<K, V> entry = nextEntry();
1383 if(lastOne)
1384 next = null;
1385 return entry;
1386 }
1387
1388 @Override
1389 protected TrieEntry<K, V> findNext(TrieEntry<K, V> prior) {
1390 return PatriciaTrie.this.nextEntryInSubtree(prior, subtree);
1391 }
1392
1393 @Override
1394 public void remove() {
1395 // If the current entry we're removing is the subtree
1396 // then we need to find a new subtree parent.
1397 boolean needsFixing = false;
1398 int bitIdx = subtree.bitIndex;
1399 if(current == subtree)
1400 needsFixing = true;
1401
1402 super.remove();
1403
1404 // If the subtree changed its bitIndex or we
1405 // removed the old subtree, get a new one.
1406 if(bitIdx != subtree.bitIndex || needsFixing)
1407 subtree = subtree(prefix, offset, length);
1408
1409 // If the subtree's bitIndex is less than the
1410 // length of our prefix, it's the last item
1411 // in the prefix tree.
1412 if(length >= subtree.bitIndex)
1413 lastOne = true;
1414 }
1415
1416 }
1417
1418 /** An iterator for submaps. */
1419 private class SubMapEntryIterator extends NodeIterator<Map.Entry<K,V>> {
1420 private final K firstExcludedKey;
1421
1422 SubMapEntryIterator(TrieEntry<K,V> first, TrieEntry<K,V> firstExcluded) {
1423 super(first);
1424 firstExcludedKey =
1425 (firstExcluded == null ? null : firstExcluded.key);
1426 }
1427
1428 @Override
1429 public boolean hasNext() {
1430 return next != null && next.key != firstExcludedKey;
1431 }
1432
1433 public Map.Entry<K,V> next() {
1434 if (next == null || next.key == firstExcludedKey)
1435 throw new NoSuchElementException();
1436 return nextEntry();
1437 }
1438 }
1439
1440 Iterator<K> newKeyIterator() {
1441 return new KeyIterator();
1442 }
1443
1444 Iterator<V> newValueIterator() {
1445 return new ValueIterator();
1446 }
1447
1448 Iterator<Map.Entry<K,V>> newEntryIterator() {
1449 return new EntryIterator();
1450 }
1451
1452 /**
1453 * Each of these fields are initialized to contain an instance of the
1454 * appropriate view the first time this view is requested. The views are
1455 * stateless, so there's no reason to create more than one of each.
1456 */
1457 private transient volatile Set<K> keySet = null;
1458 private transient volatile Collection<V> values = null;
1459 private transient volatile Set<Map.Entry<K,V>> entrySet = null;
1460
1461 private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1462 @Override
1463 public Iterator<Map.Entry<K,V>> iterator() {
1464 return newEntryIterator();
1465 }
1466
1467 @Override
1468 public boolean contains(Object o) {
1469 if (!(o instanceof Map.Entry))
1470 return false;
1471
1472 TrieEntry<K,V> candidate = getEntry(((Map.Entry)o).getKey());
1473 return candidate != null && candidate.equals(o);
1474 }
1475
1476 @Override
1477 public boolean remove(Object o) {
1478 int size = size();
1479 PatriciaTrie.this.remove(o);
1480 return size != size();
1481 }
1482
1483 @Override
1484 public int size() {
1485 return size;
1486 }
1487
1488 @Override
1489 public void clear() {
1490 PatriciaTrie.this.clear();
1491 }
1492 }
1493
1494 /**
1495 * Returns a set view of the keys contained in this map. The set is
1496 * backed by the map, so changes to the map are reflected in the set, and
1497 * vice-versa. The set supports element removal, which removes the
1498 * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
1499 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
1500 * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
1501 * <tt>addAll</tt> operations.
1502 *
1503 * @return a set view of the keys contained in this map.
1504 */
1505 @Override
1506 public Set<K> keySet() {
1507 Set<K> ks = keySet;
1508 return (ks != null ? ks : (keySet = new KeySet()));
1509 }
1510
1511 private class KeySet extends AbstractSet<K> {
1512 @Override
1513 public Iterator<K> iterator() {
1514 return newKeyIterator();
1515 }
1516 @Override
1517 public int size() {
1518 return size;
1519 }
1520 @Override
1521 public boolean contains(Object o) {
1522 return containsKey(o);
1523 }
1524 @Override
1525 public boolean remove(Object o) {
1526 int size = size();
1527 PatriciaTrie.this.remove(o);
1528 return size != size();
1529 }
1530 @Override
1531 public void clear() {
1532 PatriciaTrie.this.clear();
1533 }
1534 }
1535
1536 /**
1537 * Returns a collection view of the values contained in this map. The
1538 * collection is backed by the map, so changes to the map are reflected in
1539 * the collection, and vice-versa. The collection supports element
1540 * removal, which removes the corresponding mapping from this map, via the
1541 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
1542 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
1543 * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
1544 *
1545 * @return a collection view of the values contained in this map.
1546 */
1547 @Override
1548 public Collection<V> values() {
1549 Collection<V> vs = values;
1550 return (vs != null ? vs : (values = new Values()));
1551 }
1552
1553 /** Test two values for equality. Works with null values. */
1554 private static boolean valEquals(Object o1, Object o2) {
1555 return (o1==null ? o2==null : o1.equals(o2));
1556 }
1557
1558 private class Values extends AbstractCollection<V> {
1559 @Override
1560 public Iterator<V> iterator() {
1561 return newValueIterator();
1562 }
1563 @Override
1564 public int size() {
1565 return size;
1566 }
1567 @Override
1568 public boolean contains(Object o) {
1569 return containsValue(o);
1570 }
1571 @Override
1572 public void clear() {
1573 PatriciaTrie.this.clear();
1574 }
1575 @Override
1576 public boolean remove(Object o) {
1577 for(Iterator<V> i = iterator(); i.hasNext(); ) {
1578 V v = i.next();
1579 if(valEquals(v, o)) {
1580 i.remove();
1581 return true;
1582 }
1583 }
1584 return false;
1585 }
1586 }
1587
1588 /**
1589 * Returns the first entry the Trie is storing.
1590 *
1591 * This is implemented by going always to the left until
1592 * we encounter a valid uplink. That uplink is the first key.
1593 */
1594 private TrieEntry<K, V> firstEntry() {
1595 // if Trie is empty, no first node.
1596 if(isEmpty())
1597 return null;
1598
1599 return followLeft(root);
1600 }
1601
1602 /** Goes left through the tree until it finds a valid node. */
1603 private TrieEntry<K, V> followLeft(TrieEntry<K, V> node) {
1604 while(true) {
1605 TrieEntry<K, V> child = node.left;
1606 // if we hit root and it didn't have a node, go right instead.
1607 if(child.isEmpty())
1608 child = node.right;
1609
1610 if(child.bitIndex <= node.bitIndex)
1611 return child;
1612
1613 node = child;
1614 }
1615 }
1616
1617 /**
1618 * Returns the last entry the Trie is storing.
1619 * <p>
1620 * This is implemented by going always to the right until
1621 * we encounter a valid uplink. That uplink is the last key.
1622 */
1623 private TrieEntry<K, V> lastEntry() {
1624 return followRight(root.left);
1625 }
1626
1627 /** Traverses down the right path until it finds an uplink. */
1628 protected TrieEntry<K, V> followRight(TrieEntry<K, V> node) {
1629 // if Trie is empty, no last entry.
1630 if(node.right == null)
1631 return null;
1632
1633 // Go as far right as possible, until we encounter an uplink.
1634 while(node.right.bitIndex > node.bitIndex)
1635 node = node.right;
1636
1637 return node.right;
1638 }
1639
1640 public K firstKey() {
1641 return firstEntry().getKey();
1642 }
1643
1644 public SortedMap<K, V> headMap(K toKey) {
1645 return new SubMap(null, toKey);
1646 }
1647
1648 public K lastKey() {
1649 TrieEntry<K, V> entry = lastEntry();
1650 if(entry != null) {
1651 return entry.getKey();
1652 }
1653 return null;
1654 }
1655
1656
1657 public SortedMap<K, V> subMap(K fromKey, K toKey) {
1658 return new SubMap(fromKey, toKey);
1659 }
1660
1661 public SortedMap<K, V> tailMap(K fromKey) {
1662 return new SubMap(fromKey, null);
1663 }
1664
1665 /**
1666 * Returns an entry strictly higher than the given key,
1667 * or null if no such entry exists.
1668 */
1669 protected TrieEntry<K,V> higherEntry(K key) {
1670 // TODO: Cleanup so that we don't actually have to add/remove from the
1671 // tree. (We do it here because there are other well-defined
1672 // functions to perform the search.)
1673 int keyLength = length(key);
1674
1675 if (keyLength == 0) {
1676 if(!root.isEmpty()) {
1677 // If data in root, and more after -- return it.
1678 if(size() > 1) {
1679 return nextEntry(root);
1680 } else { // If no more after, no higher entry.
1681 return null;
1682 }
1683 } else {
1684 // Root is empty & we want something after empty, return first.
1685 return firstEntry();
1686 }
1687 }
1688
1689 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1690 if (key.equals(found.key))
1691 return nextEntry(found);
1692
1693 int bitIndex = bitIndex(key, found.key);
1694 if (isValidBitIndex(bitIndex)) {
1695 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1696 addEntry(added, keyLength);
1697 incrementSize(); // must increment because remove will decrement
1698 TrieEntry<K, V> ceil = nextEntry(added);
1699 removeEntry(added);
1700 modCount -= 2; // we didn't really modify it.
1701 return ceil;
1702 } else if (isNullBitKey(bitIndex)) {
1703 if (!root.isEmpty())
1704 return firstEntry();
1705 else if(size() > 1)
1706 return nextEntry(firstEntry());
1707 else
1708 return null;
1709 } else if (isEqualBitKey(bitIndex)) {
1710 return nextEntry(found);
1711 }
1712
1713 // we should have exited above.
1714 throw new IllegalStateException("invalid lookup: " + key);
1715 }
1716
1717 /**
1718 * Returns a key-value mapping associated with the least key greater
1719 * than or equal to the given key, or null if there is no such key.
1720 */
1721 protected TrieEntry<K,V> ceilingEntry(K key) {
1722 // Basically:
1723 // Follow the steps of adding an entry, but instead...
1724 //
1725 // - If we ever encounter a situation where we found an equal
1726 // key, we return it immediately.
1727 //
1728 // - If we hit an empty root, return the first iterable item.
1729 //
1730 // - If we have to add a new item, we temporarily add it,
1731 // find the successor to it, then remove the added item.
1732 //
1733 // These steps ensure that the returned value is either the
1734 // entry for the key itself, or the first entry directly after
1735 // the key.
1736
1737 // TODO: Cleanup so that we don't actually have to add/remove from the
1738 // tree. (We do it here because there are other well-defined
1739 // functions to perform the search.)
1740 int keyLength = length(key);
1741
1742 if (keyLength == 0) {
1743 if(!root.isEmpty())
1744 return root;
1745 else
1746 return firstEntry();
1747 }
1748
1749 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1750 if (key.equals(found.key))
1751 return found;
1752
1753 int bitIndex = bitIndex(key, found.key);
1754 if (isValidBitIndex(bitIndex)) {
1755 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1756 addEntry(added, keyLength);
1757 incrementSize(); // must increment because remove will decrement
1758 TrieEntry<K, V> ceil = nextEntry(added);
1759 removeEntry(added);
1760 modCount -= 2; // we didn't really modify it.
1761 return ceil;
1762 } else if (isNullBitKey(bitIndex)) {
1763 if (!root.isEmpty())
1764 return root;
1765 else
1766 return firstEntry();
1767 } else if (isEqualBitKey(bitIndex)) {
1768 return found;
1769 }
1770
1771 // we should have exited above.
1772 throw new IllegalStateException("invalid lookup: " + key);
1773 }
1774
1775 /**
1776 * Returns a key-value mapping associated with the greatest key
1777 * strictly less than the given key, or null if there is no such key.
1778 */
1779 protected TrieEntry<K,V> lowerEntry(K key) {
1780 // Basically:
1781 // Follow the steps of adding an entry, but instead...
1782 //
1783 // - If we ever encounter a situation where we found an equal
1784 // key, we return it's previousEntry immediately.
1785 //
1786 // - If we hit root (empty or not), return null.
1787 //
1788 // - If we have to add a new item, we temporarily add it,
1789 // find the previousEntry to it, then remove the added item.
1790 //
1791 // These steps ensure that the returned value is always just before
1792 // the key or null (if there was nothing before it).
1793
1794 // TODO: Cleanup so that we don't actually have to add/remove from the
1795 // tree. (We do it here because there are other well-defined
1796 // functions to perform the search.)
1797 int keyLength = length(key);
1798
1799 if (keyLength == 0) {
1800 return null; // there can never be anything before root.
1801 }
1802
1803 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1804 if (key.equals(found.key))
1805 return previousEntry(found);
1806
1807 int bitIndex = bitIndex(key, found.key);
1808 if (isValidBitIndex(bitIndex)) {
1809 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1810 addEntry(added, keyLength);
1811 incrementSize(); // must increment because remove will decrement
1812 TrieEntry<K, V> prior = previousEntry(added);
1813 removeEntry(added);
1814 modCount -= 2; // we didn't really modify it.
1815 return prior;
1816 } else if (isNullBitKey(bitIndex)) {
1817 return null;
1818 } else if (isEqualBitKey(bitIndex)) {
1819 return previousEntry(found);
1820 }
1821
1822 // we should have exited above.
1823 throw new IllegalStateException("invalid lookup: " + key);
1824 }
1825
1826 /**
1827 * Returns a key-value mapping associated with the greatest key
1828 * less than or equal to the given key, or null if there is no such key.
1829 */
1830 protected TrieEntry<K,V> floorEntry(K key) {
1831 // TODO: Cleanup so that we don't actually have to add/remove from the
1832 // tree. (We do it here because there are other well-defined
1833 // functions to perform the search.)
1834 int keyLength = length(key);
1835
1836 if (keyLength == 0) {
1837 if(!root.isEmpty())
1838 return root;
1839 else
1840 return null;
1841 }
1842
1843 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1844 if (key.equals(found.key))
1845 return found;
1846
1847 int bitIndex = bitIndex(key, found.key);
1848 if (isValidBitIndex(bitIndex)) {
1849 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1850 addEntry(added, keyLength);
1851 incrementSize(); // must increment because remove will decrement
1852 TrieEntry<K, V> floor = previousEntry(added);
1853 removeEntry(added);
1854 modCount -= 2; // we didn't really modify it.
1855 return floor;
1856 } else if (isNullBitKey(bitIndex)) {
1857 if (!root.isEmpty())
1858 return root;
1859 else
1860 return null;
1861 } else if (isEqualBitKey(bitIndex)) {
1862 return found;
1863 }
1864
1865 // we should have exited above.
1866 throw new IllegalStateException("invalid lookup: " + key);
1867 }
1868
1869
1870 /**
1871 * Finds the subtree that contains the prefix.
1872 *
1873 * This is very similar to getR but with the difference that
1874 * we stop the lookup if h.bitIndex > keyLength.
1875 */
1876 private TrieEntry<K, V> subtree(K prefix, int offset, int length) {
1877 TrieEntry<K, V> current = root.left;
1878 TrieEntry<K, V> path = root;
1879 while(true) {
1880 if(current.bitIndex <= path.bitIndex || length < current.bitIndex)
1881 break;
1882
1883 path = current;
1884 if(!isBitSet(prefix, length+offset, current.bitIndex+offset)) {
1885 current = current.left;
1886 } else {
1887 current = current.right;
1888 }
1889 }
1890
1891 // Make sure the entry is valid for a subtree.
1892 TrieEntry<K, V> entry = current.isEmpty() ? path : current;
1893
1894 // If entry is root, it can't be empty.
1895 if (entry.isEmpty())
1896 return null;
1897
1898 int offsetLength = offset + length;
1899
1900 // if root && length of root is less than length of lookup,
1901 // there's nothing.
1902 // (this prevents returning the whole subtree if root has an empty
1903 // string and we want to lookup things with "\0")
1904 if(entry == root && length(entry.getKey()) < offsetLength)
1905 return null;
1906
1907 // Found key's length-th bit differs from our key
1908 // which means it cannot be the prefix...
1909 if(isBitSet(prefix, offsetLength, offsetLength) !=
1910 isBitSet(entry.key, length(entry.key), length)) {
1911 return null;
1912 }
1913
1914 // ... or there are less than 'length' equal bits
1915 int bitIndex = keyAnalyzer.bitIndex(prefix, offset, length,
1916 entry.key, 0, length(entry.getKey()));
1917 if (bitIndex >= 0 && bitIndex < length)
1918 return null;
1919
1920 return entry;
1921 }
1922
1923 /** A submap used for prefix views over the Trie. */
1924 private class PrefixSubMap extends SubMap {
1925 protected final K prefix;
1926 protected final int offset;
1927 protected final int length;
1928 private transient int keyModCount = 0;
1929 protected int size;
1930
1931 PrefixSubMap(K prefix, int offset, int length) {
1932 this.prefix = prefix;
1933 this.offset = offset;
1934 this.length = length;
1935 fromInclusive = false;
1936 }
1937
1938 @Override
1939 public K firstKey() {
1940 fixup();
1941 TrieEntry<K,V> e;
1942 if(fromKey == null) {
1943 e = firstEntry();
1944 } else {
1945 e = higherEntry(fromKey);
1946 }
1947
1948 K first = e != null ? e.getKey() : null;
1949 if (e == null || !keyAnalyzer.isPrefix(prefix, offset, length, first))
1950 throw new NoSuchElementException();
1951 return first;
1952 }
1953
1954 @Override
1955 public K lastKey() {
1956 fixup();
1957 TrieEntry<K,V> e;
1958 if(toKey == null) {
1959 e = lastEntry();
1960 } else {
1961 e = lowerEntry(toKey);
1962 }
1963
1964 K last = e != null ? e.getKey() : null;
1965 if (e == null || !keyAnalyzer.isPrefix(prefix, offset, length, last))
1966 throw new NoSuchElementException();
1967 return last;
1968 }
1969
1970 @Override
1971 protected boolean inRange(K key) {
1972 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1973 }
1974
1975 @Override
1976 protected boolean inRange2(K key) {
1977 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1978 }
1979
1980 @Override
1981 protected boolean inToRange(K key, boolean forceInclusive) {
1982 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1983 }
1984
1985 @Override
1986 protected boolean inFromRange(K key, boolean forceInclusive) {
1987 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1988 }
1989
1990 private void fixup() {
1991 // The trie has changed since we last
1992 // found our toKey / fromKey
1993 if(modCount != keyModCount) {
1994 Iterator<Map.Entry<K, V>> iter = entrySet().iterator();
1995 size = 0;
1996
1997 Map.Entry<K, V> entry = null;
1998 if(iter.hasNext()) {
1999 entry = iter.next();
2000 size = 1;
2001 }
2002
2003 fromKey = entry == null ? null : entry.getKey();
2004 if(fromKey != null) {
2005 TrieEntry<K, V> prior = previousEntry((TrieEntry<K, V>)entry);
2006 fromKey = prior == null ? null : prior.getKey();
2007 }
2008
2009 toKey = fromKey;
2010
2011 while(iter.hasNext()) {
2012 size++;
2013 entry = iter.next();
2014 }
2015
2016 toKey = entry == null ? null : entry.getKey();
2017
2018 if(toKey != null) {
2019 entry = nextEntry((TrieEntry<K, V>)entry);
2020 toKey = entry == null ? null : entry.getKey();
2021 }
2022
2023 keyModCount = modCount;
2024 }
2025 }
2026
2027 @Override
2028 protected Set<Map.Entry<K, V>> newSubMapEntrySet() {
2029 return new PrefixEntrySetView();
2030 }
2031
2032 private class PrefixEntrySetView extends SubMap.EntrySetView {
2033 private TrieEntry<K, V> prefixStart;
2034 private int iterModCount = 0;
2035
2036 @Override
2037 public int size() {
2038 fixup();
2039 return PrefixSubMap.this.size;
2040 }
2041
2042 @Override
2043 public Iterator<Map.Entry<K,V>> iterator() {
2044 if(modCount != iterModCount) {
2045 prefixStart = subtree(prefix, offset, length);
2046 iterModCount = modCount;
2047 }
2048
2049 if(prefixStart == null) {
2050 return EmptyIterator.emptyIterator();
2051 } else if(length >= prefixStart.bitIndex){
2052 return new SingletonIterator(prefixStart);
2053 } else {
2054 return new PrefixEntryIterator(prefixStart, prefix, offset, length);
2055 }
2056 }
2057 }
2058 }
2059
2060 private class SubMap extends AbstractMap<K,V> implements SortedMap<K,V>, java.io.Serializable {
2061
2062 // TODO: add serialVersionUID
2063
2064 /** The key to start from, null if the beginning. */
2065 protected K fromKey;
2066
2067 /** The key to end at, null if till the end. */
2068 protected K toKey;
2069
2070 /** Whether or not the 'from' is inclusive. */
2071 protected boolean fromInclusive;
2072
2073 /** Whether or not the 'to' is inclusive. */
2074 protected boolean toInclusive;
2075
2076 /**
2077 * Constructs a blank SubMap -- this should ONLY be used
2078 * by subclasses that wish to lazily construct their
2079 * fromKey or toKey
2080 */
2081 protected SubMap() {}
2082
2083 SubMap(K fromKey, K toKey) {
2084 if(fromKey == null && toKey == null)
2085 throw new IllegalArgumentException("must have a from or to!");
2086 if(fromKey != null && toKey != null && keyAnalyzer.compare(fromKey, toKey) > 0)
2087 throw new IllegalArgumentException("fromKey > toKey");
2088 this.fromKey = fromKey;
2089 this.toKey = toKey;
2090 fromInclusive = true;
2091 }
2092
2093 @Override
2094 public boolean isEmpty() {
2095 return entrySet().isEmpty();
2096 }
2097
2098 @SuppressWarnings("unchecked")
2099 @Override
2100 public boolean containsKey(Object key) {
2101 return inRange((K) key) && PatriciaTrie.this.containsKey(key);
2102 }
2103
2104 @SuppressWarnings("unchecked")
2105 @Override
2106 public V remove(Object key) {
2107 if(!inRange((K)key))
2108 return null;
2109 return PatriciaTrie.this.remove(key);
2110 }
2111
2112 @SuppressWarnings("unchecked")
2113 @Override
2114 public V get(Object key) {
2115 if (!inRange((K) key))
2116 return null;
2117 return PatriciaTrie.this.get(key);
2118 }
2119
2120 @Override
2121 public V put(K key, V value) {
2122 if (!inRange(key))
2123 throw new IllegalArgumentException("key out of range");
2124 return PatriciaTrie.this.put(key, value);
2125 }
2126
2127 public Comparator<? super K> comparator() {
2128 return keyAnalyzer;
2129 }
2130
2131 public K firstKey() {
2132 TrieEntry<K,V> e;
2133 if(fromKey == null) {
2134 e = firstEntry();
2135 } else {
2136 if(fromInclusive)
2137 e = ceilingEntry(fromKey);
2138 else
2139 e = higherEntry(fromKey);
2140 }
2141
2142 K first = e != null ? e.getKey() : null;
2143 if (e == null || toKey != null && !inToRange(first, false))
2144 throw new NoSuchElementException();
2145 return first;
2146 }
2147
2148 public K lastKey() {
2149 TrieEntry<K,V> e;
2150 if(toKey == null) {
2151 e = lastEntry();
2152 } else {
2153 if(toInclusive)
2154 e = floorEntry(toKey);
2155 else
2156 e = lowerEntry(toKey);
2157 }
2158
2159 K last = e != null ? e.getKey() : null;
2160 if (e == null || fromKey != null && !inFromRange(last, false))
2161 throw new NoSuchElementException();
2162 return last;
2163 }
2164
2165 private transient Set<Map.Entry<K,V>> entrySet;
2166
2167 @Override
2168 public Set<Map.Entry<K,V>> entrySet() {
2169 if(entrySet == null)
2170 entrySet = newSubMapEntrySet();
2171 return entrySet;
2172 }
2173
2174 protected Set<Map.Entry<K, V>> newSubMapEntrySet() {
2175 return new EntrySetView();
2176 }
2177
2178 class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
2179 private transient int size = -1, sizeModCount;
2180
2181 @Override
2182 public int size() {
2183 if (size == -1 || sizeModCount != PatriciaTrie.this.modCount) {
2184 size = 0; sizeModCount = PatriciaTrie.this.modCount;
2185 Iterator i = iterator();
2186 while (i.hasNext()) {
2187 size++;
2188 i.next();
2189 }
2190 }
2191 return size;
2192 }
2193
2194 @Override
2195 public boolean isEmpty() {
2196 return !iterator().hasNext();
2197 }
2198
2199 @SuppressWarnings("unchecked")
2200 @Override
2201 public boolean contains(Object o) {
2202 if (!(o instanceof Map.Entry))
2203 return false;
2204 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
2205 K key = entry.getKey();
2206 if (!inRange(key))
2207 return false;
2208 TrieEntry<K, V> node = getEntry(key);
2209 return node != null &&
2210 valEquals(node.getValue(), entry.getValue());
2211 }
2212
2213 @SuppressWarnings("unchecked")
2214 @Override
2215 public boolean remove(Object o) {
2216 if (!(o instanceof Map.Entry))
2217 return false;
2218 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
2219 K key = entry.getKey();
2220 if (!inRange(key))
2221 return false;
2222 TrieEntry<K,V> node = getEntry(key);
2223 if (node!=null && valEquals(node.getValue(),entry.getValue())){
2224 removeEntry(node);
2225 return true;
2226 }
2227 return false;
2228 }
2229
2230 @Override
2231 public Iterator<Map.Entry<K,V>> iterator() {
2232 return new SubMapEntryIterator(
2233 (fromKey == null ? firstEntry() : ceilingEntry(fromKey)),
2234 (toKey == null ? null : ceilingEntry(toKey)));
2235 }
2236 }
2237
2238 public SortedMap<K,V> subMap(K fromKey, K toKey) {
2239 if (!inRange2(fromKey))
2240 throw new IllegalArgumentException("fromKey out of range");
2241 if (!inRange2(toKey))
2242 throw new IllegalArgumentException("toKey out of range");
2243 return new SubMap(fromKey, toKey);
2244 }
2245
2246 public SortedMap<K,V> headMap(K toKey) {
2247 if (!inRange2(toKey))
2248 throw new IllegalArgumentException("toKey out of range");
2249 return new SubMap(fromKey, toKey);
2250 }
2251
2252 public SortedMap<K,V> tailMap(K fromKey) {
2253 if (!inRange2(fromKey))
2254 throw new IllegalArgumentException("fromKey out of range");
2255 return new SubMap(fromKey, toKey);
2256 }
2257
2258 protected boolean inRange(K key) {
2259 return (fromKey == null || inFromRange(key, false)) &&
2260 (toKey == null || inToRange(key, false));
2261 }
2262
2263 // This form allows the high endpoint (as well as all legit keys)
2264 protected boolean inRange2(K key) {
2265 return (fromKey == null || inFromRange(key, false)) &&
2266 (toKey == null || inToRange(key, true));
2267 }
2268
2269 protected boolean inToRange(K key, boolean forceInclusive) {
2270 int ret = keyAnalyzer.compare(key, toKey);
2271 if(toInclusive || forceInclusive)
2272 return ret <= 0;
2273 else
2274 return ret < 0;
2275 }
2276
2277 protected boolean inFromRange(K key, boolean forceInclusive) {
2278 int ret = keyAnalyzer.compare(key, fromKey);
2279 if (fromInclusive || forceInclusive)
2280 return ret >= 0;
2281 else
2282 return ret > 0;
2283 }
2284 }
2285 }