/* * This file is part of the HyperGraphDB source distribution. This is copyrighted * software. For permitted uses, licensing options and redistribution, please see * the LicensingInformation file at the root level of the distribution. * * Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved. */ package org.hypergraphdb.query.impl; import java.util.NoSuchElementException; import org.hypergraphdb.HGSearchResult; /** * <p> * Combines two ordered result sets into a (ordered) result representing their set theoretical intersection. * It assumes that the objects contained in the result sets being intersected * are <code>java.lang.Comparable</code> instances. * </p> * * @author Borislav Iordanov */ public class SortedIntersectionResult<T> implements HGSearchResult<T> //, RSCombiner<T> { private HGSearchResult<T> left, right; private T current = null, next = null, prev = null; private int lookahead = 0; @SuppressWarnings("unchecked") private T advance() { boolean advance_left = true, advance_right = true; Comparable<T> lnext = null, rnext = null; while (true) { if (advance_left) if (!left.hasNext()) return null; else lnext = (Comparable<T>)left.next(); if (advance_right) if (!right.hasNext()) return null; else rnext = (Comparable<T>)right.next(); int comp = lnext.compareTo((T)rnext); if (comp == 0) return (T)lnext; else if (comp < 0) // lnext < rnext { advance_left = true; advance_right = false; } else { advance_left = false; advance_right = true; } } } @SuppressWarnings("unchecked") private T back() { boolean back_left = true, back_right = true; Comparable<T> lprev = null, rprev = null; while (true) { if (back_left) if (!left.hasPrev()) return null; else lprev = (Comparable<T>)left.prev(); if (back_right) if (!right.hasPrev()) return null; else rprev = (Comparable<T>)right.prev(); int comp = lprev.compareTo((T)rprev); if (comp == 0) return (T)lprev; else if (comp < 0) // lprev < rprev { back_left = false; back_right = true; } else { back_left = false; back_right = true; } } } // public SortedIntersectionResult() // { // } public final static class Combiner<T> implements RSCombiner<T> { public HGSearchResult<T> combine(HGSearchResult<T> left, HGSearchResult<T> right) { return new SortedIntersectionResult<T>(left, right); } } public SortedIntersectionResult(HGSearchResult<T> left, HGSearchResult<T> right) { //init(left, right); this.left = left; this.right = right; next = advance(); lookahead = 1; } // public void reset() { // current = null; // next = null; // prev = null; // lookahead = 0; // } // // public void init(HGSearchResult<T> left, HGSearchResult<T> right) // { // this.left = left; // this.right = right; // next = advance(); // lookahead = 1; // } public T current() { if (current == null) throw new NoSuchElementException(); else return current; } public void close() { left.close(); right.close(); } public boolean hasPrev() { return prev != null; } public T prev() { if (prev == null) throw new NoSuchElementException(); else { next = current; current = prev; lookahead++; while (true) { prev = back(); if (prev == null) break; if (--lookahead == -1) break; } return current; } } public boolean hasNext() { return next != null; } public T next() { if (next == null) throw new NoSuchElementException(); else { prev = current; current = next; lookahead--; while (true) { next = advance(); if (next == null) break; if (++lookahead == 1) break; } return current; } } public void remove() { throw new UnsupportedOperationException(); } public boolean isOrdered() { return true; } }