/* 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.algebra; import com.db4o.foundation.*; import com.db4o.internal.btree.*; /** * @exclude */ class BTreeAlgebra { public static BTreeRange intersect(BTreeRangeUnion union, BTreeRangeSingle single) { final SortedCollection4 collection = newBTreeRangeSingleCollection(); collectIntersections(collection, union, single); return toRange(collection); } public static BTreeRange intersect(BTreeRangeUnion union1, BTreeRangeUnion union2) { final SortedCollection4 collection = newBTreeRangeSingleCollection(); final Iterator4 ranges = union1.ranges(); while (ranges.moveNext()) { final BTreeRangeSingle current = (BTreeRangeSingle) ranges.current(); collectIntersections(collection, union2, current); } return toRange(collection); } private static void collectIntersections(final SortedCollection4 collection, BTreeRangeUnion union, BTreeRangeSingle single) { final Iterator4 ranges = union.ranges(); while (ranges.moveNext()) { final BTreeRangeSingle current = (BTreeRangeSingle) ranges.current(); if (single.overlaps(current)) { collection.add(single.intersect(current)); } } } public static BTreeRange intersect(BTreeRangeSingle single1, BTreeRangeSingle single2) { BTreePointer first = BTreePointer.max(single1.first(), single2.first()); BTreePointer end = BTreePointer.min(single1.end(), single2.end()); return single1.newBTreeRangeSingle(first, end); } public static BTreeRange union(final BTreeRangeUnion union1, final BTreeRangeUnion union2) { final Iterator4 ranges = union1.ranges(); BTreeRange merged = union2; while (ranges.moveNext()) { merged = merged.union((BTreeRange) ranges.current()); } return merged; } public static BTreeRange union(final BTreeRangeUnion union, final BTreeRangeSingle single) { if (single.isEmpty()) { return union; } SortedCollection4 sorted = newBTreeRangeSingleCollection(); sorted.add(single); BTreeRangeSingle range = single; Iterator4 ranges = union.ranges(); while (ranges.moveNext()) { BTreeRangeSingle current = (BTreeRangeSingle) ranges.current(); if (canBeMerged(current, range)) { sorted.remove(range); range = merge(current, range); sorted.add(range); } else { sorted.add(current); } } return toRange(sorted); } private static BTreeRange toRange(SortedCollection4 sorted) { if (1 == sorted.size()) { return (BTreeRange)sorted.singleElement(); } return new BTreeRangeUnion(sorted); } private static SortedCollection4 newBTreeRangeSingleCollection() { return new SortedCollection4(BTreeRangeSingle.COMPARISON); } public static BTreeRange union(final BTreeRangeSingle single1, final BTreeRangeSingle single2) { if (single1.isEmpty()) { return single2; } if (single2.isEmpty()) { return single1; } if (canBeMerged(single1, single2)) { return merge(single1, single2); } return new BTreeRangeUnion(new BTreeRangeSingle[] { single1, single2 }); } private static BTreeRangeSingle merge(BTreeRangeSingle range1, BTreeRangeSingle range2) { return range1.newBTreeRangeSingle( BTreePointer.min(range1.first(), range2.first()), BTreePointer.max(range1.end(), range2.end())); } private static boolean canBeMerged(BTreeRangeSingle range1, BTreeRangeSingle range2) { return range1.overlaps(range2) || range1.adjacent(range2); } }