View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.trie;
18  
19  import java.util.AbstractMap;
20  import java.util.AbstractSet;
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.NoSuchElementException;
26  import java.util.Set;
27  import java.util.SortedMap;
28  
29  import org.apache.commons.collections.Trie;
30  
31  /**
32   * <h3>PATRICIA {@link Trie}</h3>
33   *  
34   * <i>Practical Algorithm to Retrieve Information Coded in Alphanumeric</i>
35   * 
36   * <p>A PATRICIA {@link Trie} is a compressed {@link Trie}. Instead of storing 
37   * all data at the edges of the {@link Trie} (and having empty internal nodes), 
38   * PATRICIA stores data in every node. This allows for very efficient traversal, 
39   * insert, delete, predecessor, successor, prefix, range, and {@link #select(Object)} 
40   * operations. All operations are performed at worst in O(K) time, where K 
41   * is the number of bits in the largest item in the tree. In practice, 
42   * operations actually take O(A(K)) time, where A(K) is the average number of 
43   * bits of all items in the tree.
44   * 
45   * <p>Most importantly, PATRICIA requires very few comparisons to keys while
46   * doing any operation. While performing a lookup, each comparison (at most 
47   * K of them, described above) will perform a single bit comparison against 
48   * the given key, instead of comparing the entire key to another key.
49   * 
50   * <p>The {@link Trie} can return operations in lexicographical order using the 
51   * {@link #traverse(Cursor)}, 'prefix', 'submap', or 'iterator' methods. The 
52   * {@link Trie} can also scan for items that are 'bitwise' (using an XOR 
53   * metric) by the 'select' method. Bitwise closeness is determined by the 
54   * {@link KeyAnalyzer} returning true or false for a bit being set or not in 
55   * a given key.
56   * 
57   * <p>This PATRICIA {@link Trie} supports both variable length & fixed length 
58   * keys. Some methods, such as {@link #getPrefixedBy(Object)} are suited only 
59   * to variable length keys, whereas {@link #getPrefixedByBits(Object, int)} is 
60   * suited to fixed-size keys.
61   * 
62   * <p>Any methods here that take an {@link Object} argument may throw a 
63   * {@link ClassCastException} if the method is expecting an instance of K 
64   * and it isn't K.
65   * 
66   * @see <a href="http://en.wikipedia.org/wiki/Radix_tree">Radix Tree</a>
67   * @see <a href="http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/PATRICIA">PATRICIA</a>
68   * @see <a href="http://www.imperialviolet.org/binary/critbit.pdf">Crit-Bit Tree</a>
69   * @since 4.0
70   * @version $Id: PatriciaTrie.java 1436026 2013-01-21 00:55:20Z sebb $
71   */
72  public class PatriciaTrie<K, V> extends PatriciaTrieBase<K, V> implements Trie<K, V> {
73      
74      private static final long serialVersionUID = 4446367780901817838L;
75  
76      public PatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer) {
77          super(keyAnalyzer);
78      }
79  
80      public PatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer,
81              final Map<? extends K, ? extends V> m) {
82          super(keyAnalyzer, m);
83      }
84      
85      /**
86       * {@inheritDoc}
87       */
88      public Comparator<? super K> comparator() {
89          return keyAnalyzer;
90      }
91      
92      /**
93       * {@inheritDoc}
94       */
95      public SortedMap<K, V> getPrefixedBy(final K key) {
96          return getPrefixedByBits(key, 0, lengthInBits(key));
97      }
98  
99      /**
100      * {@inheritDoc}
101      */
102     public SortedMap<K, V> getPrefixedBy(final K key, final int length) {
103         return getPrefixedByBits(key, 0, length * bitsPerElement());
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
109     public SortedMap<K, V> getPrefixedBy(final K key, final int offset, final int length) {
110         final int bitsPerElement = bitsPerElement();
111         return getPrefixedByBits(key, offset*bitsPerElement, length*bitsPerElement);
112     }
113 
114     /**
115      * {@inheritDoc}
116      */
117     public SortedMap<K, V> getPrefixedByBits(final K key, final int lengthInBits) {
118         return getPrefixedByBits(key, 0, lengthInBits);
119     }
120     
121     /**
122      * {@inheritDoc}
123      */
124     public K firstKey() {
125         return firstEntry().getKey();
126     }
127 
128     /**
129      * {@inheritDoc}
130      */
131     public K lastKey() {
132         final TrieEntry<K, V> entry = lastEntry();
133         if (entry != null) {
134             return entry.getKey();
135         }
136         return null;
137     }
138     
139     /**
140      * {@inheritDoc}
141      * 
142      * The view that this returns is optimized to have a very efficient
143      * {@link Iterator}. The {@link SortedMap#firstKey()}, 
144      * {@link SortedMap#lastKey()} &amp; {@link Map#size()} methods must 
145      * iterate over all possible values in order to determine the results. 
146      * This information is cached until the PATRICIA {@link Trie} changes. 
147      * All other methods (except {@link Iterator}) must compare the given 
148      * key to the prefix to ensure that it is within the range of the view.  
149      * The {@link Iterator}'s remove method must also relocate the subtree 
150      * that contains the prefixes if the entry holding the subtree is 
151      * removed or changes. Changing the subtree takes O(K) time.
152      */
153     public SortedMap<K, V> getPrefixedByBits(final K key, final int offsetInBits, final int lengthInBits) {
154         
155         final int offsetLength = offsetInBits + lengthInBits;
156         if (offsetLength > lengthInBits(key)) {
157             throw new IllegalArgumentException(offsetInBits + " + " 
158                     + lengthInBits + " > " + lengthInBits(key));
159         }
160         
161         if (offsetLength == 0) {
162             return this;
163         }
164         
165         return new PrefixRangeMap(key, offsetInBits, lengthInBits);
166     }
167     
168     /**
169      * {@inheritDoc}
170      */
171     public SortedMap<K, V> headMap(final K toKey) {
172         return new RangeEntryMap(null, toKey);
173     }
174 
175     /**
176      * {@inheritDoc}
177      */
178     public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
179         return new RangeEntryMap(fromKey, toKey);
180     }
181 
182     /**
183      * {@inheritDoc}
184      */
185     public SortedMap<K, V> tailMap(final K fromKey) {
186         return new RangeEntryMap(fromKey, null);
187     } 
188     
189     /**
190      * Returns an entry strictly higher than the given key,
191      * or null if no such entry exists.
192      */
193     TrieEntry<K,V> higherEntry(final K key) {
194         // TODO: Cleanup so that we don't actually have to add/remove from the
195         //       tree.  (We do it here because there are other well-defined 
196         //       functions to perform the search.)
197         final int lengthInBits = lengthInBits(key);
198         
199         if (lengthInBits == 0) {
200             if (!root.isEmpty()) {
201                 // If data in root, and more after -- return it.
202                 if (size() > 1) {
203                     return nextEntry(root);
204                 } else { // If no more after, no higher entry.
205                     return null;
206                 }
207             } else {
208                 // Root is empty & we want something after empty, return first.
209                 return firstEntry();
210             }
211         }
212         
213         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
214         if (compareKeys(key, found.key)) {
215             return nextEntry(found);
216         }
217         
218         final int bitIndex = bitIndex(key, found.key);
219         if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
220             final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
221             addEntry(added, lengthInBits);
222             incrementSize(); // must increment because remove will decrement
223             final TrieEntry<K, V> ceil = nextEntry(added);
224             removeEntry(added);
225             modCount -= 2; // we didn't really modify it.
226             return ceil;
227         } else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
228             if (!root.isEmpty()) {
229                 return firstEntry();
230             } else if (size() > 1) {
231                 return nextEntry(firstEntry());
232             } else {
233                 return null;
234             }
235         } else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
236             return nextEntry(found);
237         }
238 
239         // we should have exited above.
240         throw new IllegalStateException("invalid lookup: " + key);
241     }
242     
243     /**
244      * Returns a key-value mapping associated with the least key greater
245      * than or equal to the given key, or null if there is no such key.
246      */
247     TrieEntry<K,V> ceilingEntry(final K key) {
248         // Basically:
249         // Follow the steps of adding an entry, but instead...
250         //
251         // - If we ever encounter a situation where we found an equal
252         //   key, we return it immediately.
253         //
254         // - If we hit an empty root, return the first iterable item.
255         //
256         // - If we have to add a new item, we temporarily add it,
257         //   find the successor to it, then remove the added item.
258         //
259         // These steps ensure that the returned value is either the
260         // entry for the key itself, or the first entry directly after
261         // the key.
262         
263         // TODO: Cleanup so that we don't actually have to add/remove from the
264         //       tree.  (We do it here because there are other well-defined 
265         //       functions to perform the search.)
266         final int lengthInBits = lengthInBits(key);
267         
268         if (lengthInBits == 0) {
269             if (!root.isEmpty()) {
270                 return root;
271             } else {
272                 return firstEntry();
273             }
274         }
275         
276         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
277         if (compareKeys(key, found.key)) {
278             return found;
279         }
280         
281         final int bitIndex = bitIndex(key, found.key);
282         if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
283             final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
284             addEntry(added, lengthInBits);
285             incrementSize(); // must increment because remove will decrement
286             final TrieEntry<K, V> ceil = nextEntry(added);
287             removeEntry(added);
288             modCount -= 2; // we didn't really modify it.
289             return ceil;
290         } else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
291             if (!root.isEmpty()) {
292                 return root;
293             } else {
294                 return firstEntry();
295             }
296         } else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
297             return found;
298         }
299 
300         // we should have exited above.
301         throw new IllegalStateException("invalid lookup: " + key);
302     }
303     
304     /**
305      * Returns a key-value mapping associated with the greatest key
306      * strictly less than the given key, or null if there is no such key.
307      */
308     TrieEntry<K,V> lowerEntry(final K key) {
309         // Basically:
310         // Follow the steps of adding an entry, but instead...
311         //
312         // - If we ever encounter a situation where we found an equal
313         //   key, we return it's previousEntry immediately.
314         //
315         // - If we hit root (empty or not), return null.
316         //
317         // - If we have to add a new item, we temporarily add it,
318         //   find the previousEntry to it, then remove the added item.
319         //
320         // These steps ensure that the returned value is always just before
321         // the key or null (if there was nothing before it).
322         
323         // TODO: Cleanup so that we don't actually have to add/remove from the
324         //       tree.  (We do it here because there are other well-defined 
325         //       functions to perform the search.)
326         final int lengthInBits = lengthInBits(key);
327         
328         if (lengthInBits == 0) {
329             return null; // there can never be anything before root.
330         }
331         
332         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
333         if (compareKeys(key, found.key)) {
334             return previousEntry(found);
335         }
336         
337         final int bitIndex = bitIndex(key, found.key);
338         if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
339             final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
340             addEntry(added, lengthInBits);
341             incrementSize(); // must increment because remove will decrement
342             final TrieEntry<K, V> prior = previousEntry(added);
343             removeEntry(added);
344             modCount -= 2; // we didn't really modify it.
345             return prior;
346         } else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
347             return null;
348         } else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
349             return previousEntry(found);
350         }
351 
352         // we should have exited above.
353         throw new IllegalStateException("invalid lookup: " + key);
354     }
355     
356     /**
357      * Returns a key-value mapping associated with the greatest key
358      * less than or equal to the given key, or null if there is no such key.
359      */
360     TrieEntry<K,V> floorEntry(final K key) {        
361         // TODO: Cleanup so that we don't actually have to add/remove from the
362         //       tree.  (We do it here because there are other well-defined 
363         //       functions to perform the search.)
364         final int lengthInBits = lengthInBits(key);
365         
366         if (lengthInBits == 0) {
367             if (!root.isEmpty()) {
368                 return root;
369             } else {
370                 return null;
371             }
372         }
373         
374         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
375         if (compareKeys(key, found.key)) {
376             return found;
377         }
378         
379         final int bitIndex = bitIndex(key, found.key);
380         if (AbstractKeyAnalyzer.isValidBitIndex(bitIndex)) {
381             final TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
382             addEntry(added, lengthInBits);
383             incrementSize(); // must increment because remove will decrement
384             final TrieEntry<K, V> floor = previousEntry(added);
385             removeEntry(added);
386             modCount -= 2; // we didn't really modify it.
387             return floor;
388         } else if (AbstractKeyAnalyzer.isNullBitKey(bitIndex)) {
389             if (!root.isEmpty()) {
390                 return root;
391             } else {
392                 return null;
393             }
394         } else if (AbstractKeyAnalyzer.isEqualBitKey(bitIndex)) {
395             return found;
396         }
397 
398         // we should have exited above.
399         throw new IllegalStateException("invalid lookup: " + key);
400     }
401     
402     /**
403      * Finds the subtree that contains the prefix.
404      * 
405      * This is very similar to getR but with the difference that
406      * we stop the lookup if h.bitIndex > lengthInBits.
407      */
408     TrieEntry<K, V> subtree(final K prefix, final int offsetInBits, final int lengthInBits) {
409         TrieEntry<K, V> current = root.left;
410         TrieEntry<K, V> path = root;
411         while(true) {
412             if (current.bitIndex <= path.bitIndex 
413                     || lengthInBits < current.bitIndex) {
414                 break;
415             }
416             
417             path = current;
418             if (!isBitSet(prefix, offsetInBits + current.bitIndex, 
419                     offsetInBits + lengthInBits)) {
420                 current = current.left;
421             } else {
422                 current = current.right;
423             }
424         }        
425 
426         // Make sure the entry is valid for a subtree.
427         final TrieEntry<K, V> entry = current.isEmpty() ? path : current;
428         
429         // If entry is root, it can't be empty.
430         if (entry.isEmpty()) {
431             return null;
432         }
433         
434         final int endIndexInBits = offsetInBits + lengthInBits;
435         
436         // if root && length of root is less than length of lookup,
437         // there's nothing.
438         // (this prevents returning the whole subtree if root has an empty
439         //  string and we want to lookup things with "\0")
440         if (entry == root && lengthInBits(entry.getKey()) < endIndexInBits) {
441             return null;
442         }
443         
444         // Found key's length-th bit differs from our key
445         // which means it cannot be the prefix...
446         if (isBitSet(prefix, endIndexInBits, endIndexInBits) 
447                 != isBitSet(entry.key, lengthInBits, lengthInBits(entry.key))) {
448             return null;
449         }
450         
451         // ... or there are less than 'length' equal bits
452         final int bitIndex = keyAnalyzer.bitIndex(prefix, offsetInBits, 
453                 lengthInBits, entry.key, 0, lengthInBits(entry.getKey()));
454         
455         if (bitIndex >= 0 && bitIndex < lengthInBits) {
456             return null;
457         }
458         
459         return entry;
460     }
461     
462     /**
463      * Returns the last entry the {@link Trie} is storing.
464      * 
465      * <p>This is implemented by going always to the right until
466      * we encounter a valid uplink. That uplink is the last key.
467      */
468     TrieEntry<K, V> lastEntry() {
469         return followRight(root.left);
470     }
471     
472     /**
473      * Traverses down the right path until it finds an uplink.
474      */
475     TrieEntry<K, V> followRight(TrieEntry<K, V> node) {
476         // if Trie is empty, no last entry.
477         if (node.right == null) {
478             return null;
479         }
480         
481         // Go as far right as possible, until we encounter an uplink.
482         while (node.right.bitIndex > node.bitIndex) {
483             node = node.right;
484         }
485         
486         return node.right;
487     }
488     
489     /**
490      * Returns the node lexicographically before the given node (or null if none).
491      * 
492      * This follows four simple branches:
493      *  - If the uplink that returned us was a right uplink:
494      *      - If predecessor's left is a valid uplink from predecessor, return it.
495      *      - Else, follow the right path from the predecessor's left.
496      *  - If the uplink that returned us was a left uplink:
497      *      - Loop back through parents until we encounter a node where 
498      *        node != node.parent.left.
499      *          - If node.parent.left is uplink from node.parent:
500      *              - If node.parent.left is not root, return it.
501      *              - If it is root & root isEmpty, return null.
502      *              - If it is root & root !isEmpty, return root.
503      *          - If node.parent.left is not uplink from node.parent:
504      *              - Follow right path for first right child from node.parent.left   
505      * 
506      * @param start
507      */
508     TrieEntry<K, V> previousEntry(final TrieEntry<K, V> start) {
509         if (start.predecessor == null) {
510             throw new IllegalArgumentException("must have come from somewhere!");
511         }
512         
513         if (start.predecessor.right == start) {
514             if (isValidUplink(start.predecessor.left, start.predecessor)) {
515                 return start.predecessor.left;
516             } else {
517                 return followRight(start.predecessor.left);
518             }
519         } else {
520             TrieEntry<K, V> node = start.predecessor;
521             while (node.parent != null && node == node.parent.left) {
522                 node = node.parent;
523             }
524             
525             if (node.parent == null) { // can be null if we're looking up root.
526                 return null;
527             }
528             
529             if (isValidUplink(node.parent.left, node.parent)) {
530                 if (node.parent.left == root) {
531                     if (root.isEmpty()) {
532                         return null;
533                     } else {
534                         return root;
535                     }
536                     
537                 } else {
538                     return node.parent.left;
539                 }
540             } else {
541                 return followRight(node.parent.left);
542             }
543         }
544     }
545     
546     /**
547      * Returns the entry lexicographically after the given entry.
548      * If the given entry is null, returns the first node.
549      * 
550      * This will traverse only within the subtree.  If the given node
551      * is not within the subtree, this will have undefined results.
552      */
553     TrieEntry<K, V> nextEntryInSubtree(final TrieEntry<K, V> node, 
554             final TrieEntry<K, V> parentOfSubtree) {
555         if (node == null) {
556             return firstEntry();
557         } else {
558             return nextEntryImpl(node.predecessor, node, parentOfSubtree);
559         }
560     }
561     
562     /**
563      * A range view of the {@link Trie}
564      */
565     private abstract class RangeMap extends AbstractMap<K, V> 
566             implements SortedMap<K, V> {
567 
568         /**
569          * The {@link #entrySet()} view
570          */
571         private transient volatile Set<Map.Entry<K, V>> entrySet;
572 
573         /**
574          * Creates and returns an {@link #entrySet()} 
575          * view of the {@link RangeMap}
576          */
577         protected abstract Set<Map.Entry<K, V>> createEntrySet();
578 
579         /**
580          * Returns the FROM Key
581          */
582         protected abstract K getFromKey();
583         
584         /**
585          * Whether or not the {@link #getFromKey()} is in the range
586          */
587         protected abstract boolean isFromInclusive();
588         
589         /**
590          * Returns the TO Key
591          */
592         protected abstract K getToKey();
593         
594         /**
595          * Whether or not the {@link #getToKey()} is in the range
596          */
597         protected abstract boolean isToInclusive();
598         
599         /**
600          * {@inheritDoc}
601          */
602         public Comparator<? super K> comparator() {
603             return PatriciaTrie.this.comparator();
604         }
605 
606         /**
607          * {@inheritDoc}
608          */
609         @Override
610         public boolean containsKey(final Object key) {
611             if (!inRange(castKey(key))) {
612                 return false;
613             }
614 
615             return PatriciaTrie.this.containsKey(key);
616         }
617 
618         /**
619          * {@inheritDoc}
620          */
621         @Override
622         public V remove(final Object key) {
623             if (!inRange(castKey(key))) {
624                 return null;
625             }
626 
627             return PatriciaTrie.this.remove(key);
628         }
629 
630         /**
631          * {@inheritDoc}
632          */
633         @Override
634         public V get(final Object key) {
635             if (!inRange(castKey(key))) {
636                 return null;
637             }
638 
639             return PatriciaTrie.this.get(key);
640         }
641 
642         /**
643          * {@inheritDoc}
644          */
645         @Override
646         public V put(final K key, final V value) {
647             if (!inRange(key)) {
648                 throw new IllegalArgumentException(
649                         "Key is out of range: " + key);
650             }
651 
652             return PatriciaTrie.this.put(key, value);
653         }
654 
655         /**
656          * {@inheritDoc}
657          */
658         @Override
659         public Set<Map.Entry<K, V>> entrySet() {
660             if (entrySet == null) {
661                 entrySet = createEntrySet();
662             }
663             return entrySet;
664         }
665 
666         /**
667          * {@inheritDoc}
668          */
669         public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
670             if (!inRange2(fromKey)) {
671                 throw new IllegalArgumentException(
672                         "FromKey is out of range: " + fromKey);
673             }
674 
675             if (!inRange2(toKey)) {
676                 throw new IllegalArgumentException(
677                         "ToKey is out of range: " + toKey);
678             }
679 
680             return createRangeMap(fromKey, isFromInclusive(), 
681                     toKey, isToInclusive());
682         }
683 
684         /**
685          * {@inheritDoc}
686          */
687         public SortedMap<K, V> headMap(final K toKey) {
688             if (!inRange2(toKey)) {
689                 throw new IllegalArgumentException(
690                         "ToKey is out of range: " + toKey);
691             }
692 
693             return createRangeMap(getFromKey(), isFromInclusive(), 
694                     toKey, isToInclusive());
695         }
696 
697         /**
698          * {@inheritDoc}
699          */
700         public SortedMap<K, V> tailMap(final K fromKey) {
701             if (!inRange2(fromKey)) {
702                 throw new IllegalArgumentException(
703                         "FromKey is out of range: " + fromKey);
704             }
705 
706             return createRangeMap(fromKey, isFromInclusive(), 
707                     getToKey(), isToInclusive());
708         }
709 
710         /**
711          * Returns true if the provided key is greater than TO and
712          * less than FROM
713          */
714         protected boolean inRange(final K key) {
715 
716             final K fromKey = getFromKey();
717             final K toKey = getToKey();
718 
719             return (fromKey == null || inFromRange(key, false))
720                     && (toKey == null || inToRange(key, false));
721         }
722 
723         /**
724          * This form allows the high endpoint (as well as all legit keys)
725          */
726         protected boolean inRange2(final K key) {
727 
728             final K fromKey = getFromKey();
729             final K toKey = getToKey();
730 
731             return (fromKey == null || inFromRange(key, false))
732                     && (toKey == null || inToRange(key, true));
733         }
734 
735         /**
736          * Returns true if the provided key is in the FROM range 
737          * of the {@link RangeMap}
738          */
739         protected boolean inFromRange(final K key, final boolean forceInclusive) {
740 
741             final K fromKey = getFromKey();
742             final boolean fromInclusive = isFromInclusive();
743 
744             final int ret = keyAnalyzer.compare(key, fromKey);
745             if (fromInclusive || forceInclusive) {
746                 return ret >= 0;
747             } else {
748                 return ret > 0;
749             }
750         }
751 
752         /**
753          * Returns true if the provided key is in the TO range 
754          * of the {@link RangeMap}
755          */
756         protected boolean inToRange(final K key, final boolean forceInclusive) {
757 
758             final K toKey = getToKey();
759             final boolean toInclusive = isToInclusive();
760 
761             final int ret = keyAnalyzer.compare(key, toKey);
762             if (toInclusive || forceInclusive) {
763                 return ret <= 0;
764             } else {
765                 return ret < 0;
766             }
767         }
768 
769         /**
770          * Creates and returns a sub-range view of the current {@link RangeMap}
771          */
772         protected abstract SortedMap<K, V> createRangeMap(K fromKey,
773                 boolean fromInclusive, K toKey, boolean toInclusive);
774     }
775    
776    /**
777     * A {@link RangeMap} that deals with {@link Entry}s
778     */
779    private class RangeEntryMap extends RangeMap {
780        
781        /** 
782         * The key to start from, null if the beginning. 
783         */
784        protected final K fromKey;
785        
786        /** 
787         * The key to end at, null if till the end. 
788         */
789        protected final K toKey;
790        
791        /** 
792         * Whether or not the 'from' is inclusive. 
793         */
794        protected final boolean fromInclusive;
795        
796        /** 
797         * Whether or not the 'to' is inclusive. 
798         */
799        protected final boolean toInclusive;
800        
801        /**
802         * Creates a {@link RangeEntryMap} with the fromKey included and
803         * the toKey excluded from the range
804         */
805        protected RangeEntryMap(final K fromKey, final K toKey) {
806            this(fromKey, true, toKey, false);
807        }
808        
809        /**
810         * Creates a {@link RangeEntryMap}
811         */
812        protected RangeEntryMap(final K fromKey, final boolean fromInclusive, 
813                final K toKey, final boolean toInclusive) {
814            
815            if (fromKey == null && toKey == null) {
816                throw new IllegalArgumentException("must have a from or to!");
817            }
818            
819            if (fromKey != null && toKey != null 
820                    && keyAnalyzer.compare(fromKey, toKey) > 0) {
821                throw new IllegalArgumentException("fromKey > toKey");
822            }
823            
824            this.fromKey = fromKey;
825            this.fromInclusive = fromInclusive;
826            this.toKey = toKey;
827            this.toInclusive = toInclusive;
828        }
829        
830        /**
831         * {@inheritDoc}
832         */
833        public K firstKey() {
834            Map.Entry<K,V> e = null;
835            if (fromKey == null) {
836                e = firstEntry();
837            } else {
838                if (fromInclusive) {
839                    e = ceilingEntry(fromKey);
840                } else {
841                    e = higherEntry(fromKey);
842                }
843            }
844            
845            final K first = e != null ? e.getKey() : null;
846            if (e == null || toKey != null && !inToRange(first, false)) {
847                throw new NoSuchElementException();
848            }
849            return first;
850        }
851 
852        /**
853         * {@inheritDoc}
854         */
855        public K lastKey() {
856            Map.Entry<K,V> e;
857            if (toKey == null) {
858                e = lastEntry();
859            } else {
860                if (toInclusive) {
861                    e = floorEntry(toKey);
862                } else {
863                    e = lowerEntry(toKey);
864                }
865            }
866            
867            final K last = e != null ? e.getKey() : null;
868            if (e == null || fromKey != null && !inFromRange(last, false)) {
869                throw new NoSuchElementException();
870            }
871            return last;
872        }
873        
874        /**
875         * {@inheritDoc}
876         */
877        @Override
878        protected Set<Entry<K, V>> createEntrySet() {
879            return new RangeEntrySet(this);
880        }
881        
882        /**
883         * {@inheritDoc}
884         */
885        @Override
886        public K getFromKey() {
887            return fromKey;
888        }
889 
890        /**
891         * {@inheritDoc}
892         */
893        @Override
894        public K getToKey() {
895            return toKey;
896        }
897 
898        /**
899         * {@inheritDoc}
900         */
901        @Override
902        public boolean isFromInclusive() {
903            return fromInclusive;
904        }
905 
906        /**
907         * {@inheritDoc}
908         */
909        @Override
910        public boolean isToInclusive() {
911            return toInclusive;
912        }
913 
914        /**
915         * {@inheritDoc}
916         */
917        @Override
918        protected SortedMap<K, V> createRangeMap(final K fromKey, final boolean fromInclusive,
919                final K toKey, final boolean toInclusive) {
920            return new RangeEntryMap(fromKey, fromInclusive, toKey, toInclusive);
921        }
922    }
923    
924     /**
925      * A {@link Set} view of a {@link RangeMap}
926      */
927     private class RangeEntrySet extends AbstractSet<Map.Entry<K, V>> {
928 
929         private final RangeMap delegate;
930 
931         private transient int size = -1;
932 
933         private transient int expectedModCount;
934 
935         /**
936          * Creates a {@link RangeEntrySet}
937          */
938         public RangeEntrySet(final RangeMap delegate) {
939             if (delegate == null) {
940                 throw new NullPointerException("delegate");
941             }
942 
943             this.delegate = delegate;
944         }
945 
946         /**
947          * {@inheritDoc}
948          */
949         @Override
950         public Iterator<Map.Entry<K, V>> iterator() {
951             final K fromKey = delegate.getFromKey();
952             final K toKey = delegate.getToKey();
953 
954             TrieEntry<K, V> first = null;
955             if (fromKey == null) {
956                 first = firstEntry();
957             } else {
958                 first = ceilingEntry(fromKey);
959             }
960 
961             TrieEntry<K, V> last = null;
962             if (toKey != null) {
963                 last = ceilingEntry(toKey);
964             }
965 
966             return new EntryIterator(first, last);
967         }
968 
969         /**
970          * {@inheritDoc}
971          */
972         @Override
973         public int size() {
974             if (size == -1 || expectedModCount != PatriciaTrie.this.modCount) {
975                 size = 0;
976 
977                 for (final Iterator<?> it = iterator(); it.hasNext(); it.next()) {
978                     ++size;
979                 }
980 
981                 expectedModCount = PatriciaTrie.this.modCount;
982             }
983             return size;
984         }
985 
986         /**
987          * {@inheritDoc}
988          */
989         @Override
990         public boolean isEmpty() {
991             return !iterator().hasNext();
992         }
993 
994         /**
995          * {@inheritDoc}
996          */
997         @SuppressWarnings("unchecked")
998         @Override
999         public boolean contains(final Object o) {
1000             if (!(o instanceof Map.Entry)) {
1001                 return false;
1002             }
1003 
1004             final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
1005             final K key = entry.getKey();
1006             if (!delegate.inRange(key)) {
1007                 return false;
1008             }
1009 
1010             final TrieEntry<K, V> node = getEntry(key);
1011             return node != null && compare(node.getValue(), entry.getValue());
1012         }
1013 
1014         /**
1015          * {@inheritDoc}
1016          */
1017         @SuppressWarnings("unchecked")
1018         @Override
1019         public boolean remove(final Object o) {
1020             if (!(o instanceof Map.Entry)) {
1021                 return false;
1022             }
1023 
1024             final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
1025             final K key = entry.getKey();
1026             if (!delegate.inRange(key)) {
1027                 return false;
1028             }
1029 
1030             final TrieEntry<K, V> node = getEntry(key);
1031             if (node != null && compare(node.getValue(), entry.getValue())) {
1032                 removeEntry(node);
1033                 return true;
1034             }
1035             return false;
1036         }
1037         
1038         /** 
1039          * An {@link Iterator} for {@link RangeEntrySet}s. 
1040          */
1041         private final class EntryIterator extends TrieIterator<Map.Entry<K,V>> {
1042             
1043             private final K excludedKey;
1044 
1045             /**
1046              * Creates a {@link EntryIterator}
1047              */
1048             private EntryIterator(
1049                     final TrieEntry<K,V> first, 
1050                     final TrieEntry<K,V> last) {
1051                 super(first);
1052                 
1053                 this.excludedKey = last != null ? last.getKey() : null;
1054             }
1055 
1056             /**
1057              * {@inheritDoc}
1058              */
1059             @Override
1060             public boolean hasNext() {
1061                 return next != null && !compare(next.key, excludedKey);
1062             }
1063 
1064             /**
1065              * {@inheritDoc}
1066              */
1067             public Map.Entry<K,V> next() {
1068                 if (next == null || compare(next.key, excludedKey)) {
1069                     throw new NoSuchElementException();
1070                 }
1071                 
1072                 return nextEntry();
1073             }
1074         }
1075     }   
1076    
1077     /** 
1078      * A submap used for prefix views over the {@link Trie}. 
1079      */
1080     private class PrefixRangeMap extends RangeMap {
1081         
1082         private final K prefix;
1083         
1084         private final int offsetInBits;
1085         
1086         private final int lengthInBits;
1087         
1088         private K fromKey = null;
1089         
1090         private K toKey = null;
1091         
1092         private transient int expectedModCount = 0;
1093         
1094         private int size = -1;
1095         
1096         /**
1097          * Creates a {@link PrefixRangeMap}
1098          */
1099         private PrefixRangeMap(final K prefix, final int offsetInBits, final int lengthInBits) {
1100             this.prefix = prefix;
1101             this.offsetInBits = offsetInBits;
1102             this.lengthInBits = lengthInBits;
1103         }
1104         
1105         /**
1106          * This method does two things. It determinates the FROM
1107          * and TO range of the {@link PrefixRangeMap} and the number
1108          * of elements in the range. This method must be called every 
1109          * time the {@link Trie} has changed.
1110          */
1111         private int fixup() {
1112             // The trie has changed since we last
1113             // found our toKey / fromKey
1114             if (size == - 1 || PatriciaTrie.this.modCount != expectedModCount) {
1115                 final Iterator<Map.Entry<K, V>> it = entrySet().iterator();
1116                 size = 0;
1117                 
1118                 Map.Entry<K, V> entry = null;
1119                 if (it.hasNext()) {
1120                     entry = it.next();
1121                     size = 1;
1122                 }
1123                 
1124                 fromKey = entry == null ? null : entry.getKey();
1125                 if (fromKey != null) {
1126                     final TrieEntry<K, V> prior = previousEntry((TrieEntry<K, V>)entry);
1127                     fromKey = prior == null ? null : prior.getKey();
1128                 }
1129                 
1130                 toKey = fromKey;
1131                 
1132                 while (it.hasNext()) {
1133                     ++size;
1134                     entry = it.next();
1135                 }
1136                 
1137                 toKey = entry == null ? null : entry.getKey();
1138                 
1139                 if (toKey != null) {
1140                     entry = nextEntry((TrieEntry<K, V>)entry);
1141                     toKey = entry == null ? null : entry.getKey();
1142                 }
1143                 
1144                 expectedModCount = PatriciaTrie.this.modCount;
1145             }
1146             
1147             return size;
1148         }
1149         
1150         /**
1151          * {@inheritDoc}
1152          */
1153         public K firstKey() {
1154             fixup();
1155             
1156             Map.Entry<K,V> e = null;
1157             if (fromKey == null) {
1158                 e = firstEntry();
1159             } else {
1160                 e = higherEntry(fromKey);
1161             }
1162             
1163             final K first = e != null ? e.getKey() : null;
1164             if (e == null || !keyAnalyzer.isPrefix(prefix, 
1165                     offsetInBits, lengthInBits, first)) {
1166                 throw new NoSuchElementException();
1167             }
1168             
1169             return first;
1170         }
1171 
1172         /**
1173          * {@inheritDoc}
1174          */
1175         public K lastKey() {
1176             fixup();
1177             
1178             Map.Entry<K,V> e = null;
1179             if (toKey == null) {
1180                 e = lastEntry();
1181             } else {
1182                 e = lowerEntry(toKey);
1183             }
1184             
1185             final K last = e != null ? e.getKey() : null;
1186             if (e == null || !keyAnalyzer.isPrefix(prefix, 
1187                     offsetInBits, lengthInBits, last)) {
1188                 throw new NoSuchElementException();
1189             }
1190             
1191             return last;
1192         }
1193         
1194         /**
1195          * Returns true if this {@link PrefixRangeMap}'s key is a prefix
1196          * of the provided key.
1197          */
1198         @Override
1199         protected boolean inRange(final K key) {
1200             return keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, key);
1201         }
1202 
1203         /**
1204          * Same as {@link #inRange(Object)}
1205          */
1206         @Override
1207         protected boolean inRange2(final K key) {
1208             return inRange(key);
1209         }
1210         
1211         /**
1212          * Returns true if the provided Key is in the FROM range
1213          * of the {@link PrefixRangeMap}
1214          */
1215         @Override
1216         protected boolean inFromRange(final K key, final boolean forceInclusive) {
1217             return keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, key);
1218         }
1219         
1220         /**
1221          * Returns true if the provided Key is in the TO range
1222          * of the {@link PrefixRangeMap}
1223          */
1224         @Override
1225         protected boolean inToRange(final K key, final boolean forceInclusive) {
1226             return keyAnalyzer.isPrefix(prefix, offsetInBits, lengthInBits, key);
1227         }
1228         
1229         /**
1230          * {@inheritDoc}
1231          */
1232         @Override
1233         protected Set<Map.Entry<K, V>> createEntrySet() {
1234             return new PrefixRangeEntrySet(this);
1235         }
1236 
1237         /**
1238          * {@inheritDoc}
1239          */
1240         @Override
1241         public K getFromKey() {
1242             return fromKey;
1243         }
1244 
1245         /**
1246          * {@inheritDoc}
1247          */
1248         @Override
1249         public K getToKey() {
1250             return toKey;
1251         }
1252 
1253         /**
1254          * {@inheritDoc}
1255          */
1256         @Override
1257         public boolean isFromInclusive() {
1258             return false;
1259         }
1260 
1261         /**
1262          * {@inheritDoc}
1263          */
1264         @Override
1265         public boolean isToInclusive() {
1266             return false;
1267         }
1268 
1269         /**
1270          * {@inheritDoc}
1271          */
1272         @Override
1273         protected SortedMap<K, V> createRangeMap(
1274                 final K fromKey, final boolean fromInclusive,
1275                 final K toKey, final boolean toInclusive) {
1276             return new RangeEntryMap(fromKey, fromInclusive, toKey, toInclusive);
1277         }
1278     }
1279     
1280     /**
1281      * A prefix {@link RangeEntrySet} view of the {@link Trie}
1282      */
1283     private final class PrefixRangeEntrySet extends RangeEntrySet {
1284         
1285         private final PrefixRangeMap delegate;
1286         
1287         private TrieEntry<K, V> prefixStart;
1288         
1289         private int expectedModCount = 0;
1290         
1291         /**
1292          * Creates a {@link PrefixRangeEntrySet}
1293          */
1294         public PrefixRangeEntrySet(final PrefixRangeMap delegate) {
1295             super(delegate);
1296             this.delegate = delegate;
1297         }
1298         
1299         /**
1300          * {@inheritDoc}
1301          */
1302         @Override
1303         public int size() {
1304             return delegate.fixup();
1305         }
1306 
1307         /**
1308          * {@inheritDoc}
1309          */
1310         @Override
1311         public Iterator<Map.Entry<K,V>> iterator() {
1312             if (PatriciaTrie.this.modCount != expectedModCount) {
1313                 prefixStart = subtree(delegate.prefix, delegate.offsetInBits, delegate.lengthInBits);
1314                 expectedModCount = PatriciaTrie.this.modCount;
1315             }
1316             
1317             if (prefixStart == null) {
1318                 final Set<Map.Entry<K,V>> empty = Collections.emptySet();
1319                 return empty.iterator();
1320             } else if (delegate.lengthInBits >= prefixStart.bitIndex) {
1321                 return new SingletonIterator(prefixStart);
1322             } else {
1323                 return new EntryIterator(prefixStart, delegate.prefix, delegate.offsetInBits, delegate.lengthInBits);
1324             }
1325         }
1326         
1327         /** 
1328          * An {@link Iterator} that holds a single {@link TrieEntry}. 
1329          */
1330         private final class SingletonIterator implements Iterator<Map.Entry<K, V>> {
1331             
1332             private final TrieEntry<K, V> entry;
1333             
1334             private int hit = 0;
1335             
1336             public SingletonIterator(final TrieEntry<K, V> entry) {
1337                 this.entry = entry;
1338             }
1339             
1340             /**
1341              * {@inheritDoc}
1342              */
1343             public boolean hasNext() {
1344                 return hit == 0;
1345             }
1346 
1347             /**
1348              * {@inheritDoc}
1349              */
1350             public Map.Entry<K, V> next() {
1351                 if (hit != 0) {
1352                     throw new NoSuchElementException();
1353                 }
1354                 
1355                 ++hit;
1356                 return entry;
1357             }
1358 
1359             /**
1360              * {@inheritDoc}
1361              */
1362             public void remove() {
1363                 if (hit != 1) {
1364                     throw new IllegalStateException();
1365                 }
1366                 
1367                 ++hit;
1368                 PatriciaTrie.this.removeEntry(entry);
1369             }
1370         }
1371         
1372         /** 
1373          * An {@link Iterator} for iterating over a prefix search. 
1374          */
1375         private final class EntryIterator extends TrieIterator<Map.Entry<K, V>> {
1376             
1377             // values to reset the subtree if we remove it.
1378             protected final K prefix; 
1379             protected final int offset;
1380             protected final int lengthInBits;
1381             protected boolean lastOne;
1382             
1383             protected TrieEntry<K, V> subtree; // the subtree to search within
1384             
1385             /**
1386              * Starts iteration at the given entry & search only 
1387              * within the given subtree.
1388              */
1389             EntryIterator(final TrieEntry<K, V> startScan, final K prefix, 
1390                     final int offset, final int lengthInBits) {
1391                 subtree = startScan;
1392                 next = PatriciaTrie.this.followLeft(startScan);
1393                 this.prefix = prefix;
1394                 this.offset = offset;
1395                 this.lengthInBits = lengthInBits;
1396             }
1397 
1398             /**
1399              * {@inheritDoc}
1400              */
1401             public Map.Entry<K,V> next() {
1402                 final Map.Entry<K, V> entry = nextEntry();
1403                 if (lastOne) {
1404                     next = null;
1405                 }
1406                 return entry;
1407             }
1408             
1409             /**
1410              * {@inheritDoc}
1411              */
1412             @Override
1413             protected TrieEntry<K, V> findNext(final TrieEntry<K, V> prior) {
1414                 return PatriciaTrie.this.nextEntryInSubtree(prior, subtree);
1415             }
1416             
1417             /**
1418              * {@inheritDoc}
1419              */
1420             @Override
1421             public void remove() {
1422                 // If the current entry we're removing is the subtree
1423                 // then we need to find a new subtree parent.
1424                 boolean needsFixing = false;
1425                 final int bitIdx = subtree.bitIndex;
1426                 if (current == subtree) {
1427                     needsFixing = true;
1428                 }
1429                 
1430                 super.remove();
1431                 
1432                 // If the subtree changed its bitIndex or we
1433                 // removed the old subtree, get a new one.
1434                 if (bitIdx != subtree.bitIndex || needsFixing) {
1435                     subtree = subtree(prefix, offset, lengthInBits);
1436                 }
1437                 
1438                 // If the subtree's bitIndex is less than the
1439                 // length of our prefix, it's the last item
1440                 // in the prefix tree.
1441                 if (lengthInBits >= subtree.bitIndex) {
1442                     lastOne = true;
1443                 }
1444             }
1445         }
1446     }
1447 }