PathIterationTest.java
/*******************************************************************************
* Copyright (c) 2023 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.iterator;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.eclipse.rdf4j.common.iteration.CloseableIteratorIteration;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.LinkedHashModel;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.QueryEvaluationException;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.StatementPattern.Scope;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.Var;
import org.eclipse.rdf4j.query.algebra.evaluation.QueryBindingSet;
import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.DefaultEvaluationStrategy;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class PathIterationTest {
private DefaultEvaluationStrategy evaluator;
private static final ValueFactory vf = SimpleValueFactory.getInstance();
private static final Resource one = vf.createIRI("https://example.org/", "one");
private static final Resource two = vf.createIRI("https://example.org/", "two");
private static final Resource three = vf.createIRI("https://example.org/", "three");
@BeforeEach
public void setUp() {
Model m = new LinkedHashModel();
m.add(one, RDFS.SUBCLASSOF, two);
m.add(two, RDFS.SUBCLASSOF, three);
TripleSource ts = new TripleSource() {
@Override
public CloseableIteration<? extends Statement> getStatements(Resource subj,
IRI pred, Value obj, Resource... contexts) throws QueryEvaluationException {
return new CloseableIteratorIteration<>(m.getStatements(subj, pred, obj, contexts).iterator());
}
@Override
public ValueFactory getValueFactory() {
return vf;
}
};
evaluator = new DefaultEvaluationStrategy(ts, null);
}
@Test
public void zeroHop() {
// SELECT * WHERE { ?subClass rdfs:subClassOf+ ?superClass }
Var startVar = new Var("subClass");
Var endVar = new Var("superClass");
TupleExpr pathExpression = new StatementPattern(startVar, new Var("lala", RDFS.SUBCLASSOF, true, true), endVar);
Var contextVar = null;
long minLength = 0;
BindingSet bindings = new QueryBindingSet();
// Expect but not necessary in this order
// one | one
// one | two
// one | three
// two | three
// two | two
// three | three
try (PathIteration zlp = new PathIteration(evaluator, Scope.DEFAULT_CONTEXTS, startVar,
pathExpression, endVar, contextVar, minLength, bindings)) {
assertExpected(zlp.getNextElement(), one, one);
assertExpected(zlp.getNextElement(), two, two);
assertExpected(zlp.getNextElement(), three, three);
assertExpected(zlp.getNextElement(), one, two);
assertExpected(zlp.getNextElement(), two, three);
assertExpected(zlp.getNextElement(), one, three);
assertNull(zlp.getNextElement());
}
}
void assertExpected(BindingSet result, Value subClass, Value superClass) {
assertNotNull(result);
assertTrue(result.hasBinding("subClass"), "path zlp evaluation should binding for subClass var");
assertEquals(subClass, result.getBinding("subClass").getValue());
assertTrue(result.hasBinding("superClass"), "path zlp evaluation should binding for superClass var");
assertEquals(superClass, result.getBinding("superClass").getValue());
assertEquals(2, result.size());
}
@Test
public void oneHop() {
// SELECT * WHERE { ?subClass rdfs:subClassOf+ ?superClass }
Var startVar = new Var("subClass");
Var endVar = new Var("superClass");
TupleExpr pathExpression = new StatementPattern(startVar, new Var("lala", RDFS.SUBCLASSOF, true, true), endVar);
Var contextVar = null;
long minLength = 1;
// Expected
// one two
// one three
// two three
BindingSet bindings = new QueryBindingSet();
try (PathIteration zlp = new PathIteration(evaluator, Scope.DEFAULT_CONTEXTS, startVar,
pathExpression, endVar, contextVar, minLength, bindings)) {
assertExpected(zlp.getNextElement(), one, two);
assertExpected(zlp.getNextElement(), two, three);
assertExpected(zlp.getNextElement(), one, three);
assertNull(zlp.getNextElement());
}
}
@Test
public void oneHopStartConstant() {
// SELECT * WHERE { ?subClass rdfs:subClassOf+ ?superClass }
Var startVar = new Var("subClass", one, true, true);
Var endVar = new Var("superClass");
TupleExpr pathExpression = new StatementPattern(startVar, new Var("lala", RDFS.SUBCLASSOF, true, true), endVar);
Var contextVar = null;
long minLength = 1;
BindingSet bindings = new QueryBindingSet();
try (PathIteration zlp = new PathIteration(evaluator, Scope.DEFAULT_CONTEXTS, startVar,
pathExpression, endVar, contextVar, minLength, bindings)) {
assertExpected(zlp.getNextElement(), one, two);
assertExpected(zlp.getNextElement(), one, three);
assertNull(zlp.getNextElement());
}
}
}