CustomGraphQueryInferencerTest.java
/*******************************************************************************
* Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
*
* 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.sail.inferencer.fc;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.stream.Stream;
import org.eclipse.rdf4j.common.io.ResourceUtil;
import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.query.MalformedQueryException;
import org.eclipse.rdf4j.query.QueryLanguage;
import org.eclipse.rdf4j.query.UnsupportedQueryLanguageException;
import org.eclipse.rdf4j.query.UpdateExecutionException;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.RepositoryException;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.RDFParseException;
import org.eclipse.rdf4j.sail.NotifyingSail;
import org.eclipse.rdf4j.sail.SailException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public abstract class CustomGraphQueryInferencerTest {
@BeforeAll
public static void setUpClass() {
System.setProperty("org.eclipse.rdf4j.repository.debug", "true");
}
@AfterAll
public static void afterClass() {
System.setProperty("org.eclipse.rdf4j.repository.debug", "false");
}
protected static class Expectation {
private final int initialCount, countAfterRemove, subjCount, predCount, objCount;
public Expectation(int initialCount, int countAfterRemove, int subjCount, int predCount, int objCount) {
this.initialCount = initialCount;
this.countAfterRemove = countAfterRemove;
this.subjCount = subjCount;
this.predCount = predCount;
this.objCount = objCount;
}
}
private static final String TEST_DIR_PREFIX = "/custom-query-inferencing/";
private static final String BASE = "http://foo.org/bar#";
private static final String PREDICATE = "predicate";
public static final Stream<Arguments> parameters() {
Expectation predExpect = new Expectation(8, 2, 0, 2, 0);
return Stream.of(
Arguments.of(PREDICATE, predExpect, QueryLanguage.SPARQL),
Arguments.of("resource", new Expectation(4, 2, 2, 0, 2), QueryLanguage.SPARQL)
);
}
private String initial;
private String delete;
protected void runTest(final CustomGraphQueryInferencer inferencer, String resourceFolder, Expectation testData)
throws RepositoryException, RDFParseException,
IOException, MalformedQueryException, UpdateExecutionException {
// Initialize
Repository sail = new SailRepository(inferencer);
try (RepositoryConnection connection = sail.getConnection()) {
connection.begin();
connection.clear();
connection.add(new StringReader(initial), BASE, RDFFormat.TURTLE);
// Test initial inferencer state
Collection<Value> watchPredicates = inferencer.getWatchPredicates();
assertThat(watchPredicates).hasSize(testData.predCount);
Collection<Value> watchObjects = inferencer.getWatchObjects();
assertThat(watchObjects).hasSize(testData.objCount);
Collection<Value> watchSubjects = inferencer.getWatchSubjects();
assertThat(watchSubjects).hasSize(testData.subjCount);
ValueFactory factory = connection.getValueFactory();
if (resourceFolder.startsWith(PREDICATE)) {
assertThat(watchPredicates.contains(factory.createIRI(BASE, "brotherOf"))).isTrue();
assertThat(watchPredicates.contains(factory.createIRI(BASE, "parentOf"))).isTrue();
} else {
IRI bob = factory.createIRI(BASE, "Bob");
IRI alice = factory.createIRI(BASE, "Alice");
assertThat(watchSubjects).contains(bob, alice);
assertThat(watchObjects).contains(bob, alice);
}
// Test initial inferencing results
assertThat(Iterations.asSet(connection.getStatements(null, null, null, true)))
.hasSize(testData.initialCount);
// Test results after removing some statements
connection.prepareUpdate(QueryLanguage.SPARQL, delete).execute();
assertThat(Iterations.asSet(connection.getStatements(null, null, null, true)))
.hasSize(testData.countAfterRemove);
// Tidy up. Storage gets re-used for subsequent tests, so must clear here,
// in order to properly clear out any inferred statements.
connection.clear();
connection.commit();
}
sail.shutDown();
}
protected CustomGraphQueryInferencer createRepository(boolean withMatchQuery, String resourceFolder,
QueryLanguage language)
throws IOException, MalformedQueryException, UnsupportedQueryLanguageException, RepositoryException,
SailException, RDFParseException {
String testFolder = TEST_DIR_PREFIX + resourceFolder;
String rule = ResourceUtil.getString(testFolder + "/rule.rq");
String match = withMatchQuery ? ResourceUtil.getString(testFolder + "/match.rq") : "";
initial = ResourceUtil.getString(testFolder + "/initial.ttl");
delete = ResourceUtil.getString(testFolder + "/delete.ru");
NotifyingSail store = newSail();
return new CustomGraphQueryInferencer(store, language, rule, match);
}
/**
* Gets an instance of the Sail that should be tested. The returned repository must not be initialized.
*
* @return an uninitialized NotifyingSail.
*/
protected abstract NotifyingSail newSail();
@ParameterizedTest(name = "{0}")
@MethodSource("parameters")
public void testCustomQueryInference(String resourceFolder, Expectation testData, QueryLanguage language)
throws RepositoryException, RDFParseException, MalformedQueryException,
UpdateExecutionException, IOException, UnsupportedQueryLanguageException, SailException {
runTest(createRepository(true, resourceFolder, language), resourceFolder, testData);
}
@ParameterizedTest(name = "{0}")
@MethodSource("parameters")
public void testCustomQueryInferenceImplicitMatcher(String resourceFolder, Expectation testData,
QueryLanguage language)
throws RepositoryException, RDFParseException, MalformedQueryException, UpdateExecutionException,
IOException, UnsupportedQueryLanguageException, SailException {
runTest(createRepository(false, resourceFolder, language), resourceFolder, testData);
}
}