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 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); } }
@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; } }