/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.internal.btree; import com.db4o.foundation.*; import com.db4o.internal.*; import com.db4o.internal.btree.algebra.*; /** * @exclude */ public class BTreeRangeSingle implements BTreeRange { public static final Comparison4 COMPARISON = new Comparison4() { public int compare(Object x, Object y) { BTreeRangeSingle xRange = (BTreeRangeSingle)x; BTreeRangeSingle yRange = (BTreeRangeSingle)y; return xRange.first().compareTo(yRange.first()); } }; private final Transaction _transaction; private final BTree _btree; private final BTreePointer _first; private final BTreePointer _end; public BTreeRangeSingle(Transaction transaction, BTree btree, BTreePointer first, BTreePointer end) { if (transaction == null || btree == null) { throw new ArgumentNullException(); } _transaction = transaction; _btree = btree; _first = first; _end = end; } public void accept(BTreeRangeVisitor visitor) { visitor.visit(this); } public boolean isEmpty() { return BTreePointer.equals(_first, _end); } public int size(){ if(isEmpty()){ return 0; } // TODO: This was an attempt to improve size calculation. // Since all nodes are read, there is no improvement. // BTreeNode currentNode = _first.node(); // int sizeOnFirst = currentNode.count() - _first.index(); // // BTreeNode endNode = _end == null ? null : _end.node(); // int substractForEnd = // (endNode == null) ? 0 : (endNode.count() - _end.index()); // // int size = sizeOnFirst - substractForEnd; // while(! currentNode.equals(endNode)){ // currentNode = currentNode.nextNode(); // if(currentNode == null){ // break; // } // currentNode.prepareRead(transaction()); // size += currentNode.count(); // } // return size; int size = 0; final Iterator4 i = keys(); while (i.moveNext()) { ++size; } return size; } public Iterator4 pointers() { return new BTreeRangePointerIterator(this); } public Iterator4 keys() { return new BTreeRangeKeyIterator(this); } public final BTreePointer end() { return _end; } public Transaction transaction() { return _transaction; } public BTreePointer first() { return _first; } public BTreeRange greater() { return newBTreeRangeSingle(_end, null); } public BTreeRange union(BTreeRange other) { if (null == other) { throw new ArgumentNullException(); } return new BTreeRangeSingleUnion(this).dispatch(other); } public boolean adjacent(BTreeRangeSingle range) { return BTreePointer.equals(_end, range._first) || BTreePointer.equals(range._end, _first); } public boolean overlaps(BTreeRangeSingle range) { return firstOverlaps(this, range) || firstOverlaps(range, this); } private boolean firstOverlaps(BTreeRangeSingle x, BTreeRangeSingle y) { return BTreePointer.lessThan(y._first, x._end) && BTreePointer.lessThan(x._first, y._end); } public BTreeRange extendToFirst() { return newBTreeRangeSingle(firstBTreePointer(), _end); } public BTreeRange extendToLast() { return newBTreeRangeSingle(_first, null); } public BTreeRange smaller() { return newBTreeRangeSingle(firstBTreePointer(), _first); } public BTreeRangeSingle newBTreeRangeSingle(BTreePointer first, BTreePointer end) { return new BTreeRangeSingle(transaction(), _btree, first, end); } public BTreeRange newEmptyRange() { return newBTreeRangeSingle(null, null); } private BTreePointer firstBTreePointer() { // We don't want nulls included so we have to search for null and use the resulting pointer if we find one. Indexable4 keyHandler = btree().keyHandler(); if(keyHandler instanceof CanExcludeNullInQueries){ CanExcludeNullInQueries canExcludeNullInQueries = (CanExcludeNullInQueries) keyHandler; if(canExcludeNullInQueries.excludeNull()){ BTreeNodeSearchResult searchLeaf = btree().searchLeafByObject(transaction(), null, SearchTarget.HIGHEST); BTreePointer pointer = searchLeaf.firstValidPointer(); if(pointer != null){ return pointer; } } } return btree().firstPointer(transaction()); } private BTree btree() { return _btree; } public BTreeRange intersect(BTreeRange range) { if (null == range) { throw new ArgumentNullException(); } return new BTreeRangeSingleIntersect(this).dispatch(range); } public BTreeRange extendToLastOf(BTreeRange range) { BTreeRangeSingle rangeImpl = checkRangeArgument(range); return newBTreeRangeSingle(_first, rangeImpl._end); } public String toString() { return "BTreeRangeSingle(first=" + _first + ", end=" + _end + ")"; } private BTreeRangeSingle checkRangeArgument(BTreeRange range) { if (null == range) { throw new ArgumentNullException(); } BTreeRangeSingle rangeImpl = (BTreeRangeSingle)range; if (btree() != rangeImpl.btree()) { throw new IllegalArgumentException(); } return rangeImpl; } public BTreePointer lastPointer() { if(_end == null){ return btree().lastPointer(transaction()); } return _end.previous(); } }