/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.query.algebra.evaluation.iterator;
import java.util.Set;
import info.aduna.iteration.CloseableIteration;
import info.aduna.iteration.LookAheadIteration;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.algebra.LeftJoin;
import org.openrdf.query.algebra.evaluation.QueryBindingSet;
import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
import org.openrdf.query.algebra.evaluation.EvaluationStrategy;
public class LeftJoinIterator extends LookAheadIteration<BindingSet, QueryEvaluationException> {
/*-----------*
* Constants *
*-----------*/
private EvaluationStrategy strategy;
private final LeftJoin join;
/**
* The set of binding names that are "in scope" for the filter. The filter
* must not include bindings that are (only) included because of the
* depth-first evaluation strategy in the evaluation of the constraint.
*/
private final Set<String> scopeBindingNames;
/*-----------*
* Variables *
*-----------*/
private CloseableIteration<BindingSet, QueryEvaluationException> leftIter;
private CloseableIteration<BindingSet, QueryEvaluationException> rightIter;
/*--------------*
* Constructors *
*--------------*/
public LeftJoinIterator(EvaluationStrategy strategy, LeftJoin join, BindingSet bindings)
throws QueryEvaluationException
{
this.strategy = strategy;
this.join = join;
this.scopeBindingNames = join.getBindingNames();
leftIter = strategy.evaluate(join.getLeftArg(), bindings);
}
/*---------*
* Methods *
*---------*/
@Override
protected BindingSet getNextElement()
throws QueryEvaluationException
{
while (rightIter != null || leftIter.hasNext()) {
BindingSet leftBindings = null;
if (rightIter == null) {
// Use left arg's bindings in case join fails
leftBindings = leftIter.next();
rightIter = strategy.evaluate(join.getRightArg(), leftBindings);
}
while (rightIter.hasNext()) {
BindingSet rightBindings = rightIter.next();
try {
if (join.getCondition() == null) {
return rightBindings;
}
else {
// Limit the bindings to the ones that are in scope for this
// filter
QueryBindingSet scopeBindings = new QueryBindingSet(rightBindings);
scopeBindings.retainAll(scopeBindingNames);
if (strategy.isTrue(join.getCondition(), scopeBindings)) {
return rightBindings;
}
}
}
catch (ValueExprEvaluationException e) {
// Ignore, condition not evaluated successfully
}
}
rightIter.close();
rightIter = null;
if (leftBindings != null) {
// Join failed, return left arg's bindings
return leftBindings;
}
}
return null;
}
@Override
protected void handleClose()
throws QueryEvaluationException
{
if (rightIter != null) {
rightIter.close();
rightIter = null;
}
leftIter.close();
super.handleClose();
}
}