/******************************************************************************* * 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. *******************************************************************************/ package org.eclipse.rdf4j.federated; import java.util.Arrays; import java.util.List; import org.eclipse.rdf4j.common.iteration.Iterations; import org.eclipse.rdf4j.model.vocabulary.FOAF; import org.eclipse.rdf4j.model.vocabulary.OWL; import org.eclipse.rdf4j.model.vocabulary.RDFS; import org.eclipse.rdf4j.model.vocabulary.SKOS; import org.eclipse.rdf4j.query.BindingSet; import org.eclipse.rdf4j.query.TupleQueryResult; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.google.common.collect.Sets; public class PropertyPathTests extends SPARQLBaseTest { @BeforeEach public void before() { QueryManager qm = federationContext().getQueryManager(); qm.addPrefixDeclaration("owl", OWL.NAMESPACE); qm.addPrefixDeclaration("rdfs", RDFS.NAMESPACE); qm.addPrefixDeclaration("skos", SKOS.NAMESPACE); qm.addPrefixDeclaration("foaf", FOAF.NAMESPACE); qm.addPrefixDeclaration("", EXAMPLE_NAMESPACE); } @Test public void testArbitratyLengthPath() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { ?subClass rdfs:subClassOf+ :MyClass . ?subClass rdfs:label ?label }"; try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "subClass", Sets.newHashSet(iri("MySubClass1"), iri("MySubClass2"), iri("MySubSubClass1"))); } } @Test public void testPropertyPath() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { ?subClass rdfs:subClassOf/rdfs:label ?label }"; try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "subClass", Sets.newHashSet(iri("MySubClass1"), iri("MySubClass2"), iri("MySubSubClass1"), FOAF.PERSON)); } } @Test public void testPropertyPath_Alternatives() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { ?concept a :MyClass . ?concept rdfs:label|skos:altLabel ?label }"; try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "label", Sets.newHashSet(l("Concept1"), l("Concept1 AltLabel"), l("Concept2"), l("Concept2 AltLabel"), l("Concept3"), l("Concept3 AltLabel"))); } } @Test public void testPropertyPath_ExclusiveGroup() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { ?concept a skos:Concept . ?concept skos:broader+ :mammals . ?concept rdfs:label ?label}"; String actualQueryPlan = federationContext().getQueryManager().getQueryPlan(query); assertQueryPlanEquals(readResourceAsString("/tests/propertypath/query_path_exclusiveGroup.qp"), actualQueryPlan); try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "label", Sets.newHashSet(l("Bovinae"), l("Cows"))); assertContainsAll(res, "concept", Sets.newHashSet(iri("bovinae"), iri("cows"))); } } @Test public void testPropertyPath_ExclusivePath() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { ?x rdf:type/rdfs:subClassOf* foaf:Agent . ?x rdfs:label ?label}"; String actualQueryPlan = federationContext().getQueryManager().getQueryPlan(query); // Note: we currently cannot compare the query plan, because the queryplan contains generated // variable name identifiers for anonymous nodes. // assertQueryPlanEquals(readResourceAsString("/tests/propertypath/query_path_exclusivePath.qp"), // actualQueryPlan); Assertions.assertTrue(actualQueryPlan.contains("ExclusiveArbitraryLengthPath")); try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "label", Sets.newHashSet(l("Person 1"), l("Person 2"))); } } @Test public void testPropertyPath_BoundInJoin() throws Exception { prepareTest(Arrays.asList("/tests/propertypath/data1.ttl", "/tests/propertypath/data2.ttl")); String query = "SELECT * WHERE { BIND(foaf:Person AS ?subClass) . ?subClass rdfs:subClassOf+ foaf:Agent . ?subClass rdfs:label ?label }"; try (TupleQueryResult tqr = federationContext().getQueryManager().prepareTupleQuery(query).evaluate()) { List<BindingSet> res = Iterations.asList(tqr); assertContainsAll(res, "subClass", Sets.newHashSet(FOAF.PERSON)); assertContainsAll(res, "label", Sets.newHashSet(l("Person"))); } } }