AbstractPatriciaTrie.java

  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.collections4.trie;

  18. import java.io.IOException;
  19. import java.io.ObjectInputStream;
  20. import java.io.ObjectOutputStream;
  21. import java.util.AbstractCollection;
  22. import java.util.AbstractMap;
  23. import java.util.AbstractSet;
  24. import java.util.Collection;
  25. import java.util.Collections;
  26. import java.util.Comparator;
  27. import java.util.ConcurrentModificationException;
  28. import java.util.Iterator;
  29. import java.util.Map;
  30. import java.util.NoSuchElementException;
  31. import java.util.Objects;
  32. import java.util.Set;
  33. import java.util.SortedMap;

  34. import org.apache.commons.collections4.OrderedMapIterator;
  35. import org.apache.commons.collections4.Trie;

  36. /**
  37.  * This class implements the base PATRICIA algorithm and everything that
  38.  * is related to the {@link Map} interface.
  39.  *
  40.  * @param <K> the type of the keys in this map
  41.  * @param <V> the type of the values in this map
  42.  * @since 4.0
  43.  */
  44. public abstract class AbstractPatriciaTrie<K, V> extends AbstractBitwiseTrie<K, V> {

  45.     /**
  46.      * A range view of the {@link org.apache.commons.collections4.Trie}.
  47.      */
  48.     private abstract class AbstractRangeMap extends AbstractMap<K, V>
  49.             implements SortedMap<K, V> {

  50.         /** The {@link #entrySet()} view. */
  51.         private transient volatile Set<Map.Entry<K, V>> entrySet;

  52.         @Override
  53.         public Comparator<? super K> comparator() {
  54.             return AbstractPatriciaTrie.this.comparator();
  55.         }

  56.         @Override
  57.         public boolean containsKey(final Object key) {
  58.             if (!inRange(castKey(key))) {
  59.                 return false;
  60.             }

  61.             return AbstractPatriciaTrie.this.containsKey(key);
  62.         }

  63.         /**
  64.          * Creates and returns an {@link #entrySet()} view of the {@link AbstractRangeMap}.
  65.          */
  66.         protected abstract Set<Map.Entry<K, V>> createEntrySet();

  67.         /**
  68.          * Creates and returns a sub-range view of the current {@link AbstractRangeMap}.
  69.          */
  70.         protected abstract SortedMap<K, V> createRangeMap(K fromKey, boolean fromInclusive,
  71.                                                           K toKey, boolean toInclusive);

  72.         @Override
  73.         public Set<Map.Entry<K, V>> entrySet() {
  74.             if (entrySet == null) {
  75.                 entrySet = createEntrySet();
  76.             }
  77.             return entrySet;
  78.         }

  79.         @Override
  80.         public V get(final Object key) {
  81.             if (!inRange(castKey(key))) {
  82.                 return null;
  83.             }

  84.             return AbstractPatriciaTrie.this.get(key);
  85.         }

  86.         /**
  87.          * Gets the FROM Key.
  88.          */
  89.         protected abstract K getFromKey();

  90.         /**
  91.          * Gets the TO Key.
  92.          */
  93.         protected abstract K getToKey();

  94.         @Override
  95.         public SortedMap<K, V> headMap(final K toKey) {
  96.             if (!inRange2(toKey)) {
  97.                 throw new IllegalArgumentException("ToKey is out of range: " + toKey);
  98.             }
  99.             return createRangeMap(getFromKey(), isFromInclusive(), toKey, isToInclusive());
  100.         }

  101.         /**
  102.          * Returns true if the provided key is in the FROM range of the {@link AbstractRangeMap}.
  103.          */
  104.         protected boolean inFromRange(final K key, final boolean forceInclusive) {
  105.             final K fromKey = getFromKey();
  106.             final boolean fromInclusive = isFromInclusive();

  107.             final int ret = getKeyAnalyzer().compare(key, fromKey);
  108.             if (fromInclusive || forceInclusive) {
  109.                 return ret >= 0;
  110.             }
  111.             return ret > 0;
  112.         }

  113.         /**
  114.          * Returns true if the provided key is greater than TO and less than FROM.
  115.          */
  116.         protected boolean inRange(final K key) {
  117.             final K fromKey = getFromKey();
  118.             final K toKey = getToKey();

  119.             return (fromKey == null || inFromRange(key, false)) && (toKey == null || inToRange(key, false));
  120.         }

  121.         /**
  122.          * This form allows the high endpoint (as well as all legit keys).
  123.          */
  124.         protected boolean inRange2(final K key) {
  125.             final K fromKey = getFromKey();
  126.             final K toKey = getToKey();

  127.             return (fromKey == null || inFromRange(key, false)) && (toKey == null || inToRange(key, true));
  128.         }

  129.         /**
  130.          * Returns true if the provided key is in the TO range of the {@link AbstractRangeMap}.
  131.          */
  132.         protected boolean inToRange(final K key, final boolean forceInclusive) {
  133.             final K toKey = getToKey();
  134.             final boolean toInclusive = isToInclusive();

  135.             final int ret = getKeyAnalyzer().compare(key, toKey);
  136.             if (toInclusive || forceInclusive) {
  137.                 return ret <= 0;
  138.             }
  139.             return ret < 0;
  140.         }

  141.         /**
  142.          * Tests whether or not the {@link #getFromKey()} is in the range.
  143.          *
  144.          * @return whether or not the {@link #getFromKey()} is in the range.
  145.          */
  146.         protected abstract boolean isFromInclusive();

  147.         /**
  148.          * Tests whether or not the {@link #getToKey()} is in the range.
  149.          *
  150.          * @return whether or not the {@link #getToKey()} is in the range.
  151.          */
  152.         protected abstract boolean isToInclusive();

  153.         @Override
  154.         public V put(final K key, final V value) {
  155.             if (!inRange(key)) {
  156.                 throw new IllegalArgumentException("Key is out of range: " + key);
  157.             }
  158.             return AbstractPatriciaTrie.this.put(key, value);
  159.         }

  160.         @Override
  161.         public V remove(final Object key) {
  162.             if (!inRange(castKey(key))) {
  163.                 return null;
  164.             }

  165.             return AbstractPatriciaTrie.this.remove(key);
  166.         }

  167.         @Override
  168.         public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
  169.             if (!inRange2(fromKey)) {
  170.                 throw new IllegalArgumentException("FromKey is out of range: " + fromKey);
  171.             }

  172.             if (!inRange2(toKey)) {
  173.                 throw new IllegalArgumentException("ToKey is out of range: " + toKey);
  174.             }

  175.             return createRangeMap(fromKey, isFromInclusive(), toKey, isToInclusive());
  176.         }

  177.         @Override
  178.         public SortedMap<K, V> tailMap(final K fromKey) {
  179.             if (!inRange2(fromKey)) {
  180.                 throw new IllegalArgumentException("FromKey is out of range: " + fromKey);
  181.             }
  182.             return createRangeMap(fromKey, isFromInclusive(), getToKey(), isToInclusive());
  183.         }
  184.     }

  185.     /**
  186.      * An iterator for the entries.
  187.      */
  188.     abstract class AbstractTrieIterator<E> implements Iterator<E> {

  189.         /** For fast-fail. */
  190.         protected int expectedModCount = AbstractPatriciaTrie.this.modCount;

  191.         protected TrieEntry<K, V> next; // the next node to return
  192.         protected TrieEntry<K, V> current; // the current entry we're on

  193.         /**
  194.          * Starts iteration from the root.
  195.          */
  196.         protected AbstractTrieIterator() {
  197.             next = AbstractPatriciaTrie.this.nextEntry(null);
  198.         }

  199.         /**
  200.          * Starts iteration at the given entry.
  201.          */
  202.         protected AbstractTrieIterator(final TrieEntry<K, V> firstEntry) {
  203.             next = firstEntry;
  204.         }

  205.         /**
  206.          * @see PatriciaTrie#nextEntry(TrieEntry)
  207.          */
  208.         protected TrieEntry<K, V> findNext(final TrieEntry<K, V> prior) {
  209.             return AbstractPatriciaTrie.this.nextEntry(prior);
  210.         }

  211.         @Override
  212.         public boolean hasNext() {
  213.             return next != null;
  214.         }

  215.         /**
  216.          * Returns the next {@link TrieEntry}.
  217.          */
  218.         protected TrieEntry<K, V> nextEntry() {
  219.             if (expectedModCount != AbstractPatriciaTrie.this.modCount) {
  220.                 throw new ConcurrentModificationException();
  221.             }

  222.             final TrieEntry<K, V> e = next;
  223.             if (e == null) {
  224.                 throw new NoSuchElementException();
  225.             }

  226.             next = findNext(e);
  227.             current = e;
  228.             return e;
  229.         }

  230.         @Override
  231.         public void remove() {
  232.             if (current == null) {
  233.                 throw new IllegalStateException();
  234.             }

  235.             if (expectedModCount != AbstractPatriciaTrie.this.modCount) {
  236.                 throw new ConcurrentModificationException();
  237.             }

  238.             final TrieEntry<K, V> node = current;
  239.             current = null;
  240.             AbstractPatriciaTrie.this.removeEntry(node);

  241.             expectedModCount = AbstractPatriciaTrie.this.modCount;
  242.         }
  243.     }

  244.     /**
  245.      * This is an entry set view of the {@link org.apache.commons.collections4.Trie} as returned by {@link Map#entrySet()}.
  246.      */
  247.     private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {

  248.         /**
  249.          * An {@link Iterator} that returns {@link Entry} Objects.
  250.          */
  251.         private final class EntryIterator extends AbstractTrieIterator<Map.Entry<K, V>> {
  252.             @Override
  253.             public Map.Entry<K, V> next() {
  254.                 return nextEntry();
  255.             }
  256.         }

  257.         @Override
  258.         public void clear() {
  259.             AbstractPatriciaTrie.this.clear();
  260.         }

  261.         @Override
  262.         public boolean contains(final Object o) {
  263.             if (!(o instanceof Map.Entry)) {
  264.                 return false;
  265.             }

  266.             final TrieEntry<K, V> candidate = getEntry(((Map.Entry<?, ?>) o).getKey());
  267.             return candidate != null && candidate.equals(o);
  268.         }

  269.         @Override
  270.         public Iterator<Map.Entry<K, V>> iterator() {
  271.             return new EntryIterator();
  272.         }

  273.         @Override
  274.         public boolean remove(final Object obj) {
  275.             if (!(obj instanceof Map.Entry)) {
  276.                 return false;
  277.             }
  278.             if (!contains(obj)) {
  279.                 return false;
  280.             }
  281.             final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
  282.             AbstractPatriciaTrie.this.remove(entry.getKey());
  283.             return true;
  284.         }

  285.         @Override
  286.         public int size() {
  287.             return AbstractPatriciaTrie.this.size();
  288.         }
  289.     }
  290.     /**
  291.      * This is a key set view of the {@link org.apache.commons.collections4.Trie} as returned by {@link Map#keySet()}.
  292.      */
  293.     private final class KeySet extends AbstractSet<K> {

  294.         /**
  295.          * An {@link Iterator} that returns Key Objects.
  296.          */
  297.         private final class KeyIterator extends AbstractTrieIterator<K> {
  298.             @Override
  299.             public K next() {
  300.                 return nextEntry().getKey();
  301.             }
  302.         }

  303.         @Override
  304.         public void clear() {
  305.             AbstractPatriciaTrie.this.clear();
  306.         }

  307.         @Override
  308.         public boolean contains(final Object o) {
  309.             return containsKey(o);
  310.         }

  311.         @Override
  312.         public Iterator<K> iterator() {
  313.             return new KeyIterator();
  314.         }

  315.         @Override
  316.         public boolean remove(final Object o) {
  317.             final int size = size();
  318.             AbstractPatriciaTrie.this.remove(o);
  319.             return size != size();
  320.         }

  321.         @Override
  322.         public int size() {
  323.             return AbstractPatriciaTrie.this.size();
  324.         }
  325.     }
  326.     /**
  327.      * A prefix {@link RangeEntrySet} view of the {@link org.apache.commons.collections4.Trie}.
  328.      */
  329.     private final class PrefixRangeEntrySet extends RangeEntrySet {

  330.         /**
  331.          * An {@link Iterator} for iterating over a prefix search.
  332.          */
  333.         private final class EntryIterator extends AbstractTrieIterator<Map.Entry<K, V>> {

  334.             // values to reset the subtree if we remove it.
  335.             private final K prefix;
  336.             private final int offset;
  337.             private final int lengthInBits;
  338.             private boolean lastOne;

  339.             private TrieEntry<K, V> subtree; // the subtree to search within

  340.             /**
  341.              * Starts iteration at the given entry &amp; search only
  342.              * within the given subtree.
  343.              */
  344.             EntryIterator(final TrieEntry<K, V> startScan, final K prefix,
  345.                     final int offset, final int lengthInBits) {
  346.                 subtree = startScan;
  347.                 next = AbstractPatriciaTrie.this.followLeft(startScan);
  348.                 this.prefix = prefix;
  349.                 this.offset = offset;
  350.                 this.lengthInBits = lengthInBits;
  351.             }

  352.             @Override
  353.             protected TrieEntry<K, V> findNext(final TrieEntry<K, V> prior) {
  354.                 return AbstractPatriciaTrie.this.nextEntryInSubtree(prior, subtree);
  355.             }

  356.             @Override
  357.             public Map.Entry<K, V> next() {
  358.                 final Map.Entry<K, V> entry = nextEntry();
  359.                 if (lastOne) {
  360.                     next = null;
  361.                 }
  362.                 return entry;
  363.             }

  364.             @Override
  365.             public void remove() {
  366.                 // If the current entry we're removing is the subtree
  367.                 // then we need to find a new subtree parent.
  368.                 boolean needsFixing = false;
  369.                 final int bitIdx = subtree.bitIndex;
  370.                 if (current == subtree) {
  371.                     needsFixing = true;
  372.                 }

  373.                 super.remove();

  374.                 // If the subtree changed its bitIndex or we
  375.                 // removed the old subtree, get a new one.
  376.                 if (bitIdx != subtree.bitIndex || needsFixing) {
  377.                     subtree = subtree(prefix, offset, lengthInBits);
  378.                 }

  379.                 // If the subtree's bitIndex is less than the
  380.                 // length of our prefix, it's the last item
  381.                 // in the prefix tree.
  382.                 if (lengthInBits >= subtree.bitIndex) {
  383.                     lastOne = true;
  384.                 }
  385.             }
  386.         }

  387.         /**
  388.          * An {@link Iterator} that holds a single {@link TrieEntry}.
  389.          */
  390.         private final class SingletonIterator implements Iterator<Map.Entry<K, V>> {

  391.             private final TrieEntry<K, V> entry;

  392.             private int hit;

  393.             SingletonIterator(final TrieEntry<K, V> entry) {
  394.                 this.entry = entry;
  395.             }

  396.             @Override
  397.             public boolean hasNext() {
  398.                 return hit == 0;
  399.             }

  400.             @Override
  401.             public Map.Entry<K, V> next() {
  402.                 if (hit != 0) {
  403.                     throw new NoSuchElementException();
  404.                 }

  405.                 ++hit;
  406.                 return entry;
  407.             }

  408.             @Override
  409.             public void remove() {
  410.                 if (hit != 1) {
  411.                     throw new IllegalStateException();
  412.                 }

  413.                 ++hit;
  414.                 AbstractPatriciaTrie.this.removeEntry(entry);
  415.             }
  416.         }

  417.         private final PrefixRangeMap delegate;

  418.         private TrieEntry<K, V> prefixStart;

  419.         private int expectedModCount;

  420.         /**
  421.          * Creates a {@link PrefixRangeEntrySet}.
  422.          */
  423.         PrefixRangeEntrySet(final PrefixRangeMap delegate) {
  424.             super(delegate);
  425.             this.delegate = delegate;
  426.         }

  427.         @Override
  428.         public Iterator<Map.Entry<K, V>> iterator() {
  429.             if (AbstractPatriciaTrie.this.modCount != expectedModCount) {
  430.                 prefixStart = subtree(delegate.prefix, delegate.offsetInBits, delegate.lengthInBits);
  431.                 expectedModCount = AbstractPatriciaTrie.this.modCount;
  432.             }

  433.             if (prefixStart == null) {
  434.                 final Set<Map.Entry<K, V>> empty = Collections.emptySet();
  435.                 return empty.iterator();
  436.             }
  437.             if (delegate.lengthInBits > prefixStart.bitIndex) {
  438.                 return new SingletonIterator(prefixStart);
  439.             }
  440.             return new EntryIterator(prefixStart, delegate.prefix, delegate.offsetInBits, delegate.lengthInBits);
  441.         }

  442.         @Override
  443.         public int size() {
  444.             return delegate.fixup();
  445.         }
  446.     }

  447.     /**
  448.      * A submap used for prefix views over the {@link org.apache.commons.collections4.Trie}.
  449.      */
  450.     private final class PrefixRangeMap extends AbstractRangeMap {

  451.         private final K prefix;

  452.         private final int offsetInBits;

  453.         private final int lengthInBits;

  454.         private K fromKey;

  455.         private K toKey;

  456.         private transient int expectedModCount;

  457.         private int size = -1;

  458.         /**
  459.          * Creates a {@link PrefixRangeMap}.
  460.          */
  461.         private PrefixRangeMap(final K prefix, final int offsetInBits, final int lengthInBits) {
  462.             this.prefix = prefix;
  463.             this.offsetInBits = offsetInBits;
  464.             this.lengthInBits = lengthInBits;
  465.         }

  466.         @Override
  467.         public void clear() {
  468.             final Iterator<Map.Entry<K, V>> it = AbstractPatriciaTrie.this.entrySet().iterator();
  469.             final Set<K> currentKeys = keySet();
  470.             while (it.hasNext()) {
  471.                 if (currentKeys.contains(it.next().getKey())) {
  472.                     it.remove();
  473.                 }
  474.             }
  475.         }

  476.         @Override
  477.         protected Set<Map.Entry<K, V>> createEntrySet() {
  478.             return new PrefixRangeEntrySet(this);
  479.         }

  480.         @Override
  481.         protected SortedMap<K, V> createRangeMap(final K fromKey, final boolean fromInclusive,
  482.                                                  final K toKey, final boolean toInclusive) {
  483.             return new RangeEntryMap(fromKey, fromInclusive, toKey, toInclusive);
  484.         }

  485.         @Override
  486.         public K firstKey() {
  487.             fixup();

  488.             Map.Entry<K, V> e = null;
  489.             if (fromKey == null) {
  490.                 e = firstEntry();
  491.             } else {
  492.                 e = higherEntry(fromKey);
  493.             }

  494.             final K first = e != null ? e.getKey() : null;
  495.             if (e == null || !getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, first)) {
  496.                 throw new NoSuchElementException();
  497.             }

  498.             return first;
  499.         }

  500.         /**
  501.          * This method does two things. It determines the FROM
  502.          * and TO range of the {@link PrefixRangeMap} and the number
  503.          * of elements in the range. This method must be called every
  504.          * time the {@link org.apache.commons.collections4.Trie} has changed.
  505.          */
  506.         private int fixup() {
  507.             // The trie has changed since we last found our toKey / fromKey
  508.             if (size == - 1 || AbstractPatriciaTrie.this.modCount != expectedModCount) {
  509.                 final Iterator<Map.Entry<K, V>> it = super.entrySet().iterator();
  510.                 size = 0;

  511.                 Map.Entry<K, V> entry = null;
  512.                 if (it.hasNext()) {
  513.                     entry = it.next();
  514.                     size = 1;
  515.                 }

  516.                 fromKey = entry == null ? null : entry.getKey();
  517.                 if (fromKey != null) {
  518.                     final TrieEntry<K, V> prior = previousEntry((TrieEntry<K, V>) entry);
  519.                     fromKey = prior == null ? null : prior.getKey();
  520.                 }

  521.                 toKey = fromKey;

  522.                 while (it.hasNext()) {
  523.                     ++size;
  524.                     entry = it.next();
  525.                 }

  526.                 toKey = entry == null ? null : entry.getKey();

  527.                 if (toKey != null) {
  528.                     entry = nextEntry((TrieEntry<K, V>) entry);
  529.                     toKey = entry == null ? null : entry.getKey();
  530.                 }

  531.                 expectedModCount = AbstractPatriciaTrie.this.modCount;
  532.             }

  533.             return size;
  534.         }

  535.         @Override
  536.         public K getFromKey() {
  537.             return fromKey;
  538.         }

  539.         @Override
  540.         public K getToKey() {
  541.             return toKey;
  542.         }

  543.         /**
  544.          * Returns true if the provided Key is in the FROM range of the {@link PrefixRangeMap}.
  545.          */
  546.         @Override
  547.         protected boolean inFromRange(final K key, final boolean forceInclusive) {
  548.             return getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, key);
  549.         }

  550.         /**
  551.          * Returns true if this {@link PrefixRangeMap}'s key is a prefix of the provided key.
  552.          */
  553.         @Override
  554.         protected boolean inRange(final K key) {
  555.             return getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, key);
  556.         }

  557.         /**
  558.          * Same as {@link #inRange(Object)}.
  559.          */
  560.         @Override
  561.         protected boolean inRange2(final K key) {
  562.             return inRange(key);
  563.         }

  564.         /**
  565.          * Returns true if the provided Key is in the TO range of the {@link PrefixRangeMap}.
  566.          */
  567.         @Override
  568.         protected boolean inToRange(final K key, final boolean forceInclusive) {
  569.             return getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, key);
  570.         }

  571.         @Override
  572.         public boolean isFromInclusive() {
  573.             return false;
  574.         }

  575.         @Override
  576.         public boolean isToInclusive() {
  577.             return false;
  578.         }

  579.         @Override
  580.         public K lastKey() {
  581.             fixup();

  582.             Map.Entry<K, V> e = null;
  583.             if (toKey == null) {
  584.                 e = lastEntry();
  585.             } else {
  586.                 e = lowerEntry(toKey);
  587.             }

  588.             final K last = e != null ? e.getKey() : null;
  589.             if (e == null || !getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, last)) {
  590.                 throw new NoSuchElementException();
  591.             }

  592.             return last;
  593.         }
  594.     }

  595.     /**
  596.      * A {@link AbstractRangeMap} that deals with {@link Entry}s.
  597.      */
  598.     private final class RangeEntryMap extends AbstractRangeMap {

  599.         /** The key to start from, null if the beginning. */
  600.         private final K fromKey;

  601.         /** The key to end at, null if till the end. */
  602.         private final K toKey;

  603.         /** Whether or not the 'from' is inclusive. */
  604.         private final boolean fromInclusive;

  605.         /** Whether or not the 'to' is inclusive. */
  606.         private final boolean toInclusive;

  607.         /**
  608.          * Creates a {@link RangeEntryMap}.
  609.          */
  610.         protected RangeEntryMap(final K fromKey, final boolean fromInclusive,
  611.                                 final K toKey, final boolean toInclusive) {

  612.             if (fromKey == null && toKey == null) {
  613.                 throw new IllegalArgumentException("must have a from or to!");
  614.             }

  615.             if (fromKey != null && toKey != null && getKeyAnalyzer().compare(fromKey, toKey) > 0) {
  616.                 throw new IllegalArgumentException("fromKey > toKey");
  617.             }

  618.             this.fromKey = fromKey;
  619.             this.fromInclusive = fromInclusive;
  620.             this.toKey = toKey;
  621.             this.toInclusive = toInclusive;
  622.         }

  623.         /**
  624.          * Creates a {@link RangeEntryMap} with the fromKey included and
  625.          * the toKey excluded from the range.
  626.          */
  627.         protected RangeEntryMap(final K fromKey, final K toKey) {
  628.             this(fromKey, true, toKey, false);
  629.         }

  630.         @Override
  631.         protected Set<Entry<K, V>> createEntrySet() {
  632.             return new RangeEntrySet(this);
  633.         }

  634.         @Override
  635.         protected SortedMap<K, V> createRangeMap(final K fromKey, final boolean fromInclusive,
  636.                                                  final K toKey, final boolean toInclusive) {
  637.             return new RangeEntryMap(fromKey, fromInclusive, toKey, toInclusive);
  638.         }

  639.         @Override
  640.         public K firstKey() {
  641.             Map.Entry<K, V> e = null;
  642.             if (fromKey == null) {
  643.                 e = firstEntry();
  644.             } else if (fromInclusive) {
  645.                 e = ceilingEntry(fromKey);
  646.             } else {
  647.                 e = higherEntry(fromKey);
  648.             }

  649.             final K first = e != null ? e.getKey() : null;
  650.             if (e == null || toKey != null && !inToRange(first, false)) {
  651.                 throw new NoSuchElementException();
  652.             }
  653.             return first;
  654.         }

  655.         @Override
  656.         public K getFromKey() {
  657.             return fromKey;
  658.         }

  659.         @Override
  660.         public K getToKey() {
  661.             return toKey;
  662.         }

  663.         @Override
  664.         public boolean isFromInclusive() {
  665.             return fromInclusive;
  666.         }

  667.         @Override
  668.         public boolean isToInclusive() {
  669.             return toInclusive;
  670.         }

  671.         @Override
  672.         public K lastKey() {
  673.             final Map.Entry<K, V> e;
  674.             if (toKey == null) {
  675.                 e = lastEntry();
  676.             } else if (toInclusive) {
  677.                 e = floorEntry(toKey);
  678.             } else {
  679.                 e = lowerEntry(toKey);
  680.             }

  681.             final K last = e != null ? e.getKey() : null;
  682.             if (e == null || fromKey != null && !inFromRange(last, false)) {
  683.                 throw new NoSuchElementException();
  684.             }
  685.             return last;
  686.         }
  687.     }

  688.     /**
  689.      * A {@link Set} view of a {@link AbstractRangeMap}.
  690.      */
  691.     private class RangeEntrySet extends AbstractSet<Map.Entry<K, V>> {

  692.         /**
  693.          * An {@link Iterator} for {@link RangeEntrySet}s.
  694.          */
  695.         private final class EntryIterator extends AbstractTrieIterator<Map.Entry<K, V>> {

  696.             private final K excludedKey;

  697.             /**
  698.              * Creates a {@link EntryIterator}.
  699.              */
  700.             private EntryIterator(final TrieEntry<K, V> first, final TrieEntry<K, V> last) {
  701.                 super(first);
  702.                 this.excludedKey = last != null ? last.getKey() : null;
  703.             }

  704.             @Override
  705.             public boolean hasNext() {
  706.                 return next != null && !compare(next.key, excludedKey);
  707.             }

  708.             @Override
  709.             public Map.Entry<K, V> next() {
  710.                 if (next == null || compare(next.key, excludedKey)) {
  711.                     throw new NoSuchElementException();
  712.                 }
  713.                 return nextEntry();
  714.             }
  715.         }

  716.         private final AbstractRangeMap delegate;

  717.         private transient int size = -1;

  718.         private transient int expectedModCount;

  719.         /**
  720.          * Creates a {@link RangeEntrySet}.
  721.          */
  722.         RangeEntrySet(final AbstractRangeMap delegate) {
  723.             this.delegate = Objects.requireNonNull(delegate, "delegate");
  724.         }

  725.         @SuppressWarnings("unchecked")
  726.         @Override
  727.         public boolean contains(final Object o) {
  728.             if (!(o instanceof Map.Entry)) {
  729.                 return false;
  730.             }

  731.             final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
  732.             final K key = entry.getKey();
  733.             if (!delegate.inRange(key)) {
  734.                 return false;
  735.             }

  736.             final TrieEntry<K, V> node = getEntry(key);
  737.             return node != null && compare(node.getValue(), entry.getValue());
  738.         }

  739.         @Override
  740.         public boolean isEmpty() {
  741.             return !iterator().hasNext();
  742.         }

  743.         @Override
  744.         public Iterator<Map.Entry<K, V>> iterator() {
  745.             final K fromKey = delegate.getFromKey();
  746.             final K toKey = delegate.getToKey();

  747.             TrieEntry<K, V> first = null;
  748.             if (fromKey == null) {
  749.                 first = firstEntry();
  750.             } else {
  751.                 first = ceilingEntry(fromKey);
  752.             }

  753.             TrieEntry<K, V> last = null;
  754.             if (toKey != null) {
  755.                 last = ceilingEntry(toKey);
  756.             }

  757.             return new EntryIterator(first, last);
  758.         }

  759.         @SuppressWarnings("unchecked")
  760.         @Override
  761.         public boolean remove(final Object o) {
  762.             if (!(o instanceof Map.Entry)) {
  763.                 return false;
  764.             }

  765.             final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
  766.             final K key = entry.getKey();
  767.             if (!delegate.inRange(key)) {
  768.                 return false;
  769.             }

  770.             final TrieEntry<K, V> node = getEntry(key);
  771.             if (node != null && compare(node.getValue(), entry.getValue())) {
  772.                 removeEntry(node);
  773.                 return true;
  774.             }
  775.             return false;
  776.         }

  777.         @Override
  778.         public int size() {
  779.             if (size == -1 || expectedModCount != AbstractPatriciaTrie.this.modCount) {
  780.                 size = 0;

  781.                 for (final Iterator<?> it = iterator(); it.hasNext(); it.next()) {
  782.                     ++size;
  783.                 }

  784.                 expectedModCount = AbstractPatriciaTrie.this.modCount;
  785.             }
  786.             return size;
  787.         }
  788.     }

  789.     /**
  790.      * A {@link Reference} allows us to return something through a Method's
  791.      * argument list. An alternative would be to an Array with a length of
  792.      * one (1) but that leads to compiler warnings. Computationally and memory
  793.      * wise there's no difference (except for the need to load the
  794.      * {@link Reference} Class but that happens only once).
  795.      */
  796.     private static final class Reference<E> {

  797.         private E item;

  798.         public E get() {
  799.             return item;
  800.         }

  801.         public void set(final E item) {
  802.             this.item = item;
  803.         }
  804.     }

  805.     /**
  806.      * A {@link org.apache.commons.collections4.Trie} is a set of {@link TrieEntry} nodes.
  807.      *
  808.      * @param <K> the key type.
  809.      * @param <V> the value type.
  810.      */
  811.     protected static class TrieEntry<K, V> extends BasicEntry<K, V> {

  812.         private static final long serialVersionUID = 4596023148184140013L;

  813.         /** The index this entry is comparing. */
  814.         protected int bitIndex;

  815.         /** The parent of this entry. */
  816.         protected TrieEntry<K, V> parent;

  817.         /** The left child of this entry. */
  818.         protected TrieEntry<K, V> left;

  819.         /** The right child of this entry. */
  820.         protected TrieEntry<K, V> right;

  821.         /** The entry who uplinks to this entry. */
  822.         protected TrieEntry<K, V> predecessor;

  823.         /**
  824.          * Constructs a new instance.
  825.          *
  826.          * @param key The entry's key.
  827.          * @param value The entry's value.
  828.          * @param bitIndex The entry's bitIndex.
  829.          */
  830.         public TrieEntry(final K key, final V value, final int bitIndex) {
  831.             super(key, value);
  832.             this.bitIndex = bitIndex;
  833.             this.parent = null;
  834.             this.left = this;
  835.             this.right = null;
  836.             this.predecessor = this;
  837.         }

  838.         /**
  839.          * Tests whether the entry is storing a key. Only the root can potentially be empty, all other nodes must have a key.
  840.          *
  841.          * @return Whether the entry is storing a key
  842.          */
  843.         public boolean isEmpty() {
  844.             return key == null;
  845.         }

  846.         /**
  847.          * Tests whether the left or right child is a loopback.
  848.          *
  849.          * @return Whether the left or right child is a loopback.
  850.          */
  851.         public boolean isExternalNode() {
  852.             return !isInternalNode();
  853.         }

  854.         /**
  855.          * Tests that neither the left nor right child is a loopback.
  856.          *
  857.          * @return That neither the left nor right child is a loopback.
  858.          */
  859.         public boolean isInternalNode() {
  860.             return left != this && right != this;
  861.         }

  862.         @Override
  863.         public String toString() {
  864.             final StringBuilder buffer = new StringBuilder();

  865.             if (bitIndex == -1) {
  866.                 buffer.append("RootEntry(");
  867.             } else {
  868.                 buffer.append("Entry(");
  869.             }

  870.             buffer.append("key=").append(getKey()).append(" [").append(bitIndex).append("], ");
  871.             buffer.append("value=").append(getValue()).append(", ");
  872.             //buffer.append("bitIndex=").append(bitIndex).append(", ");

  873.             if (parent != null) {
  874.                 if (parent.bitIndex == -1) {
  875.                     buffer.append("parent=").append("ROOT");
  876.                 } else {
  877.                     buffer.append("parent=").append(parent.getKey()).append(" [").append(parent.bitIndex).append("]");
  878.                 }
  879.             } else {
  880.                 buffer.append("parent=").append("null");
  881.             }
  882.             buffer.append(", ");

  883.             if (left != null) {
  884.                 if (left.bitIndex == -1) {
  885.                     buffer.append("left=").append("ROOT");
  886.                 } else {
  887.                     buffer.append("left=").append(left.getKey()).append(" [").append(left.bitIndex).append("]");
  888.                 }
  889.             } else {
  890.                 buffer.append("left=").append("null");
  891.             }
  892.             buffer.append(", ");

  893.             if (right != null) {
  894.                 if (right.bitIndex == -1) {
  895.                     buffer.append("right=").append("ROOT");
  896.                 } else {
  897.                     buffer.append("right=").append(right.getKey()).append(" [").append(right.bitIndex).append("]");
  898.                 }
  899.             } else {
  900.                 buffer.append("right=").append("null");
  901.             }
  902.             buffer.append(", ");

  903.             if (predecessor != null) {
  904.                 if (predecessor.bitIndex == -1) {
  905.                     buffer.append("predecessor=").append("ROOT");
  906.                 } else {
  907.                     buffer.append("predecessor=").append(predecessor.getKey()).append(" [").
  908.                            append(predecessor.bitIndex).append("]");
  909.                 }
  910.             }

  911.             buffer.append(")");
  912.             return buffer.toString();
  913.         }
  914.     }

  915.     /**
  916.      * An {@link OrderedMapIterator} for a {@link org.apache.commons.collections4.Trie}.
  917.      */
  918.     private final class TrieMapIterator extends AbstractTrieIterator<K> implements OrderedMapIterator<K, V> {

  919.         protected TrieEntry<K, V> previous; // the previous node to return

  920.         @Override
  921.         public K getKey() {
  922.             if (current == null) {
  923.                 throw new IllegalStateException();
  924.             }
  925.             return current.getKey();
  926.         }

  927.         @Override
  928.         public V getValue() {
  929.             if (current == null) {
  930.                 throw new IllegalStateException();
  931.             }
  932.             return current.getValue();
  933.         }

  934.         @Override
  935.         public boolean hasPrevious() {
  936.             return previous != null;
  937.         }

  938.         @Override
  939.         public K next() {
  940.             return nextEntry().getKey();
  941.         }

  942.         @Override
  943.         protected TrieEntry<K, V> nextEntry() {
  944.             final TrieEntry<K, V> nextEntry = super.nextEntry();
  945.             previous = nextEntry;
  946.             return nextEntry;
  947.         }

  948.         @Override
  949.         public K previous() {
  950.             return previousEntry().getKey();
  951.         }

  952.         protected TrieEntry<K, V> previousEntry() {
  953.             if (expectedModCount != AbstractPatriciaTrie.this.modCount) {
  954.                 throw new ConcurrentModificationException();
  955.             }

  956.             final TrieEntry<K, V> e = previous;
  957.             if (e == null) {
  958.                 throw new NoSuchElementException();
  959.             }

  960.             previous = AbstractPatriciaTrie.this.previousEntry(e);
  961.             next = current;
  962.             current = e;
  963.             return current;
  964.         }

  965.         @Override
  966.         public V setValue(final V value) {
  967.             if (current == null) {
  968.                 throw new IllegalStateException();
  969.             }
  970.             return current.setValue(value);
  971.         }

  972.     }

  973.     /**
  974.      * This is a value view of the {@link org.apache.commons.collections4.Trie} as returned by {@link Map#values()}.
  975.      */
  976.     private final class Values extends AbstractCollection<V> {

  977.         /**
  978.          * An {@link Iterator} that returns Value Objects.
  979.          */
  980.         private final class ValueIterator extends AbstractTrieIterator<V> {
  981.             @Override
  982.             public V next() {
  983.                 return nextEntry().getValue();
  984.             }
  985.         }

  986.         @Override
  987.         public void clear() {
  988.             AbstractPatriciaTrie.this.clear();
  989.         }

  990.         @Override
  991.         public boolean contains(final Object o) {
  992.             return containsValue(o);
  993.         }

  994.         @Override
  995.         public Iterator<V> iterator() {
  996.             return new ValueIterator();
  997.         }

  998.         @Override
  999.         public boolean remove(final Object o) {
  1000.             for (final Iterator<V> it = iterator(); it.hasNext(); ) {
  1001.                 final V value = it.next();
  1002.                 if (compare(value, o)) {
  1003.                     it.remove();
  1004.                     return true;
  1005.                 }
  1006.             }
  1007.             return false;
  1008.         }

  1009.         @Override
  1010.         public int size() {
  1011.             return AbstractPatriciaTrie.this.size();
  1012.         }
  1013.     }

  1014.     private static final long serialVersionUID = 5155253417231339498L;

  1015.     /**
  1016.      * Returns true if 'next' is a valid uplink coming from 'from'.
  1017.      */
  1018.     static boolean isValidUplink(final TrieEntry<?, ?> next, final TrieEntry<?, ?> from) {
  1019.         return next != null && next.bitIndex <= from.bitIndex && !next.isEmpty();
  1020.     }

  1021.     /** The root node of the {@link org.apache.commons.collections4.Trie}. */
  1022.     private transient TrieEntry<K, V> root = new TrieEntry<>(null, null, -1);

  1023.     /**
  1024.      * Each of these fields are initialized to contain an instance of the
  1025.      * appropriate view the first time this view is requested. The views are
  1026.      * stateless, so there's no reason to create more than one of each.
  1027.      */
  1028.     private transient volatile Set<K> keySet;

  1029.     private transient volatile Collection<V> values;

  1030.     private transient volatile Set<Map.Entry<K, V>> entrySet;

  1031.     /** The current size of the {@link org.apache.commons.collections4.Trie}. */
  1032.     private transient int size;

  1033.     /**
  1034.      * The number of times this {@link org.apache.commons.collections4.Trie} has been modified.
  1035.      * It's used to detect concurrent modifications and fail-fast the {@link Iterator}s.
  1036.      */
  1037.     protected transient int modCount;

  1038.     /**
  1039.      * Constructs a new {@link Trie} using the given {@link KeyAnalyzer}.
  1040.      *
  1041.      * @param keyAnalyzer  the {@link KeyAnalyzer}.
  1042.      */
  1043.     protected AbstractPatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer) {
  1044.         super(keyAnalyzer);
  1045.     }

  1046.     /**
  1047.      * Constructs a new {@link org.apache.commons.collections4.Trie} using the given {@link KeyAnalyzer} and initializes the
  1048.      * {@link org.apache.commons.collections4.Trie} with the values from the provided {@link Map}.
  1049.      *
  1050.      * @param keyAnalyzer  the {@link KeyAnalyzer}.
  1051.      * @param map The source map.
  1052.      */
  1053.     protected AbstractPatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer, final Map<? extends K, ? extends V> map) {
  1054.         super(keyAnalyzer);
  1055.         putAll(map);
  1056.     }

  1057.     /**
  1058.      * Adds the given {@link TrieEntry} to the {@link org.apache.commons.collections4.Trie}.
  1059.      */
  1060.     TrieEntry<K, V> addEntry(final TrieEntry<K, V> entry, final int lengthInBits) {
  1061.         TrieEntry<K, V> current = root.left;
  1062.         TrieEntry<K, V> path = root;
  1063.         while (true) {
  1064.             if (current.bitIndex >= entry.bitIndex
  1065.                     || current.bitIndex <= path.bitIndex) {
  1066.                 entry.predecessor = entry;

  1067.                 if (!isBitSet(entry.key, entry.bitIndex, lengthInBits)) {
  1068.                     entry.left = entry;
  1069.                     entry.right = current;
  1070.                 } else {
  1071.                     entry.left = current;
  1072.                     entry.right = entry;
  1073.                 }

  1074.                 entry.parent = path;
  1075.                 if (current.bitIndex >= entry.bitIndex) {
  1076.                     current.parent = entry;
  1077.                 }

  1078.                 // if we inserted an uplink, set the predecessor on it
  1079.                 if (current.bitIndex <= path.bitIndex) {
  1080.                     current.predecessor = entry;
  1081.                 }

  1082.                 if (path == root || !isBitSet(entry.key, path.bitIndex, lengthInBits)) {
  1083.                     path.left = entry;
  1084.                 } else {
  1085.                     path.right = entry;
  1086.                 }

  1087.                 return entry;
  1088.             }

  1089.             path = current;

  1090.             if (!isBitSet(entry.key, current.bitIndex, lengthInBits)) {
  1091.                 current = current.left;
  1092.             } else {
  1093.                 current = current.right;
  1094.             }
  1095.         }
  1096.     }

  1097.     /**
  1098.      * Returns a key-value mapping associated with the least key greater
  1099.      * than or equal to the given key, or null if there is no such key.
  1100.      */
  1101.     TrieEntry<K, V> ceilingEntry(final K key) {
  1102.         // Basically:
  1103.         // Follow the steps of adding an entry, but instead...
  1104.         //
  1105.         // - If we ever encounter a situation where we found an equal
  1106.         //   key, we return it immediately.
  1107.         //
  1108.         // - If we hit an empty root, return the first iterable item.
  1109.         //
  1110.         // - If we have to add a new item, we temporarily add it,
  1111.         //   find the successor to it, then remove the added item.
  1112.         //
  1113.         // These steps ensure that the returned value is either the
  1114.         // entry for the key itself, or the first entry directly after
  1115.         // the key.

  1116.         // TODO: Cleanup so that we don't actually have to add/remove from the
  1117.         //       tree.  (We do it here because there are other well-defined
  1118.         //       functions to perform the search.)
  1119.         final int lengthInBits = lengthInBits(key);

  1120.         if (lengthInBits == 0) {
  1121.             if (!root.isEmpty()) {
  1122.                 return root;
  1123.             }
  1124.             return firstEntry();
  1125.         }

  1126.         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
  1127.         if (compareKeys(key, found.key)) {
  1128.             return found;
  1129.         }

  1130.         final int bitIndex = bitIndex(key, found.key);
  1131.         if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
  1132.             final TrieEntry<K, V> added = new TrieEntry<>(key, null, bitIndex);
  1133.             addEntry(added, lengthInBits);
  1134.             incrementSize(); // must increment because remove will decrement
  1135.             final TrieEntry<K, V> ceil = nextEntry(added);
  1136.             removeEntry(added);
  1137.             modCount -= 2; // we didn't really modify it.
  1138.             return ceil;
  1139.         }
  1140.         if (KeyAnalyzer.isNullBitKey(bitIndex)) {
  1141.             if (!root.isEmpty()) {
  1142.                 return root;
  1143.             }
  1144.             return firstEntry();
  1145.         }
  1146.         if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
  1147.             return found;
  1148.         }

  1149.         // we should have exited above.
  1150.         throw new IllegalStateException("invalid lookup: " + key);
  1151.     }

  1152.     @Override
  1153.     public void clear() {
  1154.         root.key = null;
  1155.         root.bitIndex = -1;
  1156.         root.value = null;

  1157.         root.parent = null;
  1158.         root.left = root;
  1159.         root.right = null;
  1160.         root.predecessor = root;

  1161.         size = 0;
  1162.         incrementModCount();
  1163.     }

  1164.     @Override
  1165.     public Comparator<? super K> comparator() {
  1166.         return getKeyAnalyzer();
  1167.     }

  1168.     @Override
  1169.     public boolean containsKey(final Object k) {
  1170.         if (k == null) {
  1171.             return false;
  1172.         }

  1173.         final K key = castKey(k);
  1174.         final int lengthInBits = lengthInBits(key);
  1175.         final TrieEntry<K, V> entry = getNearestEntryForKey(key, lengthInBits);
  1176.         return !entry.isEmpty() && compareKeys(key, entry.key);
  1177.     }

  1178.     /**
  1179.      * A helper method to decrement the {@link org.apache.commons.collections4.Trie} size and increment the modification counter.
  1180.      */
  1181.     void decrementSize() {
  1182.         size--;
  1183.         incrementModCount();
  1184.     }

  1185.     @Override
  1186.     public Set<Map.Entry<K, V>> entrySet() {
  1187.         if (entrySet == null) {
  1188.             entrySet = new EntrySet();
  1189.         }
  1190.         return entrySet;
  1191.     }

  1192.     /**
  1193.      * Returns the first entry the {@link org.apache.commons.collections4.Trie} is storing.
  1194.      * <p>
  1195.      * This is implemented by going always to the left until
  1196.      * we encounter a valid uplink. That uplink is the first key.
  1197.      */
  1198.     TrieEntry<K, V> firstEntry() {
  1199.         // if Trie is empty, no first node.
  1200.         if (isEmpty()) {
  1201.             return null;
  1202.         }

  1203.         return followLeft(root);
  1204.     }

  1205.     @Override
  1206.     public K firstKey() {
  1207.         if (isEmpty()) {
  1208.             throw new NoSuchElementException();
  1209.         }
  1210.         return firstEntry().getKey();
  1211.     }

  1212.     /**
  1213.      * Returns a key-value mapping associated with the greatest key
  1214.      * less than or equal to the given key, or null if there is no such key.
  1215.      */
  1216.     TrieEntry<K, V> floorEntry(final K key) {
  1217.         // TODO: Cleanup so that we don't actually have to add/remove from the
  1218.         //       tree.  (We do it here because there are other well-defined
  1219.         //       functions to perform the search.)
  1220.         final int lengthInBits = lengthInBits(key);

  1221.         if (lengthInBits == 0) {
  1222.             if (!root.isEmpty()) {
  1223.                 return root;
  1224.             }
  1225.             return null;
  1226.         }

  1227.         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
  1228.         if (compareKeys(key, found.key)) {
  1229.             return found;
  1230.         }

  1231.         final int bitIndex = bitIndex(key, found.key);
  1232.         if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
  1233.             final TrieEntry<K, V> added = new TrieEntry<>(key, null, bitIndex);
  1234.             addEntry(added, lengthInBits);
  1235.             incrementSize(); // must increment because remove will decrement
  1236.             final TrieEntry<K, V> floor = previousEntry(added);
  1237.             removeEntry(added);
  1238.             modCount -= 2; // we didn't really modify it.
  1239.             return floor;
  1240.         }
  1241.         if (KeyAnalyzer.isNullBitKey(bitIndex)) {
  1242.             if (!root.isEmpty()) {
  1243.                 return root;
  1244.             }
  1245.             return null;
  1246.         }
  1247.         if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
  1248.             return found;
  1249.         }

  1250.         // we should have exited above.
  1251.         throw new IllegalStateException("invalid lookup: " + key);
  1252.     }

  1253.     /**
  1254.      * Goes left through the tree until it finds a valid node.
  1255.      */
  1256.     TrieEntry<K, V> followLeft(TrieEntry<K, V> node) {
  1257.         while (true) {
  1258.             TrieEntry<K, V> child = node.left;
  1259.             // if we hit root and it didn't have a node, go right instead.
  1260.             if (child.isEmpty()) {
  1261.                 child = node.right;
  1262.             }

  1263.             if (child.bitIndex <= node.bitIndex) {
  1264.                 return child;
  1265.             }

  1266.             node = child;
  1267.         }
  1268.     }

  1269.     /**
  1270.      * Traverses down the right path until it finds an uplink.
  1271.      */
  1272.     TrieEntry<K, V> followRight(TrieEntry<K, V> node) {
  1273.         // if Trie is empty, no last entry.
  1274.         if (node.right == null) {
  1275.             return null;
  1276.         }

  1277.         // Go as far right as possible, until we encounter an uplink.
  1278.         while (node.right.bitIndex > node.bitIndex) {
  1279.             node = node.right;
  1280.         }

  1281.         return node.right;
  1282.     }

  1283.     @Override
  1284.     public V get(final Object k) {
  1285.         final TrieEntry<K, V> entry = getEntry(k);
  1286.         return entry != null ? entry.getValue() : null;
  1287.     }

  1288.     /**
  1289.      * Gets the entry associated with the specified key in the
  1290.      * PatriciaTrieBase.  Returns null if the map contains no mapping
  1291.      * for this key.
  1292.      * <p>
  1293.      * This may throw ClassCastException if the object is not of type K.
  1294.      */
  1295.     TrieEntry<K, V> getEntry(final Object k) {
  1296.         final K key = castKey(k);
  1297.         if (key == null) {
  1298.             return null;
  1299.         }

  1300.         final int lengthInBits = lengthInBits(key);
  1301.         final TrieEntry<K, V> entry = getNearestEntryForKey(key, lengthInBits);
  1302.         return !entry.isEmpty() && compareKeys(key, entry.key) ? entry : null;
  1303.     }

  1304.     /**
  1305.      * Gets the nearest entry for a given key.  This is useful
  1306.      * for finding knowing if a given key exists (and finding the value
  1307.      * for it), or for inserting the key.
  1308.      *
  1309.      * The actual get implementation. This is very similar to
  1310.      * selectR but with the exception that it might return the
  1311.      * root Entry even if it's empty.
  1312.      */
  1313.     TrieEntry<K, V> getNearestEntryForKey(final K key, final int lengthInBits) {
  1314.         TrieEntry<K, V> current = root.left;
  1315.         TrieEntry<K, V> path = root;
  1316.         while (true) {
  1317.             if (current.bitIndex <= path.bitIndex) {
  1318.                 return current;
  1319.             }

  1320.             path = current;
  1321.             if (!isBitSet(key, current.bitIndex, lengthInBits)) {
  1322.                 current = current.left;
  1323.             } else {
  1324.                 current = current.right;
  1325.             }
  1326.         }
  1327.     }

  1328.     /**
  1329.      * Gets a view of this {@link org.apache.commons.collections4.Trie} of all elements that are prefixed
  1330.      * by the number of bits in the given Key.
  1331.      * <p>
  1332.      * The view that this returns is optimized to have a very efficient
  1333.      * {@link Iterator}. The {@link SortedMap#firstKey()},
  1334.      * {@link SortedMap#lastKey()} &amp; {@link Map#size()} methods must
  1335.      * iterate over all possible values in order to determine the results.
  1336.      * This information is cached until the PATRICIA {@link org.apache.commons.collections4.Trie} changes.
  1337.      * All other methods (except {@link Iterator}) must compare the given
  1338.      * key to the prefix to ensure that it is within the range of the view.
  1339.      * The {@link Iterator}'s remove method must also relocate the subtree
  1340.      * that contains the prefixes if the entry holding the subtree is
  1341.      * removed or changes. Changing the subtree takes O(K) time.
  1342.      *
  1343.      * @param key  the key to use in the search
  1344.      * @param offsetInBits  the prefix offset
  1345.      * @param lengthInBits  the number of significant prefix bits
  1346.      * @return a {@link SortedMap} view of this {@link org.apache.commons.collections4.Trie} with all elements whose
  1347.      *   key is prefixed by the search key
  1348.      */
  1349.     private SortedMap<K, V> getPrefixMapByBits(final K key, final int offsetInBits, final int lengthInBits) {

  1350.         final int offsetLength = offsetInBits + lengthInBits;
  1351.         if (offsetLength > lengthInBits(key)) {
  1352.             throw new IllegalArgumentException(offsetInBits + " + "
  1353.                     + lengthInBits + " > " + lengthInBits(key));
  1354.         }

  1355.         if (offsetLength == 0) {
  1356.             return this;
  1357.         }

  1358.         return new PrefixRangeMap(key, offsetInBits, lengthInBits);
  1359.     }

  1360.     @Override
  1361.     public SortedMap<K, V> headMap(final K toKey) {
  1362.         return new RangeEntryMap(null, toKey);
  1363.     }

  1364.     /**
  1365.      * Returns an entry strictly higher than the given key,
  1366.      * or null if no such entry exists.
  1367.      */
  1368.     TrieEntry<K, V> higherEntry(final K key) {
  1369.         // TODO: Cleanup so that we don't actually have to add/remove from the
  1370.         //       tree.  (We do it here because there are other well-defined
  1371.         //       functions to perform the search.)
  1372.         final int lengthInBits = lengthInBits(key);

  1373.         if (lengthInBits == 0) {
  1374.             if (!root.isEmpty()) {
  1375.                 // If data in root, and more after -- return it.
  1376.                 if (size() > 1) {
  1377.                     return nextEntry(root);
  1378.                 }
  1379.                 // If no more after, no higher entry.
  1380.                 return null;
  1381.             }
  1382.             // Root is empty & we want something after empty, return first.
  1383.             return firstEntry();
  1384.         }

  1385.         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
  1386.         if (compareKeys(key, found.key)) {
  1387.             return nextEntry(found);
  1388.         }

  1389.         final int bitIndex = bitIndex(key, found.key);
  1390.         if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
  1391.             final TrieEntry<K, V> added = new TrieEntry<>(key, null, bitIndex);
  1392.             addEntry(added, lengthInBits);
  1393.             incrementSize(); // must increment because remove will decrement
  1394.             final TrieEntry<K, V> ceil = nextEntry(added);
  1395.             removeEntry(added);
  1396.             modCount -= 2; // we didn't really modify it.
  1397.             return ceil;
  1398.         }
  1399.         if (KeyAnalyzer.isNullBitKey(bitIndex)) {
  1400.             if (!root.isEmpty()) {
  1401.                 return firstEntry();
  1402.             }
  1403.             if (size() > 1) {
  1404.                 return nextEntry(firstEntry());
  1405.             }
  1406.             return null;
  1407.         }
  1408.         if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
  1409.             return nextEntry(found);
  1410.         }

  1411.         // we should have exited above.
  1412.         throw new IllegalStateException("invalid lookup: " + key);
  1413.     }

  1414.     /**
  1415.      * A helper method to increment the modification counter.
  1416.      */
  1417.     private void incrementModCount() {
  1418.         ++modCount;
  1419.     }

  1420.     /**
  1421.      * A helper method to increment the {@link org.apache.commons.collections4.Trie} size and the modification counter.
  1422.      */
  1423.     void incrementSize() {
  1424.         size++;
  1425.         incrementModCount();
  1426.     }

  1427.     @Override
  1428.     public Set<K> keySet() {
  1429.         if (keySet == null) {
  1430.             keySet = new KeySet();
  1431.         }
  1432.         return keySet;
  1433.     }

  1434.     /**
  1435.      * Returns the last entry the {@link org.apache.commons.collections4.Trie} is storing.
  1436.      *
  1437.      * <p>This is implemented by going always to the right until
  1438.      * we encounter a valid uplink. That uplink is the last key.
  1439.      */
  1440.     TrieEntry<K, V> lastEntry() {
  1441.         return followRight(root.left);
  1442.     }

  1443.     @Override
  1444.     public K lastKey() {
  1445.         final TrieEntry<K, V> entry = lastEntry();
  1446.         if (entry != null) {
  1447.             return entry.getKey();
  1448.         }
  1449.         throw new NoSuchElementException();
  1450.     }

  1451.     /**
  1452.      * Returns a key-value mapping associated with the greatest key
  1453.      * strictly less than the given key, or null if there is no such key.
  1454.      */
  1455.     TrieEntry<K, V> lowerEntry(final K key) {
  1456.         // Basically:
  1457.         // Follow the steps of adding an entry, but instead...
  1458.         //
  1459.         // - If we ever encounter a situation where we found an equal
  1460.         //   key, we return it's previousEntry immediately.
  1461.         //
  1462.         // - If we hit root (empty or not), return null.
  1463.         //
  1464.         // - If we have to add a new item, we temporarily add it,
  1465.         //   find the previousEntry to it, then remove the added item.
  1466.         //
  1467.         // These steps ensure that the returned value is always just before
  1468.         // the key or null (if there was nothing before it).

  1469.         // TODO: Cleanup so that we don't actually have to add/remove from the
  1470.         //       tree.  (We do it here because there are other well-defined
  1471.         //       functions to perform the search.)
  1472.         final int lengthInBits = lengthInBits(key);

  1473.         if (lengthInBits == 0) {
  1474.             return null; // there can never be anything before root.
  1475.         }

  1476.         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
  1477.         if (compareKeys(key, found.key)) {
  1478.             return previousEntry(found);
  1479.         }

  1480.         final int bitIndex = bitIndex(key, found.key);
  1481.         if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
  1482.             final TrieEntry<K, V> added = new TrieEntry<>(key, null, bitIndex);
  1483.             addEntry(added, lengthInBits);
  1484.             incrementSize(); // must increment because remove will decrement
  1485.             final TrieEntry<K, V> prior = previousEntry(added);
  1486.             removeEntry(added);
  1487.             modCount -= 2; // we didn't really modify it.
  1488.             return prior;
  1489.         }
  1490.         if (KeyAnalyzer.isNullBitKey(bitIndex)) {
  1491.             return null;
  1492.         }
  1493.         if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
  1494.             return previousEntry(found);
  1495.         }

  1496.         // we should have exited above.
  1497.         throw new IllegalStateException("invalid lookup: " + key);
  1498.     }

  1499.     @Override
  1500.     public OrderedMapIterator<K, V> mapIterator() {
  1501.         return new TrieMapIterator();
  1502.     }

  1503.     /**
  1504.      * Returns the entry lexicographically after the given entry.
  1505.      * If the given entry is null, returns the first node.
  1506.      */
  1507.     TrieEntry<K, V> nextEntry(final TrieEntry<K, V> node) {
  1508.         if (node == null) {
  1509.             return firstEntry();
  1510.         }
  1511.         return nextEntryImpl(node.predecessor, node, null);
  1512.     }

  1513.     /**
  1514.      * Scans for the next node, starting at the specified point, and using 'previous'
  1515.      * as a hint that the last node we returned was 'previous' (so we know not to return
  1516.      * it again).  If 'tree' is non-null, this will limit the search to the given tree.
  1517.      *
  1518.      * The basic premise is that each iteration can follow the following steps:
  1519.      *
  1520.      * 1) Scan all the way to the left.
  1521.      *   a) If we already started from this node last time, proceed to Step 2.
  1522.      *   b) If a valid uplink is found, use it.
  1523.      *   c) If the result is an empty node (root not set), break the scan.
  1524.      *   d) If we already returned the left node, break the scan.
  1525.      *
  1526.      * 2) Check the right.
  1527.      *   a) If we already returned the right node, proceed to Step 3.
  1528.      *   b) If it is a valid uplink, use it.
  1529.      *   c) Do Step 1 from the right node.
  1530.      *
  1531.      * 3) Back up through the parents until we encounter find a parent
  1532.      *    that we're not the right child of.
  1533.      *
  1534.      * 4) If there's no right child of that parent, the iteration is finished.
  1535.      *    Otherwise continue to Step 5.
  1536.      *
  1537.      * 5) Check to see if the right child is a valid uplink.
  1538.      *    a) If we already returned that child, proceed to Step 6.
  1539.      *       Otherwise, use it.
  1540.      *
  1541.      * 6) If the right child of the parent is the parent itself, we've
  1542.      *    already found &amp; returned the end of the Trie, so exit.
  1543.      *
  1544.      * 7) Do Step 1 on the parent's right child.
  1545.      */
  1546.     TrieEntry<K, V> nextEntryImpl(final TrieEntry<K, V> start,
  1547.             final TrieEntry<K, V> previous, final TrieEntry<K, V> tree) {

  1548.         TrieEntry<K, V> current = start;

  1549.         // Only look at the left if this was a recursive or
  1550.         // the first check, otherwise we know we've already looked
  1551.         // at the left.
  1552.         if (previous == null || start != previous.predecessor) {
  1553.             while (!current.left.isEmpty()) {
  1554.                 // stop traversing if we've already
  1555.                 // returned the left of this node.
  1556.                 if (previous == current.left) {
  1557.                     break;
  1558.                 }

  1559.                 if (isValidUplink(current.left, current)) {
  1560.                     return current.left;
  1561.                 }

  1562.                 current = current.left;
  1563.             }
  1564.         }

  1565.         // If there's no data at all, exit.
  1566.         if (current.isEmpty()) {
  1567.             return null;
  1568.         }

  1569.         // If we've already returned the left,
  1570.         // and the immediate right is null,
  1571.         // there's only one entry in the Trie
  1572.         // which is stored at the root.
  1573.         //
  1574.         //  / ("")   <-- root
  1575.         //  \_/  \
  1576.         //       null <-- 'current'
  1577.         //
  1578.         if (current.right == null) {
  1579.             return null;
  1580.         }

  1581.         // If nothing valid on the left, try the right.
  1582.         if (previous != current.right) {
  1583.             // See if it immediately is valid.
  1584.             if (isValidUplink(current.right, current)) {
  1585.                 return current.right;
  1586.             }

  1587.             // Must search on the right's side if it wasn't initially valid.
  1588.             return nextEntryImpl(current.right, previous, tree);
  1589.         }

  1590.         // Neither left nor right are valid, find the first parent
  1591.         // whose child did not come from the right & traverse it.
  1592.         while (current == current.parent.right) {
  1593.             // If we're going to traverse to above the subtree, stop.
  1594.             if (current == tree) {
  1595.                 return null;
  1596.             }

  1597.             current = current.parent;
  1598.         }

  1599.         // If we're on the top of the subtree, we can't go any higher.
  1600.         if (current == tree) {
  1601.             return null;
  1602.         }

  1603.         // If there's no right, the parent must be root, so we're done.
  1604.         if (current.parent.right == null) {
  1605.             return null;
  1606.         }

  1607.         // If the parent's right points to itself, we've found one.
  1608.         if (previous != current.parent.right
  1609.                 && isValidUplink(current.parent.right, current.parent)) {
  1610.             return current.parent.right;
  1611.         }

  1612.         // If the parent's right is itself, there can't be any more nodes.
  1613.         if (current.parent.right == current.parent) {
  1614.             return null;
  1615.         }

  1616.         // We need to traverse down the parent's right's path.
  1617.         return nextEntryImpl(current.parent.right, previous, tree);
  1618.     }

  1619.     /**
  1620.      * Returns the entry lexicographically after the given entry.
  1621.      * If the given entry is null, returns the first node.
  1622.      *
  1623.      * This will traverse only within the subtree.  If the given node
  1624.      * is not within the subtree, this will have undefined results.
  1625.      */
  1626.     TrieEntry<K, V> nextEntryInSubtree(final TrieEntry<K, V> node,
  1627.             final TrieEntry<K, V> parentOfSubtree) {
  1628.         if (node == null) {
  1629.             return firstEntry();
  1630.         }
  1631.         return nextEntryImpl(node.predecessor, node, parentOfSubtree);
  1632.     }

  1633.     @Override
  1634.     public K nextKey(final K key) {
  1635.         Objects.requireNonNull(key, "key");
  1636.         final TrieEntry<K, V> entry = getEntry(key);
  1637.         if (entry != null) {
  1638.             final TrieEntry<K, V> nextEntry = nextEntry(entry);
  1639.             return nextEntry != null ? nextEntry.getKey() : null;
  1640.         }
  1641.         return null;
  1642.     }

  1643.     @Override
  1644.     public SortedMap<K, V> prefixMap(final K key) {
  1645.         return getPrefixMapByBits(key, 0, lengthInBits(key));
  1646.     }

  1647.     /**
  1648.      * Returns the node lexicographically before the given node (or null if none).
  1649.      *
  1650.      * This follows four simple branches:
  1651.      *  - If the uplink that returned us was a right uplink:
  1652.      *      - If predecessor's left is a valid uplink from predecessor, return it.
  1653.      *      - Else, follow the right path from the predecessor's left.
  1654.      *  - If the uplink that returned us was a left uplink:
  1655.      *      - Loop back through parents until we encounter a node where
  1656.      *        node != node.parent.left.
  1657.      *          - If node.parent.left is uplink from node.parent:
  1658.      *              - If node.parent.left is not root, return it.
  1659.      *              - If it is root &amp; root isEmpty, return null.
  1660.      *              - If it is root &amp; root !isEmpty, return root.
  1661.      *          - If node.parent.left is not uplink from node.parent:
  1662.      *              - Follow right path for first right child from node.parent.left
  1663.      *
  1664.      * @param start  the start entry
  1665.      */
  1666.     TrieEntry<K, V> previousEntry(final TrieEntry<K, V> start) {
  1667.         if (start.predecessor == null) {
  1668.             throw new IllegalArgumentException("must have come from somewhere!");
  1669.         }

  1670.         if (start.predecessor.right == start) {
  1671.             if (isValidUplink(start.predecessor.left, start.predecessor)) {
  1672.                 return start.predecessor.left;
  1673.             }
  1674.             return followRight(start.predecessor.left);
  1675.         }
  1676.         TrieEntry<K, V> node = start.predecessor;
  1677.         while (node.parent != null && node == node.parent.left) {
  1678.             node = node.parent;
  1679.         }

  1680.         if (node.parent == null) { // can be null if we're looking up root.
  1681.             return null;
  1682.         }

  1683.         if (isValidUplink(node.parent.left, node.parent)) {
  1684.             if (node.parent.left == root) {
  1685.                 if (root.isEmpty()) {
  1686.                     return null;
  1687.                 }
  1688.                 return root;

  1689.             }
  1690.             return node.parent.left;
  1691.         }
  1692.         return followRight(node.parent.left);
  1693.     }

  1694.     @Override
  1695.     public K previousKey(final K key) {
  1696.         Objects.requireNonNull(key, "key");
  1697.         final TrieEntry<K, V> entry = getEntry(key);
  1698.         if (entry != null) {
  1699.             final TrieEntry<K, V> prevEntry = previousEntry(entry);
  1700.             return prevEntry != null ? prevEntry.getKey() : null;
  1701.         }
  1702.         return null;
  1703.     }

  1704.     @Override
  1705.     public V put(final K key, final V value) {
  1706.         Objects.requireNonNull(key, "key");

  1707.         final int lengthInBits = lengthInBits(key);

  1708.         // The only place to store a key with a length
  1709.         // of zero bits is the root node
  1710.         if (lengthInBits == 0) {
  1711.             if (root.isEmpty()) {
  1712.                 incrementSize();
  1713.             } else {
  1714.                 incrementModCount();
  1715.             }
  1716.             return root.setKeyValue(key, value);
  1717.         }

  1718.         final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
  1719.         if (compareKeys(key, found.key)) {
  1720.             if (found.isEmpty()) { // <- must be the root
  1721.                 incrementSize();
  1722.             } else {
  1723.                 incrementModCount();
  1724.             }
  1725.             return found.setKeyValue(key, value);
  1726.         }

  1727.         final int bitIndex = bitIndex(key, found.key);
  1728.         if (!KeyAnalyzer.isOutOfBoundsIndex(bitIndex)) {
  1729.             if (KeyAnalyzer.isValidBitIndex(bitIndex)) { // in 99.999...9% the case
  1730.                 /* NEW KEY+VALUE TUPLE */
  1731.                 final TrieEntry<K, V> t = new TrieEntry<>(key, value, bitIndex);
  1732.                 addEntry(t, lengthInBits);
  1733.                 incrementSize();
  1734.                 return null;
  1735.             }
  1736.             if (KeyAnalyzer.isNullBitKey(bitIndex)) {
  1737.                 // A bits of the Key are zero. The only place to
  1738.                 // store such a Key is the root Node!

  1739.                 /* NULL BIT KEY */
  1740.                 if (root.isEmpty()) {
  1741.                     incrementSize();
  1742.                 } else {
  1743.                     incrementModCount();
  1744.                 }
  1745.                 return root.setKeyValue(key, value);

  1746.             }
  1747.             if (KeyAnalyzer.isEqualBitKey(bitIndex) && found != root) { // NOPMD
  1748.                 incrementModCount();
  1749.                 return found.setKeyValue(key, value);
  1750.             }
  1751.         }

  1752.         throw new IllegalArgumentException("Failed to put: " + key + " -> " + value + ", " + bitIndex);
  1753.     }

  1754.     /**
  1755.      * Deserializes an instance from an ObjectInputStream.
  1756.      *
  1757.      * @param in The source ObjectInputStream.
  1758.      * @throws IOException            Any of the usual Input/Output related exceptions.
  1759.      * @throws ClassNotFoundException A class of a serialized object cannot be found.
  1760.      */
  1761.     @SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect
  1762.     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
  1763.         in.defaultReadObject();
  1764.         root = new TrieEntry<>(null, null, -1);
  1765.         final int size = in.readInt();
  1766.         for (int i = 0; i < size; i++) {
  1767.             final K k = (K) in.readObject();
  1768.             final V v = (V) in.readObject();
  1769.             put(k, v);
  1770.         }
  1771.     }

  1772.     /**
  1773.      * {@inheritDoc}
  1774.      *
  1775.      * @throws ClassCastException if provided key is of an incompatible type
  1776.      */
  1777.     @Override
  1778.     public V remove(final Object k) {
  1779.         if (k == null) {
  1780.             return null;
  1781.         }

  1782.         final K key = castKey(k);
  1783.         final int lengthInBits = lengthInBits(key);
  1784.         TrieEntry<K, V> current = root.left;
  1785.         TrieEntry<K, V> path = root;
  1786.         while (true) {
  1787.             if (current.bitIndex <= path.bitIndex) {
  1788.                 if (!current.isEmpty() && compareKeys(key, current.key)) {
  1789.                     return removeEntry(current);
  1790.                 }
  1791.                 return null;
  1792.             }

  1793.             path = current;

  1794.             if (!isBitSet(key, current.bitIndex, lengthInBits)) {
  1795.                 current = current.left;
  1796.             } else {
  1797.                 current = current.right;
  1798.             }
  1799.         }
  1800.     }

  1801.     /**
  1802.      * Removes a single entry from the {@link org.apache.commons.collections4.Trie}.
  1803.      *
  1804.      * If we found a Key (Entry h) then figure out if it's
  1805.      * an internal (hard to remove) or external Entry (easy
  1806.      * to remove)
  1807.      */
  1808.     V removeEntry(final TrieEntry<K, V> h) {
  1809.         if (h != root) {
  1810.             if (h.isInternalNode()) {
  1811.                 removeInternalEntry(h);
  1812.             } else {
  1813.                 removeExternalEntry(h);
  1814.             }
  1815.         }

  1816.         decrementSize();
  1817.         return h.setKeyValue(null, null);
  1818.     }

  1819.     /**
  1820.      * Removes an external entry from the {@link org.apache.commons.collections4.Trie}.
  1821.      *
  1822.      * If it's an external Entry then just remove it.
  1823.      * This is very easy and straight forward.
  1824.      */
  1825.     private void removeExternalEntry(final TrieEntry<K, V> h) {
  1826.         if (h == root) {
  1827.             throw new IllegalArgumentException("Cannot delete root Entry!");
  1828.         }
  1829.         if (!h.isExternalNode()) {
  1830.             throw new IllegalArgumentException(h + " is not an external Entry!");
  1831.         }

  1832.         final TrieEntry<K, V> parent = h.parent;
  1833.         final TrieEntry<K, V> child = h.left == h ? h.right : h.left;

  1834.         if (parent.left == h) {
  1835.             parent.left = child;
  1836.         } else {
  1837.             parent.right = child;
  1838.         }

  1839.         // either the parent is changing, or the predecessor is changing.
  1840.         if (child.bitIndex > parent.bitIndex) {
  1841.             child.parent = parent;
  1842.         } else {
  1843.             child.predecessor = parent;
  1844.         }

  1845.     }

  1846.     /**
  1847.      * Removes an internal entry from the {@link org.apache.commons.collections4.Trie}.
  1848.      *
  1849.      * If it's an internal Entry then "good luck" with understanding
  1850.      * this code. The Idea is essentially that Entry p takes Entry h's
  1851.      * place in the trie which requires some re-wiring.
  1852.      */
  1853.     private void removeInternalEntry(final TrieEntry<K, V> h) {
  1854.         if (h == root) {
  1855.             throw new IllegalArgumentException("Cannot delete root Entry!");
  1856.         }
  1857.         if (!h.isInternalNode()) {
  1858.             throw new IllegalArgumentException(h + " is not an internal Entry!");
  1859.         }

  1860.         final TrieEntry<K, V> p = h.predecessor;

  1861.         // Set P's bitIndex
  1862.         p.bitIndex = h.bitIndex;

  1863.         // Fix P's parent, predecessor and child Nodes
  1864.         {
  1865.             final TrieEntry<K, V> parent = p.parent;
  1866.             final TrieEntry<K, V> child = p.left == h ? p.right : p.left;

  1867.             // if it was looping to itself previously,
  1868.             // it will now be pointed from its parent
  1869.             // (if we aren't removing its parent --
  1870.             //  in that case, it remains looping to itself).
  1871.             // otherwise, it will continue to have the same
  1872.             // predecessor.
  1873.             if (p.predecessor == p && p.parent != h) {
  1874.                 p.predecessor = p.parent;
  1875.             }

  1876.             if (parent.left == p) {
  1877.                 parent.left = child;
  1878.             } else {
  1879.                 parent.right = child;
  1880.             }

  1881.             if (child.bitIndex > parent.bitIndex) {
  1882.                 child.parent = parent;
  1883.             }
  1884.         }

  1885.         // Fix H's parent and child Nodes
  1886.         {
  1887.             // If H is a parent of its left and right child
  1888.             // then change them to P
  1889.             if (h.left.parent == h) {
  1890.                 h.left.parent = p;
  1891.             }

  1892.             if (h.right.parent == h) {
  1893.                 h.right.parent = p;
  1894.             }

  1895.             // Change H's parent
  1896.             if (h.parent.left == h) {
  1897.                 h.parent.left = p;
  1898.             } else {
  1899.                 h.parent.right = p;
  1900.             }
  1901.         }

  1902.         // Copy the remaining fields from H to P
  1903.         //p.bitIndex = h.bitIndex;
  1904.         p.parent = h.parent;
  1905.         p.left = h.left;
  1906.         p.right = h.right;

  1907.         // Make sure that if h was pointing to any uplinks,
  1908.         // p now points to them.
  1909.         if (isValidUplink(p.left, p)) {
  1910.             p.left.predecessor = p;
  1911.         }

  1912.         if (isValidUplink(p.right, p)) {
  1913.             p.right.predecessor = p;
  1914.         }
  1915.     }

  1916.     /**
  1917.      * Returns the {@link java.util.Map.Entry} whose key is closest in a bitwise XOR
  1918.      * metric to the given key. This is NOT lexicographic closeness.
  1919.      * For example, given the keys:
  1920.      *
  1921.      * <ol>
  1922.      * <li>D = 1000100
  1923.      * <li>H = 1001000
  1924.      * <li>L = 1001100
  1925.      * </ol>
  1926.      *
  1927.      * If the {@link org.apache.commons.collections4.Trie} contained 'H' and 'L', a lookup of 'D' would
  1928.      * return 'L', because the XOR distance between D &amp; L is smaller
  1929.      * than the XOR distance between D &amp; H.
  1930.      *
  1931.      * @param key  the key to use in the search
  1932.      * @return the {@link java.util.Map.Entry} whose key is closest in a bitwise XOR metric
  1933.      *   to the provided key
  1934.      */
  1935.     public Map.Entry<K, V> select(final K key) {
  1936.         final int lengthInBits = lengthInBits(key);
  1937.         final Reference<Map.Entry<K, V>> reference = new Reference<>();
  1938.         if (!selectR(root.left, -1, key, lengthInBits, reference)) {
  1939.             return reference.get();
  1940.         }
  1941.         return null;
  1942.     }

  1943.     /**
  1944.      * Returns the key that is closest in a bitwise XOR metric to the
  1945.      * provided key. This is NOT lexicographic closeness!
  1946.      *
  1947.      * For example, given the keys:
  1948.      *
  1949.      * <ol>
  1950.      * <li>D = 1000100
  1951.      * <li>H = 1001000
  1952.      * <li>L = 1001100
  1953.      * </ol>
  1954.      *
  1955.      * If the {@link org.apache.commons.collections4.Trie} contained 'H' and 'L', a lookup of 'D' would
  1956.      * return 'L', because the XOR distance between D &amp; L is smaller
  1957.      * than the XOR distance between D &amp; H.
  1958.      *
  1959.      * @param key  the key to use in the search
  1960.      * @return the key that is closest in a bitwise XOR metric to the provided key
  1961.      */
  1962.     public K selectKey(final K key) {
  1963.         final Map.Entry<K, V> entry = select(key);
  1964.         if (entry == null) {
  1965.             return null;
  1966.         }
  1967.         return entry.getKey();
  1968.     }

  1969.     private boolean selectR(final TrieEntry<K, V> h, final int bitIndex,
  1970.                             final K key, final int lengthInBits,
  1971.                             final Reference<Map.Entry<K, V>> reference) {

  1972.         if (h.bitIndex <= bitIndex) {
  1973.             // If we hit the root Node and it is empty
  1974.             // we have to look for an alternative best
  1975.             // matching node.
  1976.             if (!h.isEmpty()) {
  1977.                 reference.set(h);
  1978.                 return false;
  1979.             }
  1980.             return true;
  1981.         }

  1982.         if (!isBitSet(key, h.bitIndex, lengthInBits)) {
  1983.             if (selectR(h.left, h.bitIndex, key, lengthInBits, reference)) {
  1984.                 return selectR(h.right, h.bitIndex, key, lengthInBits, reference);
  1985.             }
  1986.         } else if (selectR(h.right, h.bitIndex, key, lengthInBits, reference)) {
  1987.             return selectR(h.left, h.bitIndex, key, lengthInBits, reference);
  1988.         }
  1989.         return false;
  1990.     }

  1991.     /**
  1992.      * Returns the value whose key is closest in a bitwise XOR metric to
  1993.      * the provided key. This is NOT lexicographic closeness!
  1994.      *
  1995.      * For example, given the keys:
  1996.      *
  1997.      * <ol>
  1998.      * <li>D = 1000100
  1999.      * <li>H = 1001000
  2000.      * <li>L = 1001100
  2001.      * </ol>
  2002.      *
  2003.      * If the {@link org.apache.commons.collections4.Trie} contained 'H' and 'L', a lookup of 'D' would
  2004.      * return 'L', because the XOR distance between D &amp; L is smaller
  2005.      * than the XOR distance between D &amp; H.
  2006.      *
  2007.      * @param key  the key to use in the search
  2008.      * @return the value whose key is closest in a bitwise XOR metric
  2009.      * to the provided key
  2010.      */
  2011.     public V selectValue(final K key) {
  2012.         final Map.Entry<K, V> entry = select(key);
  2013.         if (entry == null) {
  2014.             return null;
  2015.         }
  2016.         return entry.getValue();
  2017.     }

  2018.     @Override
  2019.     public int size() {
  2020.         return size;
  2021.     }

  2022.     @Override
  2023.     public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
  2024.         return new RangeEntryMap(fromKey, toKey);
  2025.     }

  2026.     /**
  2027.      * Finds the subtree that contains the prefix.
  2028.      *
  2029.      * This is very similar to getR but with the difference that
  2030.      * we stop the lookup if h.bitIndex > lengthInBits.
  2031.      */
  2032.     TrieEntry<K, V> subtree(final K prefix, final int offsetInBits, final int lengthInBits) {
  2033.         TrieEntry<K, V> current = root.left;
  2034.         TrieEntry<K, V> path = root;
  2035.         while (true) {
  2036.             if (current.bitIndex <= path.bitIndex || lengthInBits <= current.bitIndex) {
  2037.                 break;
  2038.             }

  2039.             path = current;
  2040.             if (!isBitSet(prefix, offsetInBits + current.bitIndex, offsetInBits + lengthInBits)) {
  2041.                 current = current.left;
  2042.             } else {
  2043.                 current = current.right;
  2044.             }
  2045.         }

  2046.         // Make sure the entry is valid for a subtree.
  2047.         final TrieEntry<K, V> entry = current.isEmpty() ? path : current;

  2048.         // If entry is root, it can't be empty.
  2049.         if (entry.isEmpty()) {
  2050.             return null;
  2051.         }

  2052.         final int endIndexInBits = offsetInBits + lengthInBits;

  2053.         // if root && length of root is less than length of lookup,
  2054.         // there's nothing.
  2055.         // (this prevents returning the whole subtree if root has an empty
  2056.         //  string and we want to lookup things with "\0")
  2057.         if (entry == root && lengthInBits(entry.getKey()) < endIndexInBits) {
  2058.             return null;
  2059.         }

  2060.         // Found key's length-th bit differs from our key
  2061.         // which means it cannot be the prefix...
  2062.         if (isBitSet(prefix, endIndexInBits - 1, endIndexInBits)
  2063.                 != isBitSet(entry.key, lengthInBits - 1, lengthInBits(entry.key))) {
  2064.             return null;
  2065.         }

  2066.         // ... or there are less than 'length' equal bits
  2067.         final int bitIndex = getKeyAnalyzer().bitIndex(prefix, offsetInBits, lengthInBits,
  2068.                                                        entry.key, 0, lengthInBits(entry.getKey()));

  2069.         if (bitIndex >= 0 && bitIndex < lengthInBits) {
  2070.             return null;
  2071.         }

  2072.         return entry;
  2073.     }

  2074.     @Override
  2075.     public SortedMap<K, V> tailMap(final K fromKey) {
  2076.         return new RangeEntryMap(fromKey, null);
  2077.     }

  2078.     @Override
  2079.     public Collection<V> values() {
  2080.         if (values == null) {
  2081.             values = new Values();
  2082.         }
  2083.         return values;
  2084.     }

  2085.     /**
  2086.      * Serializes this object to an ObjectOutputStream.
  2087.      *
  2088.      * @param out the target ObjectOutputStream.
  2089.      * @throws IOException thrown when an I/O errors occur writing to the target stream.
  2090.      */
  2091.     private void writeObject(final ObjectOutputStream out) throws IOException {
  2092.         out.defaultWriteObject();
  2093.         out.writeInt(this.size());
  2094.         for (final Entry<K, V> entry : entrySet()) {
  2095.             out.writeObject(entry.getKey());
  2096.             out.writeObject(entry.getValue());
  2097.         }
  2098.     }

  2099. }