in src/main/java/org/apache/commons/collections4/trie/AbstractPatriciaTrie.java [1331:1386]
TrieEntry<K, V> ceilingEntry(final K key) {
// Basically:
// Follow the steps of adding an entry, but instead...
//
// - If we ever encounter a situation where we found an equal
// key, we return it immediately.
//
// - If we hit an empty root, return the first iterable item.
//
// - If we have to add a new item, we temporarily add it,
// find the successor to it, then remove the added item.
//
// These steps ensure that the returned value is either the
// entry for the key itself, or the first entry directly after
// the key.
// TODO: Cleanup so that we don't actually have to add/remove from the
// tree. (We do it here because there are other well-defined
// functions to perform the search.)
final int lengthInBits = lengthInBits(key);
if (lengthInBits == 0) {
if (!root.isEmpty()) {
return root;
}
return firstEntry();
}
final TrieEntry<K, V> found = getNearestEntryForKey(key, lengthInBits);
if (compareKeys(key, found.key)) {
return found;
}
final int bitIndex = bitIndex(key, found.key);
if (KeyAnalyzer.isValidBitIndex(bitIndex)) {
final TrieEntry<K, V> added = new TrieEntry<>(key, null, bitIndex);
addEntry(added, lengthInBits);
incrementSize(); // must increment because remove will decrement
final TrieEntry<K, V> ceil = nextEntry(added);
removeEntry(added);
modCount -= 2; // we didn't really modify it.
return ceil;
}
if (KeyAnalyzer.isNullBitKey(bitIndex)) {
if (!root.isEmpty()) {
return root;
}
return firstEntry();
}
if (KeyAnalyzer.isEqualBitKey(bitIndex)) {
return found;
}
// we should have exited above.
throw new IllegalStateException("invalid lookup: " + key);
}