RdfStarQueryEvaluationStep.java
/*******************************************************************************
* Copyright (c) 2020 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.query.algebra.evaluation.impl.evaluationsteps;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.common.iteration.ConvertingIteration;
import org.eclipse.rdf4j.common.iteration.FilterIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Triple;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.MutableBindingSet;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.algebra.Var;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryEvaluationStep;
import org.eclipse.rdf4j.query.algebra.evaluation.RDFStarTripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.QueryEvaluationContext;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy;
public class RdfStarQueryEvaluationStep implements QueryEvaluationStep {
private final Var extVar;
private final Var predVar;
private final Var objVar;
private final Var subjVar;
private final RDFStarTripleSource tripleSource;
private final QueryEvaluationContext context;
public RdfStarQueryEvaluationStep(Var subjVar, Var predVar, Var objVar, Var extVar,
RDFStarTripleSource tripleSource, QueryEvaluationContext context) {
this.extVar = extVar;
this.predVar = predVar;
this.objVar = objVar;
this.subjVar = subjVar;
this.tripleSource = tripleSource;
this.context = context;
}
@Override
public CloseableIteration<BindingSet> evaluate(BindingSet bindings) {
final Value subjValue = StrictEvaluationStrategy.getVarValue(subjVar, bindings);
final Value predValue = StrictEvaluationStrategy.getVarValue(predVar, bindings);
final Value objValue = StrictEvaluationStrategy.getVarValue(objVar, bindings);
final Value extValue = StrictEvaluationStrategy.getVarValue(extVar, bindings);
// case1: when we have a binding for extVar we use it in the reified nodes lookup
// case2: in which we have unbound extVar
// in both cases:
// 1. iterate over all statements matching ((* | extValue), rdf:type, rdf:Statement)
// 2. construct a look ahead iteration and filter these solutions that do not match the
// bindings for the subject, predicate and object vars (if these are bound)
// return set of solution where the values of the statements (extVar, rdf:subject/predicate/object,
// value)
// are bound to the variables of the respective TripleRef variables for subject, predicate, object
// NOTE: if the tripleSource is extended to allow for lookup over asserted Triple values in the
// underlying sail
// the evaluation of the TripleRef should be suitably forwarded down the sail and filter/construct
// the correct solution out of the results of that call
if (extValue != null && !(extValue instanceof Resource)) {
return EMPTY_ITERATION;
}
// in case the
CloseableIteration<? extends Triple> sourceIter = tripleSource
.getRdfStarTriples((Resource) subjValue, (IRI) predValue, objValue);
FilterIteration<Triple> filterIter = new FilterIteration<>(
sourceIter) {
@Override
protected boolean accept(Triple triple) throws QueryEvaluationException {
if (subjValue != null && !subjValue.equals(triple.getSubject())) {
return false;
}
if (predValue != null && !predValue.equals(triple.getPredicate())) {
return false;
}
if (objValue != null && !objValue.equals(triple.getObject())) {
return false;
}
if (extValue != null && !extValue.equals(triple)) {
return false;
}
return true;
}
@Override
protected void handleClose() {
}
};
return new ConvertingIteration<>(filterIter) {
@Override
protected BindingSet convert(Triple triple) throws QueryEvaluationException {
MutableBindingSet result = context.createBindingSet(bindings);
if (subjValue == null) {
result.addBinding(subjVar.getName(), triple.getSubject());
}
if (predValue == null) {
result.addBinding(predVar.getName(), triple.getPredicate());
}
if (objValue == null) {
result.addBinding(objVar.getName(), triple.getObject());
}
// add the extVar binding if we do not have a value bound.
if (extValue == null) {
result.addBinding(extVar.getName(), triple);
}
return result;
}
};
}
}