Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* * Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
* *
* * For more information: http://www.orientechnologies.com
*
*/
package com.orientechnologies.orient.core.index.mvrbtree;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;
import com.orientechnologies.common.collection.OLazyIterator;
import com.orientechnologies.common.collection.ONavigableMap;
import com.orientechnologies.common.collection.ONavigableSet;
import com.orientechnologies.common.collection.OSimpleImmutableEntry;
import com.orientechnologies.common.comparator.ODefaultComparator;
import com.orientechnologies.common.log.OLogManager;
import com.orientechnologies.orient.core.index.OAlwaysGreaterKey;
import com.orientechnologies.orient.core.index.OAlwaysLessKey;
import com.orientechnologies.orient.core.index.OCompositeKey;
/**
* Base abstract class of MVRB-Tree algorithm.
*
* @author Luca Garulli (l.garulli--at--orientechnologies.com)
*
* @param
* Key type
* @param
* Value type
*/
@SuppressWarnings({ "unchecked", "serial" })
public abstract class OMVRBTree extends AbstractMap implements ONavigableMap, Cloneable, java.io.Serializable {
public static final boolean RED = false;
public static final boolean BLACK = true;
private static final OAlwaysLessKey ALWAYS_LESS_KEY = new OAlwaysLessKey();
private static final OAlwaysGreaterKey ALWAYS_GREATER_KEY = new OAlwaysGreaterKey();
/**
* The comparator used to maintain order in this tree map, or null if it uses the natural ordering of its keys.
*
* @serial
*/
protected final Comparator comparator;
protected boolean pageItemFound = false;
protected int pageItemComparator = 0;
protected int pageIndex = -1;
protected float pageLoadFactor = 0.7f;
protected transient OMVRBTreeEntry root = null;
protected transient boolean runtimeCheckEnabled = false;
protected transient boolean debug = false;
protected Object lastSearchKey;
protected OMVRBTreeEntry lastSearchNode;
protected boolean lastSearchFound = false;
protected int lastSearchIndex = -1;
protected int keySize = 1;
/**
* The number of structural modifications to the tree.
*/
transient int modCount = 0;
/**
* Fields initialized to contain an instance of the entry set view the first time this view is requested. Views are stateless, so
* there's no reason to create more than one.
*/
private transient EntrySet entrySet = null;
private transient KeySet navigableKeySet = null;
private transient ONavigableMap descendingMap = null;
/**
* Indicates search behavior in case of {@link com.orientechnologies.orient.core.index.OCompositeKey} keys that have less amount
* of internal keys are used, whether lowest or highest partially matched key should be used. Such keys is allowed to use only in
*
* @link OMVRBTree#subMap(K, boolean, K, boolean)}, {@link OMVRBTree#tailMap(Object, boolean)} and
* {@link OMVRBTree#headMap(Object, boolean)} .
*/
public static enum PartialSearchMode {
/**
* Any partially matched key will be used as search result.
*/
NONE,
/**
* The biggest partially matched key will be used as search result.
*/
HIGHEST_BOUNDARY,
/**
* The smallest partially matched key will be used as search result.
*/
LOWEST_BOUNDARY
}
@SuppressWarnings("rawtypes")
static final class KeySet extends AbstractSet implements ONavigableSet {
private final ONavigableMap m;
KeySet(ONavigableMap map) {
m = map;
}
@Override
public OLazyIterator iterator() {
if (m instanceof OMVRBTree)
return ((OMVRBTree) m).keyIterator();
else
return (((OMVRBTree.NavigableSubMap) m).keyIterator());
}
public OLazyIterator descendingIterator() {
if (m instanceof OMVRBTree)
return ((OMVRBTree) m).descendingKeyIterator();
else
return (((OMVRBTree.NavigableSubMap) m).descendingKeyIterator());
}
@Override
public int size() {
return m.size();
}
@Override
public boolean isEmpty() {
return m.isEmpty();
}
@Override
public boolean contains(final Object o) {
return m.containsKey(o);
}
@Override
public void clear() {
m.clear();
}
public E lower(final E e) {
return m.lowerKey(e);
}
public E floor(final E e) {
return m.floorKey(e);
}
public E ceiling(final E e) {
return m.ceilingKey(e);
}
public E higher(final E e) {
return m.higherKey(e);
}
public E first() {
return m.firstKey();
}
public E last() {
return m.lastKey();
}
public Comparator comparator() {
return m.comparator();
}
public E pollFirst() {
final Map.Entry e = m.pollFirstEntry();
return e == null ? null : e.getKey();
}
public E pollLast() {
final Map.Entry e = m.pollLastEntry();
return e == null ? null : e.getKey();
}
@Override
public boolean remove(final Object o) {
final int oldSize = size();
m.remove(o);
return size() != oldSize;
}
public ONavigableSet subSet(final E fromElement, final boolean fromInclusive, final E toElement, final boolean toInclusive) {
return new OMVRBTreeSet(m.subMap(fromElement, fromInclusive, toElement, toInclusive));
}
public ONavigableSet headSet(final E toElement, final boolean inclusive) {
return new OMVRBTreeSet(m.headMap(toElement, inclusive));
}
public ONavigableSet tailSet(final E fromElement, final boolean inclusive) {
return new OMVRBTreeSet(m.tailMap(fromElement, inclusive));
}
public SortedSet subSet(final E fromElement, final E toElement) {
return subSet(fromElement, true, toElement, false);
}
public SortedSet headSet(final E toElement) {
return headSet(toElement, false);
}
public SortedSet tailSet(final E fromElement) {
return tailSet(fromElement, true);
}
public ONavigableSet descendingSet() {
return new OMVRBTreeSet(m.descendingMap());
}
}
/**
* @serial include
*/
static abstract class NavigableSubMap extends AbstractMap implements ONavigableMap, java.io.Serializable {
/**
* The backing map.
*/
final OMVRBTree m;
/**
* Endpoints are represented as triples (fromStart, lo, loInclusive) and (toEnd, hi, hiInclusive). If fromStart is true, then
* the low (absolute) bound is the start of the backing map, and the other values are ignored. Otherwise, if loInclusive is
* true, lo is the inclusive bound, else lo is the exclusive bound. Similarly for the upper bound.
*/
final K lo, hi;
final boolean fromStart, toEnd;
final boolean loInclusive, hiInclusive;
// Views
transient ONavigableMap descendingMapView = null;
// internal utilities
transient EntrySetView entrySetView = null;
transient KeySet navigableKeySetView = null;
abstract class EntrySetView extends AbstractSet> {
private transient int size = -1, sizeModCount;
@Override
public int size() {
if (fromStart && toEnd)
return m.size();
if (size == -1 || sizeModCount != m.modCount) {
sizeModCount = m.modCount;
size = 0;
Iterator i = iterator();
while (i.hasNext()) {
size++;
i.next();
}
}
return size;
}
@Override
public boolean isEmpty() {
OMVRBTreeEntryPosition n = absLowest();
return n == null || tooHigh(n.getKey());
}
@Override
public boolean contains(final Object o) {
if (!(o instanceof OMVRBTreeEntry))
return false;
final OMVRBTreeEntry entry = (OMVRBTreeEntry) o;
final K key = entry.getKey();
if (!inRange(key))
return false;
V nodeValue = m.get(key);
return nodeValue != null && valEquals(nodeValue, entry.getValue());
}
@Override
public boolean remove(final Object o) {
if (!(o instanceof OMVRBTreeEntry))
return false;
final OMVRBTreeEntry entry = (OMVRBTreeEntry) o;
final K key = entry.getKey();
if (!inRange(key))
return false;
final OMVRBTreeEntry node = m.getEntry(key, PartialSearchMode.NONE);
if (node != null && valEquals(node.getValue(), entry.getValue())) {
m.deleteEntry(node);
return true;
}
return false;
}
}
/**
* Iterators for SubMaps
*/
abstract class SubMapIterator implements OLazyIterator {
final K fenceKey;
OMVRBTreeEntryPosition lastReturned;
OMVRBTreeEntryPosition next;
int expectedModCount;
SubMapIterator(final OMVRBTreeEntryPosition first, final OMVRBTreeEntryPosition fence) {
expectedModCount = m.modCount;
lastReturned = null;
next = first;
fenceKey = fence == null ? null : fence.getKey();
}
public final boolean hasNext() {
if (next != null) {
final K k = next.getKey();
return k != fenceKey && !k.equals(fenceKey);
}
return false;
}
final OMVRBTreeEntryPosition nextEntry() {
final OMVRBTreeEntryPosition e;
if (next != null)
e = new OMVRBTreeEntryPosition(next);
else
e = null;
if (e == null || e.entry == null)
throw new NoSuchElementException();
final K k = e.getKey();
if (k == fenceKey || k.equals(fenceKey))
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next.assign(OMVRBTree.next(e));
lastReturned = e;
return e;
}
final OMVRBTreeEntryPosition prevEntry() {
final OMVRBTreeEntryPosition e;
if (next != null)
e = new OMVRBTreeEntryPosition(next);
else
e = null;
if (e == null || e.entry == null)
throw new NoSuchElementException();
final K k = e.getKey();
if (k == fenceKey || k.equals(fenceKey))
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next.assign(OMVRBTree.previous(e));
lastReturned = e;
return e;
}
final public T update(final T iValue) {
if (lastReturned == null)
throw new IllegalStateException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
return (T) lastReturned.entry.setValue((V) iValue);
}
final void removeAscending() {
if (lastReturned == null)
throw new IllegalStateException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
// deleted entries are replaced by their successors
if (lastReturned.entry.getLeft() != null && lastReturned.entry.getRight() != null)
next = lastReturned;
m.deleteEntry(lastReturned.entry);
lastReturned = null;
expectedModCount = m.modCount;
}
final void removeDescending() {
if (lastReturned == null)
throw new IllegalStateException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
m.deleteEntry(lastReturned.entry);
lastReturned = null;
expectedModCount = m.modCount;
}
}
final class SubMapEntryIterator extends SubMapIterator> {
SubMapEntryIterator(final OMVRBTreeEntryPosition first, final OMVRBTreeEntryPosition fence) {
super(first, fence);
}
public Map.Entry next() {
final Map.Entry e = OMVRBTree.exportEntry(next);
nextEntry();
return e;
}
public void remove() {
removeAscending();
}
}
/*
* Absolute versions of relation operations. Subclasses map to these using like-named "sub" versions that invert senses for
* descending maps
*/
final class SubMapKeyIterator extends SubMapIterator {
SubMapKeyIterator(final OMVRBTreeEntryPosition first, final OMVRBTreeEntryPosition fence) {
super(first, fence);
}
public K next() {
return nextEntry().getKey();
}
public void remove() {
removeAscending();
}
}
final class DescendingSubMapEntryIterator extends SubMapIterator> {
DescendingSubMapEntryIterator(final OMVRBTreeEntryPosition last, final OMVRBTreeEntryPosition fence) {
super(last, fence);
}
public Map.Entry next() {
final Map.Entry e = OMVRBTree.exportEntry(next);
prevEntry();
return e;
}
public void remove() {
removeDescending();
}
}
final class DescendingSubMapKeyIterator extends SubMapIterator {
DescendingSubMapKeyIterator(final OMVRBTreeEntryPosition last, final OMVRBTreeEntryPosition fence) {
super(last, fence);
}
public K next() {
return prevEntry().getKey();
}
public void remove() {
removeDescending();
}
}
NavigableSubMap(final OMVRBTree m, final boolean fromStart, K lo, final boolean loInclusive, final boolean toEnd, K hi,
final boolean hiInclusive) {
if (!fromStart && !toEnd) {
if (m.compare(lo, hi) > 0)
throw new IllegalArgumentException("fromKey > toKey");
} else {
if (!fromStart) // type check
m.compare(lo, lo);
if (!toEnd)
m.compare(hi, hi);
}
this.m = m;
this.fromStart = fromStart;
this.lo = lo;
this.loInclusive = loInclusive;
this.toEnd = toEnd;
this.hi = hi;
this.hiInclusive = hiInclusive;
}
final boolean tooLow(final Object key) {
if (!fromStart) {
int c = m.compare(key, lo);
if (c < 0 || (c == 0 && !loInclusive))
return true;
}
return false;
}
final boolean tooHigh(final Object key) {
if (!toEnd) {
int c = m.compare(key, hi);
if (c > 0 || (c == 0 && !hiInclusive))
return true;
}
return false;
}
final boolean inRange(final Object key) {
return !tooLow(key) && !tooHigh(key);
}
final boolean inClosedRange(final Object key) {
return (fromStart || m.compare(key, lo) >= 0) && (toEnd || m.compare(hi, key) >= 0);
}
// Abstract methods defined in ascending vs descending classes
// These relay to the appropriate absolute versions
final boolean inRange(final Object key, final boolean inclusive) {
return inclusive ? inRange(key) : inClosedRange(key);
}
final OMVRBTreeEntryPosition absLowest() {
OMVRBTreeEntry e = (fromStart ? m.getFirstEntry() : (loInclusive ? m.getCeilingEntry(lo,
PartialSearchMode.LOWEST_BOUNDARY) : m.getHigherEntry(lo)));
return (e == null || tooHigh(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
final OMVRBTreeEntryPosition absHighest() {
OMVRBTreeEntry e = (toEnd ? m.getLastEntry() : (hiInclusive ? m.getFloorEntry(hi, PartialSearchMode.HIGHEST_BOUNDARY)
: m.getLowerEntry(hi)));
return (e == null || tooLow(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
final OMVRBTreeEntryPosition absCeiling(K key) {
if (tooLow(key))
return absLowest();
OMVRBTreeEntry e = m.getCeilingEntry(key, PartialSearchMode.NONE);
return (e == null || tooHigh(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
final OMVRBTreeEntryPosition absHigher(K key) {
if (tooLow(key))
return absLowest();
OMVRBTreeEntry e = m.getHigherEntry(key);
return (e == null || tooHigh(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
final OMVRBTreeEntryPosition absFloor(K key) {
if (tooHigh(key))
return absHighest();
OMVRBTreeEntry e = m.getFloorEntry(key, PartialSearchMode.NONE);
return (e == null || tooLow(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
final OMVRBTreeEntryPosition absLower(K key) {
if (tooHigh(key))
return absHighest();
OMVRBTreeEntry e = m.getLowerEntry(key);
return (e == null || tooLow(e.getKey())) ? null : new OMVRBTreeEntryPosition(e);
}
/** Returns the absolute high fence for ascending traversal */
final OMVRBTreeEntryPosition absHighFence() {
return (toEnd ? null : new OMVRBTreeEntryPosition(hiInclusive ? m.getHigherEntry(hi) : m.getCeilingEntry(hi,
PartialSearchMode.LOWEST_BOUNDARY)));
}
// public methods
/** Return the absolute low fence for descending traversal */
final OMVRBTreeEntryPosition absLowFence() {
return (fromStart ? null : new OMVRBTreeEntryPosition(loInclusive ? m.getLowerEntry(lo) : m.getFloorEntry(lo,
PartialSearchMode.HIGHEST_BOUNDARY)));
}
abstract OMVRBTreeEntry subLowest();
abstract OMVRBTreeEntry subHighest();
abstract OMVRBTreeEntry subCeiling(K key);
abstract OMVRBTreeEntry subHigher(K key);
abstract OMVRBTreeEntry subFloor(K key);
abstract OMVRBTreeEntry subLower(K key);
/** Returns ascending iterator from the perspective of this submap */
abstract OLazyIterator keyIterator();
/** Returns descending iterator from the perspective of this submap */
abstract OLazyIterator descendingKeyIterator();
@Override
public boolean isEmpty() {
return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty();
}
@Override
public int size() {
return (fromStart && toEnd) ? m.size() : entrySet().size();
}
@Override
public final boolean containsKey(Object key) {
return inRange(key) && m.containsKey(key);
}
@Override
public final V put(K key, V value) {
if (!inRange(key))
throw new IllegalArgumentException("key out of range");
return m.put(key, value);
}
@Override
public final V get(Object key) {
return !inRange(key) ? null : m.get(key);
}
@Override
public final V remove(Object key) {
return !inRange(key) ? null : m.remove(key);
}
public final Map.Entry ceilingEntry(K key) {
return exportEntry(subCeiling(key));
}
public final K ceilingKey(K key) {
return keyOrNull(subCeiling(key));
}
public final Map.Entry higherEntry(K key) {
return exportEntry(subHigher(key));
}
public final K higherKey(K key) {
return keyOrNull(subHigher(key));
}
public final Map.Entry floorEntry(K key) {
return exportEntry(subFloor(key));
}
public final K floorKey(K key) {
return keyOrNull(subFloor(key));
}
public final Map.Entry lowerEntry(K key) {
return exportEntry(subLower(key));
}
public final K lowerKey(K key) {
return keyOrNull(subLower(key));
}
public final K firstKey() {
return key(subLowest());
}
public final K lastKey() {
return key(subHighest());
}
public final Map.Entry firstEntry() {
return exportEntry(subLowest());
}
public final Map.Entry lastEntry() {
return exportEntry(subHighest());
}
public final Map.Entry pollFirstEntry() {
OMVRBTreeEntry e = subLowest();
Map.Entry result = exportEntry(e);
if (e != null)
m.deleteEntry(e);
return result;
}
public final Map.Entry pollLastEntry() {
OMVRBTreeEntry e = subHighest();
Map.Entry result = exportEntry(e);
if (e != null)
m.deleteEntry(e);
return result;
}
// View classes
@SuppressWarnings("rawtypes")
public final ONavigableSet navigableKeySet() {
KeySet nksv = navigableKeySetView;
return (nksv != null) ? nksv : (navigableKeySetView = new OMVRBTree.KeySet(this));
}
@Override
public final Set keySet() {
return navigableKeySet();
}
public ONavigableSet descendingKeySet() {
return descendingMap().navigableKeySet();
}
public final SortedMap subMap(final K fromKey, final K toKey) {
return subMap(fromKey, true, toKey, false);
}
public final SortedMap headMap(final K toKey) {
return headMap(toKey, false);
}
public final SortedMap tailMap(final K fromKey) {
return tailMap(fromKey, true);
}
}
/**
* @serial include
*/
static final class AscendingSubMap extends NavigableSubMap {
private static final long serialVersionUID = 912986545866124060L;
final class AscendingEntrySetView extends EntrySetView {
@Override
public Iterator> iterator() {
return new SubMapEntryIterator(absLowest(), absHighFence());
}
}
AscendingSubMap(final OMVRBTree m, final boolean fromStart, final K lo, final boolean loInclusive, final boolean toEnd,
K hi, final boolean hiInclusive) {
super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
}
public Comparator comparator() {
return m.comparator();
}
public ONavigableMap subMap(final K fromKey, final boolean fromInclusive, final K toKey, final boolean toInclusive) {
if (!inRange(fromKey, fromInclusive))
throw new IllegalArgumentException("fromKey out of range");
if (!inRange(toKey, toInclusive))
throw new IllegalArgumentException("toKey out of range");
return new AscendingSubMap(m, false, fromKey, fromInclusive, false, toKey, toInclusive);
}
public ONavigableMap headMap(final K toKey, final boolean inclusive) {
if (!inRange(toKey, inclusive))
throw new IllegalArgumentException("toKey out of range");
return new AscendingSubMap(m, fromStart, lo, loInclusive, false, toKey, inclusive);
}
public ONavigableMap tailMap(final K fromKey, final boolean inclusive) {
if (!inRange(fromKey, inclusive))
throw new IllegalArgumentException("fromKey out of range");
return new AscendingSubMap(m, false, fromKey, inclusive, toEnd, hi, hiInclusive);
}
public ONavigableMap descendingMap() {
ONavigableMap mv = descendingMapView;
return (mv != null) ? mv : (descendingMapView = new DescendingSubMap(m, fromStart, lo, loInclusive, toEnd, hi,
hiInclusive));
}
@Override
OLazyIterator keyIterator() {
return new SubMapKeyIterator(absLowest(), absHighFence());
}
@Override
OLazyIterator descendingKeyIterator() {
return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
}
@Override
public Set> entrySet() {
EntrySetView es = entrySetView;
return (es != null) ? es : new AscendingEntrySetView();
}
@Override
OMVRBTreeEntry subLowest() {
return absLowest().entry;
}
@Override
OMVRBTreeEntry subHighest() {
return absHighest().entry;
}
@Override
OMVRBTreeEntry subCeiling(final K key) {
return absCeiling(key).entry;
}
@Override
OMVRBTreeEntry subHigher(final K key) {
return absHigher(key).entry;
}
@Override
OMVRBTreeEntry subFloor(final K key) {
return absFloor(key).entry;
}
@Override
OMVRBTreeEntry subLower(final K key) {
return absLower(key).entry;
}
}
/**
* @serial include
*/
static final class DescendingSubMap extends NavigableSubMap {
private static final long serialVersionUID = 912986545866120460L;
final class DescendingEntrySetView extends EntrySetView {
@Override
public Iterator> iterator() {
return new DescendingSubMapEntryIterator(absHighest(), absLowFence());
}
}
private final Comparator reverseComparator = Collections.reverseOrder(m.comparator);
DescendingSubMap(final OMVRBTree m, final boolean fromStart, final K lo, final boolean loInclusive, final boolean toEnd,
final K hi, final boolean hiInclusive) {
super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
}
public Comparator comparator() {
return reverseComparator;
}
public ONavigableMap subMap(final K fromKey, final boolean fromInclusive, final K toKey, final boolean toInclusive) {
if (!inRange(fromKey, fromInclusive))
throw new IllegalArgumentException("fromKey out of range");
if (!inRange(toKey, toInclusive))
throw new IllegalArgumentException("toKey out of range");
return new DescendingSubMap(m, false, toKey, toInclusive, false, fromKey, fromInclusive);
}
public ONavigableMap headMap(final K toKey, final boolean inclusive) {
if (!inRange(toKey, inclusive))
throw new IllegalArgumentException("toKey out of range");
return new DescendingSubMap(m, false, toKey, inclusive, toEnd, hi, hiInclusive);
}
public ONavigableMap tailMap(final K fromKey, final boolean inclusive) {
if (!inRange(fromKey, inclusive))
throw new IllegalArgumentException("fromKey out of range");
return new DescendingSubMap(m, fromStart, lo, loInclusive, false, fromKey, inclusive);
}
public ONavigableMap descendingMap() {
ONavigableMap mv = descendingMapView;
return (mv != null) ? mv : (descendingMapView = new AscendingSubMap(m, fromStart, lo, loInclusive, toEnd, hi,
hiInclusive));
}
@Override
OLazyIterator keyIterator() {
return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
}
@Override
OLazyIterator descendingKeyIterator() {
return new SubMapKeyIterator(absLowest(), absHighFence());
}
@Override
public Set> entrySet() {
EntrySetView es = entrySetView;
return (es != null) ? es : new DescendingEntrySetView();
}
@Override
OMVRBTreeEntry subLowest() {
return absHighest().entry;
}
@Override
OMVRBTreeEntry subHighest() {
return absLowest().entry;
}
@Override
OMVRBTreeEntry subCeiling(final K key) {
return absFloor(key).entry;
}
@Override
OMVRBTreeEntry subHigher(final K key) {
return absLower(key).entry;
}
@Override
OMVRBTreeEntry subFloor(final K key) {
return absCeiling(key).entry;
}
@Override
OMVRBTreeEntry subLower(final K key) {
return absHigher(key).entry;
}
}
public class Values extends AbstractCollection {
@Override
public Iterator iterator() {
return new ValueIterator(getFirstEntry());
}
public Iterator inverseIterator() {
return new ValueInverseIterator(getLastEntry());
}
@Override
public int size() {
return OMVRBTree.this.size();
}
@Override
public boolean contains(final Object o) {
return OMVRBTree.this.containsValue(o);
}
@Override
public boolean remove(final Object o) {
for (OMVRBTreeEntry e = getFirstEntry(); e != null; e = next(e)) {
if (valEquals(e.getValue(), o)) {
deleteEntry(e);
return true;
}
}
return false;
}
@Override
public void clear() {
OMVRBTree.this.clear();
}
}
public class EntrySet extends AbstractSet> {
@Override
public Iterator> iterator() {
return new EntryIterator(getFirstEntry());
}
public Iterator> inverseIterator() {
return new InverseEntryIterator(getLastEntry());
}
@Override
public boolean contains(final Object o) {
if (!(o instanceof Map.Entry))
return false;
OMVRBTreeEntry entry = (OMVRBTreeEntry) o;
final V value = entry.getValue();
final V p = get(entry.getKey());
return p != null && valEquals(p, value);
}
@Override
public boolean remove(final Object o) {
if (!(o instanceof Map.Entry))
return false;
final OMVRBTreeEntry entry = (OMVRBTreeEntry) o;
final V value = entry.getValue();
OMVRBTreeEntry p = getEntry(entry.getKey(), PartialSearchMode.NONE);
if (p != null && valEquals(p.getValue(), value)) {
deleteEntry(p);
return true;
}
return false;
}
@Override
public int size() {
return OMVRBTree.this.size();
}
@Override
public void clear() {
OMVRBTree.this.clear();
}
}
final class EntryIterator extends AbstractEntryIterator> {
EntryIterator(final OMVRBTreeEntry first) {
super(first);
}
public Map.Entry next() {
return nextEntry();
}
}
final class InverseEntryIterator extends AbstractEntryIterator> {
InverseEntryIterator(final OMVRBTreeEntry last) {
super(last);
// we have to set ourselves after current index to make iterator work
if (last != null) {
pageIndex = last.getTree().getPageIndex() + 1;
}
}
public Map.Entry next() {
return prevEntry();
}
}
final class ValueIterator extends AbstractEntryIterator {
ValueIterator(final OMVRBTreeEntry first) {
super(first);
}
@Override
public V next() {
return nextValue();
}
}
final class ValueInverseIterator extends AbstractEntryIterator {
ValueInverseIterator(final OMVRBTreeEntry last) {
super(last);
// we have to set ourselves after current index to make iterator work
if (last != null) {
pageIndex = last.getTree().getPageIndex() + 1;
}
}
@Override
public boolean hasNext() {
return hasPrevious();
}
@Override
public V next() {
return prevValue();
}
}
final class KeyIterator extends AbstractEntryIterator {
KeyIterator(final OMVRBTreeEntry first) {
super(first);
}
@Override
public K next() {
return nextKey();
}
}
final class DescendingKeyIterator extends AbstractEntryIterator {
DescendingKeyIterator(final OMVRBTreeEntry first) {
super(first);
}
public K next() {
return prevEntry().getKey();
}
}
/**
* Constructs a new, empty tree map, using the natural ordering of its keys. All keys inserted into the map must implement the
* {@link Comparable} interface. Furthermore, all such keys must be mutually comparable: k1.compareTo(k2) must not
* throw a ClassCastException for any keys k1 and k2 in the map. If the user attempts to put a key into
* the map that violates this constraint (for example, the user attempts to put a string key into a map whose keys are integers),
* the put(Object key, Object value) call will throw a ClassCastException.
*/
public OMVRBTree() {
this(1);
}
public OMVRBTree(int keySize) {
comparator = ODefaultComparator.INSTANCE;
init();
this.keySize = keySize;
}
/**
* Constructs a new, empty tree map, ordered according to the given comparator. All keys inserted into the map must be mutually
* comparable by the given comparator: comparator.compare(k1,
* k2) must not throw a ClassCastException for any keys k1 and k2 in the map. If the user attempts
* to put a key into the map that violates this constraint, the put(Object
* key, Object value) call will throw a ClassCastException.
*
* @param iComparator
* the comparator that will be used to order this map. If null, the {@linkplain Comparable natural ordering} of
* the keys will be used.
*/
public OMVRBTree(final Comparator iComparator) {
init();
this.comparator = iComparator;
}
/**
* Constructs a new tree map containing the same mappings as the given map, ordered according to the natural ordering of
* its keys. All keys inserted into the new map must implement the {@link Comparable} interface. Furthermore, all such keys must
* be mutually comparable: k1.compareTo(k2) must not throw a ClassCastException for any keys k1
* and k2 in the map. This method runs in n*log(n) time.
*
* @param m
* the map whose mappings are to be placed in this map
* @throws ClassCastException
* if the keys in m are not {@link Comparable}, or are not mutually comparable
* @throws NullPointerException
* if the specified map is null
*/
public OMVRBTree(final Map m) {
comparator = ODefaultComparator.INSTANCE;
init();
putAll(m);
}
/**
* Constructs a new tree map containing the same mappings and using the same ordering as the specified sorted map. This method
* runs in linear time.
*
* @param m
* the sorted map whose mappings are to be placed in this map, and whose comparator is to be used to sort this map
* @throws NullPointerException
* if the specified map is null
*/
public OMVRBTree(final SortedMap m) {
init();
comparator = m.comparator();
try {
buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
}
/**
* Test two values for equality. Differs from o1.equals(o2) only in that it copes with null o1 properly.
*/
final static boolean valEquals(final Object o1, final Object o2) {
return (o1 == null ? o2 == null : o1.equals(o2));
}
/**
* Return SimpleImmutableEntry for entry, or null if null
*/
static Map.Entry exportEntry(final OMVRBTreeEntry omvrbTreeEntryPosition) {
return omvrbTreeEntryPosition == null ? null : new OSimpleImmutableEntry(omvrbTreeEntryPosition);
}
/**
* Return SimpleImmutableEntry for entry, or null if null
*/
static Map.Entry exportEntry(final OMVRBTreeEntryPosition omvrbTreeEntryPosition) {
return omvrbTreeEntryPosition == null ? null : new OSimpleImmutableEntry(omvrbTreeEntryPosition.entry);
}
/**
* Return key for entry, or null if null
*/
static K keyOrNull(final OMVRBTreeEntry e) {
return e == null ? null : e.getKey();
}
/**
* Return key for entry, or null if null
*/
static K keyOrNull(OMVRBTreeEntryPosition e) {
return e == null ? null : e.getKey();
}
/**
* Returns the key corresponding to the specified Entry.
*
* @throws NoSuchElementException
* if the Entry is null
*/
static K key(OMVRBTreeEntry e) {
if (e == null)
throw new NoSuchElementException();
return e.getKey();
}
public static OMVRBTreeEntry successor(final OMVRBTreeEntryPosition t) {
t.entry.getTree().setPageIndex(t.position);
return successor(t.entry);
}
/**
* Returns the successor of the specified Entry, or null if no such.
*/
public static OMVRBTreeEntry successor(final OMVRBTreeEntry t) {
if (t == null)
return null;
OMVRBTreeEntry p = null;
if (t.getRight() != null) {
p = t.getRight();
while (p.getLeft() != null)
p = p.getLeft();
} else {
p = t.getParent();
OMVRBTreeEntry ch = t;
while (p != null && ch == p.getRight()) {
ch = p;
p = p.getParent();
}
}
return p;
}
public static OMVRBTreeEntry next(final OMVRBTreeEntryPosition t) {
t.entry.getTree().setPageIndex(t.position);
return next(t.entry);
}
/**
* Returns the next item of the tree.
*/
public static OMVRBTreeEntry next(final OMVRBTreeEntry t) {
if (t == null)
return null;
final OMVRBTreeEntry succ;
if (t.tree.pageIndex < t.getSize() - 1) {
// ITERATE INSIDE THE NODE
succ = t;
t.tree.pageIndex++;
} else {
// GET THE NEXT NODE
succ = OMVRBTree.successor(t);
t.tree.pageIndex = 0;
}
return succ;
}
public static OMVRBTreeEntry predecessor(final OMVRBTreeEntryPosition t) {
t.entry.getTree().setPageIndex(t.position);
return predecessor(t.entry);
}
/**
* Returns the predecessor of the specified Entry, or null if no such.
*/
public static OMVRBTreeEntry predecessor(final OMVRBTreeEntry t) {
if (t == null)
return null;
else if (t.getLeft() != null) {
OMVRBTreeEntry p = t.getLeft();
while (p.getRight() != null)
p = p.getRight();
return p;
} else {
OMVRBTreeEntry p = t.getParent();
Entry ch = t;
while (p != null && ch == p.getLeft()) {
ch = p;
p = p.getParent();
}
return p;
}
}
// ONavigableMap API methods
public static OMVRBTreeEntry previous(final OMVRBTreeEntryPosition t) {
t.entry.getTree().setPageIndex(t.position);
return previous(t.entry);
}
/**
* Returns the previous item of the tree.
*/
public static OMVRBTreeEntry previous(final OMVRBTreeEntry t) {
if (t == null)
return null;
final int index = t.getTree().getPageIndex();
final OMVRBTreeEntry prev;
if (index <= 0) {
prev = predecessor(t);
if (prev != null)
t.tree.pageIndex = prev.getSize() - 1;
else
t.tree.pageIndex = 0;
} else {
prev = t;
t.tree.pageIndex = index - 1;
}
return prev;
}
/**
* Balancing operations.
*
* Implementations of rebalancings during insertion and deletion are slightly different than the CLR version. Rather than using
* dummy nilnodes, we use a set of accessors that deal properly with null. They are used to avoid messiness surrounding nullness
* checks in the main algorithms.
*/
private static boolean colorOf(final OMVRBTreeEntry p) {
return (p == null ? BLACK : p.getColor());
}
private static OMVRBTreeEntry parentOf(final OMVRBTreeEntry p) {
return (p == null ? null : p.getParent());
}
private static void setColor(final OMVRBTreeEntry p, final boolean c) {
if (p != null)
p.setColor(c);
}
private static OMVRBTreeEntry leftOf(final OMVRBTreeEntry p) {
return (p == null) ? null : p.getLeft();
}
private static OMVRBTreeEntry rightOf(final OMVRBTreeEntry p) {
return (p == null) ? null : p.getRight();
}
/**
* Find the level down to which to assign all nodes BLACK. This is the last `full' level of the complete binary tree produced by
* buildTree. The remaining nodes are colored RED. (This makes a `nice' set of color assignments wrt future insertions.) This
* level number is computed by finding the number of splits needed to reach the zeroeth node. (The answer is ~lg(N), but in any
* case must be computed by same quick O(lg(N)) loop.)
*/
private static int computeRedLevel(final int sz) {
int level = 0;
for (int m = sz - 1; m >= 0; m = m / 2 - 1)
level++;
return level;
}
public int getNodes() {
int counter = -1;
OMVRBTreeEntry