BasicTests.java
/*******************************************************************************
* Copyright (c) 2019 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.federated;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.rdf4j.common.iteration.Iterations;
import org.eclipse.rdf4j.federated.endpoint.Endpoint;
import org.eclipse.rdf4j.federated.structures.FedXDataset;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.util.Values;
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
import org.eclipse.rdf4j.model.vocabulary.FOAF;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.AbstractTupleQueryResultHandler;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.BooleanQuery;
import org.eclipse.rdf4j.query.GraphQuery;
import org.eclipse.rdf4j.query.GraphQueryResult;
import org.eclipse.rdf4j.query.QueryResults;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.TupleQueryResult;
import org.eclipse.rdf4j.query.TupleQueryResultHandlerException;
import org.eclipse.rdf4j.query.impl.SimpleDataset;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.util.Repositories;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class BasicTests extends SPARQLBaseTest {
@Test
public void test1() throws Exception {
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query01.rq", "/tests/basic/query01.srx", false, true);
}
@Test
public void test2() throws Exception {
/* test a basic Construct query retrieving all triples */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query02.rq", "/tests/basic/query02.ttl", false, true);
}
@Test
public void testBooleanTrueSingleSource() throws Exception {
/* test a basic boolean query (result true) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query03.rq", "/tests/basic/query03.srx", false, true);
}
@Test
public void testBooleanTrueMultipleSource() throws Exception {
/* test a basic boolean query (result true) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query03a.rq", "/tests/basic/query03.srx", false, true);
}
@Test
public void testBooleanFalse() throws Exception {
/* test a basic boolean query (result false) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query04.rq", "/tests/basic/query04.srx", false, true);
}
@Test
public void testSingleSourceSelect() throws Exception {
/* test a single source select query */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_singleSource01.rq", "/tests/basic/query_singleSource01.srx", false, true);
}
@Test
public void testSingleSourceConstruct() throws Exception {
/* test a single source construct */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_singleSource02.rq", "/tests/basic/query_singleSource02.ttl", false, true);
}
@Test
public void testGetStatements() throws Exception {
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
Set<Statement> res = getStatements(null, null, null);
compareGraphs(res, readExpectedGraphQueryResult("/tests/basic/query02.ttl"));
}
@Test
public void testValuesClause() throws Exception {
/* test query with values clause */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_values.rq", "/tests/basic/query_values.srx", false, true);
}
@Test
public void testQuotes() throws Exception {
/* test query with new line in literal */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint3.ttl"));
execute("/tests/basic/query_quotes.rq", "/tests/basic/query_quotes.srx", false, true);
}
@Test
public void testQuotesDatatype() throws Exception {
/* test query with new line in triple quotes and datatype */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint3.ttl"));
execute("/tests/basic/query_quotes_datatype.rq", "/tests/basic/query_quotes_datatype.srx", false, true);
}
@Test
public void testLanguageTag() throws Exception {
/* test query with a language tag */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint4.ttl"));
execute("/tests/basic/query_lang.rq", "/tests/basic/query_lang.srx", false, true);
}
@Test
public void testBindClause() throws Exception {
/* test query with bind clause */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_bind.rq", "/tests/basic/query_bind.srx", false, true);
}
@Test
public void testRepositoryConnectionApi() throws Exception {
prepareTest(
Arrays.asList("/tests/basic/data_emptyStore.ttl", "/tests/basic/data_emptyStore.ttl"));
Repository repo1 = getRepository(1);
Repository repo2 = getRepository(2);
IRI bob = Values.iri("http://example.org/bob");
IRI alice = Values.iri("http://example.org/alice");
IRI graph1 = Values.iri("http://example.org/graph1");
IRI graph2 = Values.iri("http://example.org/graph2");
try (RepositoryConnection conn = repo1.getConnection()) {
conn.add(bob, RDF.TYPE, FOAF.PERSON, graph1);
conn.add(bob, FOAF.NAME, Values.literal("Bob"), graph1);
}
try (RepositoryConnection conn = repo2.getConnection()) {
conn.add(alice, RDF.TYPE, FOAF.PERSON, graph2);
conn.add(alice, FOAF.NAME, Values.literal("Alice"), graph2);
}
var fedxRepo = fedxRule.getRepository();
try (var conn = fedxRepo.getConnection()) {
// hasStatement which exist
Assertions.assertTrue(conn.hasStatement(bob, RDF.TYPE, FOAF.PERSON, false));
Assertions.assertTrue(conn.hasStatement(bob, RDF.TYPE, FOAF.PERSON, false, graph1));
Assertions.assertTrue(conn.hasStatement(null, RDF.TYPE, FOAF.PERSON, false));
Assertions.assertTrue(conn.hasStatement(null, RDF.TYPE, FOAF.PERSON, false, graph1));
Assertions.assertTrue(conn.hasStatement(null, RDF.TYPE, null, false));
Assertions.assertTrue(conn.hasStatement(null, RDF.TYPE, null, false, graph1));
Assertions.assertTrue(conn.hasStatement(null, RDF.TYPE, null, false, graph2));
Assertions.assertTrue(conn.hasStatement(null, null, null, false));
Assertions.assertTrue(conn.hasStatement(null, null, null, false, graph1));
// hasStatement which do not exist
Assertions.assertFalse(conn.hasStatement(bob, RDF.TYPE, FOAF.ORGANIZATION, false));
Assertions.assertFalse(conn.hasStatement(bob, RDF.TYPE, FOAF.PERSON, false, graph2));
// getStatements
Assertions.assertEquals(Set.of(bob, alice),
QueryResults.asModel(conn.getStatements(null, RDF.TYPE, FOAF.PERSON, false)).subjects());
Assertions.assertEquals(Set.of(bob),
QueryResults.asModel(conn.getStatements(null, RDF.TYPE, FOAF.PERSON, false, graph1)).subjects());
Assertions.assertEquals(Set.of(bob, alice),
QueryResults.asModel(conn.getStatements(null, null, null, false)).subjects());
Assertions.assertEquals(Set.of(bob),
QueryResults.asModel(conn.getStatements(null, null, null, false, graph1)).subjects());
}
}
@Test
public void testFederationSubSetQuery() throws Exception {
String ns1 = "http://namespace1.org/";
String ns2 = "http://namespace2.org/";
List<Endpoint> endpoints = prepareTest(Arrays.asList("/tests/data/data1.ttl", "/tests/data/data2.ttl",
"/tests/data/data3.ttl",
"/tests/data/data4.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person a <http://xmlns.com/foaf/0.1/Person> }");
try (TupleQueryResult result = tq.evaluate()) {
try (TupleQueryResult expected = tupleQueryResultBuilder(List.of("person"))
.add(List.of(vf.createIRI(ns1, "Person_1")))
.add(List.of(vf.createIRI(ns1, "Person_2")))
.add(List.of(vf.createIRI(ns1, "Person_3")))
.add(List.of(vf.createIRI(ns1, "Person_4")))
.add(List.of(vf.createIRI(ns1, "Person_5")))
.add(List.of(vf.createIRI(ns2, "Person_6")))
.add(List.of(vf.createIRI(ns2, "Person_7")))
.add(List.of(vf.createIRI(ns2, "Person_8")))
.add(List.of(vf.createIRI(ns2, "Person_9")))
.add(List.of(vf.createIRI(ns2, "Person_10")))
.build()) {
compareTupleQueryResults(result, expected, false);
}
}
// evaluate against ep 1 and ep 3 only
FedXDataset fedxDataset = new FedXDataset(tq.getDataset());
fedxDataset.addEndpoint(endpoints.get(0).getId());
fedxDataset.addEndpoint(endpoints.get(2).getId());
tq.setDataset(fedxDataset);
try (TupleQueryResult result = tq.evaluate()) {
try (TupleQueryResult expected = tupleQueryResultBuilder(List.of("person"))
.add(List.of(vf.createIRI(ns1, "Person_1")))
.add(List.of(vf.createIRI(ns1, "Person_2")))
.add(List.of(vf.createIRI(ns1, "Person_3")))
.add(List.of(vf.createIRI(ns1, "Person_4")))
.add(List.of(vf.createIRI(ns1, "Person_5")))
.build()) {
compareTupleQueryResults(result, expected, false);
}
}
}
}
@Test
public void testFederationSubSetQueryWithDataset() throws Exception {
String ns1 = "http://namespace1.org/";
String ns2 = "http://namespace2.org/";
prepareTest(Arrays.asList("/tests/data/data1.trig", "/tests/data/data2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person a <http://xmlns.com/foaf/0.1/Person> }");
try (TupleQueryResult result = tq.evaluate()) {
try (TupleQueryResult expected = tupleQueryResultBuilder(List.of("person"))
.add(List.of(vf.createIRI(ns1, "Person_1")))
.add(List.of(vf.createIRI(ns1, "Person_2")))
.add(List.of(vf.createIRI(ns1, "Person_3")))
.add(List.of(vf.createIRI(ns1, "Person_4")))
.add(List.of(vf.createIRI(ns1, "Person_5")))
.add(List.of(vf.createIRI(ns2, "Person_6")))
.add(List.of(vf.createIRI(ns2, "Person_7")))
.add(List.of(vf.createIRI(ns2, "Person_8")))
.add(List.of(vf.createIRI(ns2, "Person_9")))
.add(List.of(vf.createIRI(ns2, "Person_10")))
.build()) {
compareTupleQueryResults(result, expected, false);
}
}
// evaluate against ep 1 and ep 3 only
SimpleDataset fedxDataset = new SimpleDataset();
fedxDataset.addDefaultGraph(vf.createIRI(ns1, "PG1"));
tq.setDataset(fedxDataset);
try (TupleQueryResult result = tq.evaluate()) {
try (TupleQueryResult expected = tupleQueryResultBuilder(List.of("person"))
.add(List.of(vf.createIRI(ns1, "Person_1")))
.build()) {
compareTupleQueryResults(result, expected, false);
}
}
}
}
@Test
public void testQueryBinding() throws Exception {
final QueryManager qm = federationContext().getQueryManager();
prepareTest(Arrays.asList("/tests/medium/data1.ttl", "/tests/medium/data2.ttl", "/tests/medium/data3.ttl",
"/tests/medium/data4.ttl"));
String queryString = "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\r\n" +
"SELECT ?name WHERE {\r\n" +
" ?person a foaf:Person .\r\n" +
" ?person foaf:name ?name .\r\n" +
"}";
TupleQuery query = qm.prepareTupleQuery(queryString);
query.setBinding("person", vf.createIRI("http://namespace1.org/", "Person_1"));
try (TupleQueryResult actual = query.evaluate();
TupleQueryResult expected = tupleQueryResultBuilder(List.of("name"))
.add(List.of(vf.createLiteral("Person1")))
.build()) {
compareTupleQueryResults(actual, expected, false);
}
}
@Test
public void testQueryWithLimit() throws Exception {
final QueryManager qm = federationContext().getQueryManager();
prepareTest(Arrays.asList("/tests/medium/data1.ttl", "/tests/medium/data2.ttl", "/tests/medium/data3.ttl",
"/tests/medium/data4.ttl"));
String queryString = readQueryString("/tests/basic/query_limit01.rq");
evaluateQueryPlan("/tests/basic/query_limit01.rq", "/tests/basic/query_limit01.qp");
TupleQuery query = qm.prepareTupleQuery(queryString);
try (TupleQueryResult actual = query.evaluate()) {
if (actual.hasNext()) {
@SuppressWarnings("unused")
BindingSet firstResult = actual.next();
}
if (actual.hasNext()) {
throw new Exception("Expected single result due to LIMIT 1");
}
}
}
@Test
public void testBeginTransaction() throws Exception {
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
Assertions.assertEquals(
1, Repositories
.tupleQueryNoTransaction(fedxRule.repository, "SELECT ?person WHERE { ?person ?p 'Alan' }",
it -> QueryResults.asList(it))
.size());
Assertions.assertEquals(1,
Repositories.tupleQuery(fedxRule.repository, "SELECT ?person WHERE { ?person ?p 'Alan' }",
it -> QueryResults.asList(it)).size());
}
@Test
public void testSingleSource_SetBinding() throws Exception {
/* test a single source select query where we set a binding */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
tq.setBinding("name", l("Alan"));
TupleQueryResult tqr = tq.evaluate();
List<BindingSet> res = Iterations.asList(tqr);
assertContainsAll(res, "person", Sets.newHashSet(iri("http://example.org/", "a")));
// CONSTRUCT query
GraphQuery gq = conn.prepareGraphQuery(
"CONSTRUCT { ?person <http://xmlns.com/foaf/0.1/name> ?name } WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
gq.setBinding("name", l("Alan"));
GraphQueryResult gqr = gq.evaluate();
List<Statement> stmts = Iterations.asList(gqr);
Assertions.assertEquals(1, stmts.size());
Assertions.assertEquals(iri("http://example.org/", "a"), stmts.get(0).getSubject());
// BOOLEAN query
BooleanQuery bq = conn.prepareBooleanQuery("ASK { ?person <http://xmlns.com/foaf/0.1/name> ?name }");
bq.setBinding("name", l("non-existing-name"));
Assertions.assertEquals(false, bq.evaluate());
}
}
@Test
public void testPassThroughHandler_MultiSourceQuery() throws Exception {
/* test query with custom RDF handler */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query
TupleQuery tq = conn
.prepareTupleQuery(
"SELECT ?person ?interest WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name ; <http://xmlns.com/foaf/0.1/interest> ?interest }");
tq.setBinding("name", l("Alan"));
AtomicBoolean started = new AtomicBoolean(false);
AtomicInteger numberOfResults = new AtomicInteger(0);
tq.evaluate(new AbstractTupleQueryResultHandler() {
@Override
public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
if (started.get()) {
throw new IllegalStateException("Must not start query result twice.");
}
started.set(true);
/*
* Expected trace looks like this java.lang.Exception at
* org.eclipse.rdf4j.federated.BasicTests$1.startQueryResult(BasicTests.java:276) at
* org.eclipse.rdf4j.query.QueryResults.report(QueryResults.java:263) at
* org.eclipse.rdf4j.federated.structures.FedXTupleQuery.evaluate(FedXTupleQuery.java:69)
*/
Assertions.assertEquals(QueryResults.class.getName(),
new Exception().getStackTrace()[1].getClassName());
}
@Override
public void handleSolution(BindingSet bs) throws TupleQueryResultHandlerException {
Assertions.assertEquals(bs.getValue("person"), iri("http://example.org/", "a"));
Assertions.assertEquals(bs.getValue("interest").stringValue(), "SPARQL 1.1 Basic Federated Query");
numberOfResults.incrementAndGet();
}
});
Assertions.assertTrue(started.get());
Assertions.assertEquals(1, numberOfResults.get());
}
}
@Test
public void testPassThroughHandler_SingleSourceQuery() throws Exception {
/* test query with custom RDF handler */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name . }");
tq.setBinding("name", l("Alan"));
AtomicBoolean started = new AtomicBoolean(false);
AtomicInteger numberOfResults = new AtomicInteger(0);
tq.evaluate(new AbstractTupleQueryResultHandler() {
@Override
public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
if (started.get()) {
throw new IllegalStateException("Must not start query result twice.");
}
started.set(true);
/*
* Expected trace is expected to come from some original repository (e.g. SPARQL) => we explicitly
* do not expect QueryResults#report to be the second element (compare test
* testPassThroughHandler_MultiSourceQuery)
*/
Assertions.assertNotEquals(QueryResults.class, new Exception().getStackTrace()[1].getClass());
}
@Override
public void handleSolution(BindingSet bs) throws TupleQueryResultHandlerException {
Assertions.assertEquals(bs.getValue("person"), iri("http://example.org/", "a"));
numberOfResults.incrementAndGet();
}
});
Assertions.assertTrue(started.get());
Assertions.assertEquals(1, numberOfResults.get());
}
}
@Test
public void testPassThroughHandler_EmptyResult() throws Exception {
/* test query with custom RDF handler */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query
TupleQuery tq = conn
.prepareTupleQuery(
"SELECT ?person ?interest WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name ; <http://xmlns.com/foaf/0.1/interest> ?interest }");
tq.setBinding("name", l("NotExist"));
AtomicBoolean started = new AtomicBoolean(false);
tq.evaluate(new AbstractTupleQueryResultHandler() {
@Override
public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
if (started.get()) {
throw new IllegalStateException("Must not start query result twice.");
}
started.set(true);
Assertions.assertEquals(Lists.newArrayList("person", "interest"), bindingNames);
}
@Override
public void handleSolution(BindingSet bs) throws TupleQueryResultHandlerException {
throw new IllegalStateException("Expected empty result");
}
});
Assertions.assertTrue(started.get());
}
}
@Test
public void testPassThroughHandler_emptySingleSourceQuery() throws Exception {
/* test query with custom RDF handler */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query
TupleQuery tq = conn
.prepareTupleQuery("SELECT ?person WHERE { ?person <http://xmlns.com/foaf/0.1/name> ?name . }");
tq.setBinding("name", l("notExist"));
AtomicBoolean started = new AtomicBoolean(false);
AtomicInteger numberOfResults = new AtomicInteger(0);
tq.evaluate(new AbstractTupleQueryResultHandler() {
@Override
public void startQueryResult(List<String> bindingNames) throws TupleQueryResultHandlerException {
if (started.get()) {
throw new IllegalStateException("Must not start query result twice.");
}
started.set(true);
/*
* Expected trace is expected to come from some original repository (e.g. SPARQL) => we explicitly
* do not expect QueryResults#report to be the second element (compare test
* testPassThroughHandler_MultiSourceQuery)
*/
Assertions.assertNotEquals(QueryResults.class, new Exception().getStackTrace()[1].getClass());
}
@Override
public void handleSolution(BindingSet bs) throws TupleQueryResultHandlerException {
throw new IllegalStateException("Expected empty result");
}
});
Assertions.assertTrue(started.get());
Assertions.assertEquals(0, numberOfResults.get());
}
}
@Test
public void testDescribe_SingleResource() throws Exception {
/* test DESCRIBE query for a single resource (data in two members) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_describe1.rq", "/tests/basic/query_describe1.ttl", false, true);
}
@Test
public void testDescribe_MultipleResources() throws Exception {
/* test DESCRIBE query for multiple resources (data in two members) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
execute("/tests/basic/query_describe2.rq", "/tests/basic/query_describe2.ttl", false, true);
}
@Test
public void testDescribe_SingleSource() throws Exception {
/* test DESCRIBE query for a single resource (one federation member to simulate single source) */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl"));
execute("/tests/basic/query_describe1.rq", "/tests/basic/query_describe1_singleSource.ttl", false, true);
}
@Test
public void test_EscapingQuotedLiteral() throws Exception {
IRI publication = Values.iri("http://example.org/mypublication");
Literal quotedTitle = Values.literal("'A publication with quoted (') title'");
/* add two members */
prepareTest(Arrays.asList("/tests/basic/data01endpoint1.ttl", "/tests/basic/data01endpoint2.ttl"));
// add some additional quoted literal
try (RepositoryConnection conn1 = getRepository(1).getConnection()) {
conn1.add(publication, DCTERMS.TITLE, quotedTitle);
}
// add data to second endpoint to do a join with the literal
try (RepositoryConnection conn2 = getRepository(2).getConnection()) {
conn2.add(publication, RDFS.COMMENT, quotedTitle);
}
try (RepositoryConnection conn = fedxRule.getRepository().getConnection()) {
// SELECT query (with an artificial join on ?title to simulate the escaping issue
TupleQuery tq = conn
.prepareTupleQuery(
"SELECT * WHERE { ?publication <http://purl.org/dc/terms/title> ?title ; rdfs:comment ?title }");
try (TupleQueryResult tqr = tq.evaluate()) {
while (tqr.hasNext()) {
BindingSet bs = tqr.next();
Assertions.assertEquals(publication, bs.getValue("publication"));
Assertions.assertEquals(quotedTitle, bs.getValue("title"));
Assertions.assertFalse(tqr.hasNext(), "Result is expected to have a single result");
}
}
}
}
@Test
public void test_reduceFederation() throws Exception {
List<Endpoint> endpoints = prepareTest(
Arrays.asList("/tests/basic/data_emptyStore.ttl", "/tests/basic/data_emptyStore.ttl"));
Repository repo1 = getRepository(1);
Repository repo2 = getRepository(2);
String repo1Id = endpoints.get(0).getId();
IRI graph1 = Values.iri("http://example.org/graph1");
IRI graph2 = Values.iri("http://example.org/graph2");
try (RepositoryConnection con = repo1.getConnection()) {
con.add(Values.iri("http://example.org/repo1/p1"), RDF.TYPE, FOAF.PERSON, graph1);
con.add(Values.iri("http://example.org/repo2/p2"), RDF.TYPE, FOAF.PERSON, graph2);
}
try (RepositoryConnection con = repo2.getConnection()) {
con.add(Values.iri("http://example.org/repo2/p3"), RDF.TYPE, FOAF.PERSON, graph1);
}
Repository fedxRepo = fedxRule.getRepository();
// 1: regular federation
try (RepositoryConnection con = fedxRepo.getConnection()) {
TupleQuery tupleQuery = con.prepareTupleQuery(
"PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
+ "SELECT * WHERE { "
+ " ?subClass a foaf:Person. "
+ " } "
);
// expect from both repos
Assertions.assertEquals(3, QueryResults.asSet(tupleQuery.evaluate()).size());
// now we scope it additional to graph1
tupleQuery = con.prepareTupleQuery(
"PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
+ "SELECT * FROM <http://example.org/graph1> WHERE { "
+ " ?subClass a foaf:Person. "
+ " } ");
// expect results defined in graph1 (1 in repo1, 2 from repo2)
Assertions.assertEquals(2, QueryResults.asSet(tupleQuery.evaluate()).size());
}
// 2: reduce to federation member 1 id
// 2a: additionall restrict to named graph
FedXDataset fedXDataset = new FedXDataset(new SimpleDataset());
fedXDataset.addEndpoint(repo1Id);
try (RepositoryConnection con = fedxRepo.getConnection()) {
TupleQuery tupleQuery = con.prepareTupleQuery(
"PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
+ "SELECT * WHERE { "
+ " ?subClass a foaf:Person. "
+ " } "
);
tupleQuery.setDataset(fedXDataset);
// expect result from repo 1
Assertions.assertEquals(2, QueryResults.asSet(tupleQuery.evaluate()).size());
// now we scope it additional to graph1
tupleQuery = con.prepareTupleQuery(
"PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
+ "SELECT * FROM <http://example.org/graph1> WHERE { "
+ " ?subClass a foaf:Person. "
+ " } ");
tupleQuery.setDataset(fedXDataset);
// expect result from graph1 from repo1
Assertions.assertEquals(1, QueryResults.asSet(tupleQuery.evaluate()).size());
}
}
}