/*
* 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;
import org.hypergraphdb.util.CloseMe;
import org.hypergraphdb.util.Mapping;
/**
*
* <p>
* Filter a result set through a predicate.
* </p>
*
* @author Borislav Iordanov
*/
public class FilteredResultSet<T> implements HGSearchResult<T>
{
HGSearchResult<T> searchResult;
Mapping<T, Boolean> predicate;
T current = null;
//
// The number of elements preceding the current in the underlying
// searchResult that satisfy the predicate.
//
private int prevCount = -1;
//
// The diff in the underlying result b/w the location of our 'current' member
// variable and its own "current" element.
//
private int lookahead = 0;
/**
* <p>
* The constructor assumes the underlying set is already positioned to the
* first matching entity.
* </p>
*
* @param hg The
* @param searchResult
* @param predicate
*/
public FilteredResultSet(HGSearchResult<T> searchResult,
Mapping<T, Boolean> predicate,
int lookahead)
{
this.searchResult = searchResult;
this.predicate = predicate;
this.lookahead = lookahead;
}
public void close()
{
searchResult.close();
if (predicate instanceof CloseMe)
((CloseMe)predicate).close();
}
public T current()
{
return current;
}
public boolean hasPrev()
{
return prevCount > 0;
}
public T prev()
{
if (prevCount == 0)
throw new NoSuchElementException();
while (lookahead > 0)
{
lookahead--;
searchResult.prev();
}
prevCount--;
while (searchResult.hasPrev() && !predicate.eval(searchResult.prev()));
return current = searchResult.current();
}
public boolean hasNext()
{
if (lookahead > 0) {
// System.out.println("Evaluating with LA current:" + searchResult.current());
boolean res = predicate.eval(searchResult.current());
if (res) {
// System.out.println("Evaluating with LA current was valid");
return true;
}
// System.out.println("Evaluating with LA current was invalid, so trying further");
}
while (true)
{
if (!searchResult.hasNext()) {
// System.out.println("No more next");
return false;
}
lookahead++;
T next2 = searchResult.next();
// System.out.println("Evaluating with for next:" + next2);
if (!predicate.eval(next2))
continue;
else {
// System.out.println("Has next is true for next of:" + next2);
return true;
}
}
}
public T next()
{
if (!hasNext())
throw new NoSuchElementException();
else
{
prevCount++;
lookahead = 0;
return current = searchResult.current();
}
}
public void remove()
{
while (lookahead > 0)
{
searchResult.prev();
lookahead--;
}
searchResult.remove();
}
public boolean isOrdered()
{
return searchResult.isOrdered();
}
}