public PathIteration( StrictEvaluationStrategy evaluationStrategyImpl, Scope scope, Var startVar, TupleExpr pathExpression, Var endVar, Var contextVar, long minLength, BindingSet bindings) throws QueryEvaluationException { this.evaluationStrategyImpl = evaluationStrategyImpl; this.scope = scope; this.startVar = startVar; this.endVar = endVar; this.startVarFixed = startVar.hasValue() || bindings.hasBinding(startVar.getName()); this.endVarFixed = endVar.hasValue() || bindings.hasBinding(endVar.getName()); this.pathExpression = pathExpression; this.contextVar = contextVar; this.currentLength = minLength; this.bindings = bindings; this.reportedValues = makeSet(); this.unreportedValues = makeSet(); this.valueQueue = makeQueue(); createIteration(); }
private Value getVarValue(Var var, boolean fixedValue, BindingSet bindingSet) { Value v; if (fixedValue) { v = var.getValue(); if (v == null) { v = this.bindings.getValue(var.getName()); } } else { v = bindingSet.getValue(var.getName()); } return v; }
@Override protected BindingSet getNextElement() throws QueryEvaluationException { again: while (true) { while (!currentIter.hasNext()) { Iterations.closeCloseable(currentIter); createIteration(); // stop condition: if the iter is an EmptyIteration if (currentIter instanceof EmptyIteration<?, ?>) { break; } } while (currentIter.hasNext()) { BindingSet nextElement = currentIter.next(); if (!startVarFixed && !endVarFixed && currentVp != null) { Value startValue = currentVp.getStartValue(); if (startValue != null) { nextElement = new QueryBindingSet(nextElement); ((QueryBindingSet) nextElement).addBinding(startVar.getName(), startValue); } } Value v1, v2; if (startVarFixed && endVarFixed && currentLength > 2) { v1 = getVarValue(startVar, startVarFixed, nextElement); v2 = nextElement.getValue("END_" + JOINVAR_PREFIX + pathExpression.hashCode()); } else if (startVarFixed && endVarFixed && currentLength == 2) { v1 = getVarValue(startVar, startVarFixed, nextElement); v2 = nextElement.getValue( JOINVAR_PREFIX + (currentLength - 1) + "-" + pathExpression.hashCode()); } else { v1 = getVarValue(startVar, startVarFixed, nextElement); v2 = getVarValue(endVar, endVarFixed, nextElement); } if (!isCyclicPath(v1, v2)) { ValuePair vp = new ValuePair(v1, v2); if (reportedValues.contains(vp)) { // new arbitrary-length path semantics: filter out // duplicates if (currentIter.hasNext()) { continue; } else { // if the current iter is exhausted, we need to check // that no further paths of greater length still exists. continue again; } } if (startVarFixed && endVarFixed) { Value endValue = getVarValue(endVar, endVarFixed, nextElement); if (endValue.equals(v2)) { add(reportedValues, vp); if (!v1.equals(v2)) { addToQueue(valueQueue, vp); } if (!nextElement.hasBinding(startVar.getName())) { ((QueryBindingSet) nextElement).addBinding(startVar.getName(), v1); } if (!nextElement.hasBinding(endVar.getName())) { ((QueryBindingSet) nextElement).addBinding(endVar.getName(), v2); } return nextElement; } else { if (add(unreportedValues, vp)) { if (!v1.equals(v2)) { addToQueue(valueQueue, vp); } } continue again; } } else { add(reportedValues, vp); if (!v1.equals(v2)) { addToQueue(valueQueue, vp); } if (!nextElement.hasBinding(startVar.getName())) { ((QueryBindingSet) nextElement).addBinding(startVar.getName(), v1); } if (!nextElement.hasBinding(endVar.getName())) { ((QueryBindingSet) nextElement).addBinding(endVar.getName(), v2); } return nextElement; } } else { continue again; } } // if we're done, throw away the cached lists of values to avoid // hogging resources reportedValues.clear(); unreportedValues.clear(); valueQueue.clear(); return null; } }
public Var createAnonVar(String varName) { Var var = new Var(varName); var.setAnonymous(true); return var; }
@Override public void meet(Var var) { if (toBeReplaced.equals(var) || (toBeReplaced.isAnonymous() && var.isAnonymous() && (toBeReplaced.hasValue() && toBeReplaced.getValue().equals(var.getValue())))) { QueryModelNode parent = var.getParentNode(); parent.replaceChildNode(var, replacement); replacement.setParentNode(parent); } else if (replaceAnons && var.isAnonymous() && !var.hasValue()) { Var replacementVar = createAnonVar("anon-replace-" + var.getName() + index); QueryModelNode parent = var.getParentNode(); parent.replaceChildNode(var, replacementVar); replacementVar.setParentNode(parent); } }
private void createIteration() throws QueryEvaluationException { if (currentLength == 0L) { ZeroLengthPath zlp = new ZeroLengthPath(scope, startVar, endVar, contextVar); currentIter = this.evaluationStrategyImpl.evaluate(zlp, bindings); currentLength++; } else if (currentLength == 1) { TupleExpr pathExprClone = pathExpression.clone(); if (startVarFixed && endVarFixed) { Var replacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + pathExpression.hashCode()); VarReplacer replacer = new VarReplacer(endVar, replacement, 0, false); pathExprClone.visit(replacer); } currentIter = this.evaluationStrategyImpl.evaluate(pathExprClone, bindings); currentLength++; } else { currentVp = valueQueue.poll(); if (currentVp != null) { TupleExpr pathExprClone = pathExpression.clone(); if (startVarFixed && endVarFixed) { Var startReplacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + pathExpression.hashCode()); Var endReplacement = createAnonVar("END_" + JOINVAR_PREFIX + pathExpression.hashCode()); startReplacement.setAnonymous(false); endReplacement.setAnonymous(false); Value v = currentVp.getEndValue(); startReplacement.setValue(v); VarReplacer replacer = new VarReplacer(startVar, startReplacement, 0, false); pathExprClone.visit(replacer); replacer = new VarReplacer(endVar, endReplacement, 0, false); pathExprClone.visit(replacer); } else { Var toBeReplaced; Value v; if (!endVarFixed) { toBeReplaced = startVar; v = currentVp.getEndValue(); } else { toBeReplaced = endVar; v = currentVp.getStartValue(); } Var replacement = createAnonVar(JOINVAR_PREFIX + currentLength + "-" + pathExpression.hashCode()); replacement.setValue(v); VarReplacer replacer = new VarReplacer(toBeReplaced, replacement, 0, false); pathExprClone.visit(replacer); } currentIter = this.evaluationStrategyImpl.evaluate(pathExprClone, bindings); } else { currentIter = new EmptyIteration<BindingSet, QueryEvaluationException>(); } currentLength++; } }