| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.rya.rdftriplestore.inference; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.rya.accumulo.AccumuloRdfConfiguration; |
| import org.junit.Test; |
| import org.openrdf.model.Resource; |
| import org.openrdf.model.URI; |
| import org.openrdf.model.ValueFactory; |
| import org.openrdf.model.impl.ValueFactoryImpl; |
| import org.openrdf.model.vocabulary.RDF; |
| import org.openrdf.query.algebra.Join; |
| import org.openrdf.query.algebra.Projection; |
| import org.openrdf.query.algebra.ProjectionElem; |
| import org.openrdf.query.algebra.ProjectionElemList; |
| import org.openrdf.query.algebra.StatementPattern; |
| import org.openrdf.query.algebra.Union; |
| import org.openrdf.query.algebra.Var; |
| |
| import com.google.common.collect.Sets; |
| |
| /** |
| * Tests the methods of {@link IntersectionOfVisitor}. |
| */ |
| public class IntersectionOfVisitorTest { |
| private final AccumuloRdfConfiguration conf = new AccumuloRdfConfiguration(); |
| private static final ValueFactory VF = new ValueFactoryImpl(); |
| |
| private static final URI MOTHER = VF.createURI("urn:Mother"); |
| private static final URI FATHER = VF.createURI("urn:Father"); |
| |
| // Definition #1: :Mother owl:intersectionOf(:Animal, :Female, :Parent) |
| private static final URI ANIMAL = VF.createURI("urn:Animal"); |
| private static final URI FEMALE = VF.createURI("urn:Female"); |
| private static final URI PARENT = VF.createURI("urn:Parent"); |
| |
| // Definition #2: :Mother owl:intersectionOf(:Female, :Leader, :Nun) |
| private static final URI NUN = VF.createURI("urn:Nun"); |
| private static final URI LEADER = VF.createURI("urn:Leader"); |
| |
| // Definition #3: :Father owl:intersectionOf(:Man, :Parent) |
| private static final URI MAN = VF.createURI("urn:Man"); |
| |
| @Test |
| public void testIntersectionOf() throws Exception { |
| // Configure a mock instance engine with an ontology: |
| final InferenceEngine inferenceEngine = mock(InferenceEngine.class); |
| final Map<Resource, List<Set<Resource>>> intersections = new HashMap<>(); |
| final List<Set<Resource>> motherIntersections = Arrays.asList( |
| Sets.newHashSet(ANIMAL, FEMALE, PARENT), |
| Sets.newHashSet(FEMALE, LEADER, NUN) |
| ); |
| final List<Set<Resource>> fatherIntersections = Arrays.asList( |
| Sets.newHashSet(MAN, PARENT) |
| ); |
| intersections.put(MOTHER, motherIntersections); |
| when(inferenceEngine.getIntersectionsImplying(MOTHER)).thenReturn(motherIntersections); |
| when(inferenceEngine.getIntersectionsImplying(FATHER)).thenReturn(fatherIntersections); |
| // Query for a specific type and rewrite using the visitor: |
| final Projection query = new Projection( |
| new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", MOTHER)), |
| new ProjectionElemList(new ProjectionElem("s", "subject"))); |
| query.visit(new IntersectionOfVisitor(conf, inferenceEngine)); |
| // Expected structure: a union whose members are the original |
| // statement pattern and a nested union of statement patterns and joins. |
| // This will join both intersections of Mother together. The nested |
| // union tree is unioned with the original statement pattern. |
| // The nested union of Mother should be: |
| // Union( |
| // Join( |
| // SP(Animal), |
| // Join( |
| // SP(Female), |
| // SP(Parent) |
| // ) |
| // ), |
| // Join( |
| // SP(Female), |
| // Join( |
| // SP(Leader), |
| // SP(Nun) |
| // ) |
| // ) |
| // ) |
| // |
| // Collect the arguments to the union: |
| assertTrue(query.getArg() instanceof Union); |
| final Union union1 = (Union) query.getArg(); |
| assertTrue(union1.getLeftArg() instanceof Union); |
| final Union union2 = (Union) union1.getLeftArg(); |
| |
| assertTrue(union2.getLeftArg() instanceof Join); |
| final Join join1 = (Join) union2.getLeftArg(); |
| assertTrue(join1.getLeftArg() instanceof StatementPattern); |
| final StatementPattern animalSp = (StatementPattern) join1.getLeftArg(); |
| assertStatementPattern(animalSp, ANIMAL); |
| assertTrue(join1.getRightArg() instanceof Join); |
| final Join join2 = (Join) join1.getRightArg(); |
| assertTrue(join2.getLeftArg() instanceof StatementPattern); |
| final StatementPattern femaleSp = (StatementPattern) join2.getLeftArg(); |
| assertStatementPattern(femaleSp, FEMALE); |
| assertTrue(join2.getRightArg() instanceof StatementPattern); |
| final StatementPattern parentSp = (StatementPattern) join2.getRightArg(); |
| assertStatementPattern(parentSp, PARENT); |
| |
| assertTrue(union2.getRightArg() instanceof Join); |
| final Join join3 = (Join) union2.getRightArg(); |
| assertTrue(join3.getLeftArg() instanceof StatementPattern); |
| final StatementPattern femaleSp2 = (StatementPattern) join3.getLeftArg(); |
| assertStatementPattern(femaleSp2, FEMALE); |
| assertTrue(join3.getRightArg() instanceof Join); |
| final Join join4 = (Join) join3.getRightArg(); |
| assertTrue(join4.getLeftArg() instanceof StatementPattern); |
| final StatementPattern leaderSp = (StatementPattern) join4.getLeftArg(); |
| assertStatementPattern(leaderSp, LEADER); |
| assertTrue(join4.getRightArg() instanceof StatementPattern); |
| final StatementPattern nunSp = (StatementPattern) join4.getRightArg(); |
| assertStatementPattern(nunSp, NUN); |
| |
| assertTrue(union1.getRightArg() instanceof StatementPattern); |
| final StatementPattern actualMotherSp = (StatementPattern) union1.getRightArg(); |
| final StatementPattern expectedMotherSp = new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", MOTHER)); |
| assertEquals(expectedMotherSp, actualMotherSp); |
| |
| |
| // Query for a specific type and rewrite using the visitor: |
| final Projection query2 = new Projection( |
| new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", FATHER)), |
| new ProjectionElemList(new ProjectionElem("s", "subject"))); |
| query2.visit(new IntersectionOfVisitor(conf, inferenceEngine)); |
| // Since Father produces only one intersection it creates a nested join |
| // that gets union with the original statement pattern. |
| // The nested join of Father should be: |
| // Join( |
| // SP(Man), |
| // SP(Parent) |
| // ) |
| // Collect the arguments to the union: |
| assertTrue(query2.getArg() instanceof Union); |
| final Union union3 = (Union) query2.getArg(); |
| assertTrue(union3.getLeftArg() instanceof Join); |
| final Join join5 = (Join) union3.getLeftArg(); |
| assertTrue(join5.getLeftArg() instanceof StatementPattern); |
| final StatementPattern manSp = (StatementPattern) join5.getLeftArg(); |
| assertStatementPattern(manSp, MAN); |
| assertTrue(join5.getRightArg() instanceof StatementPattern); |
| final StatementPattern parentSp2 = (StatementPattern) join5.getRightArg(); |
| assertStatementPattern(parentSp2, PARENT); |
| |
| assertTrue(union3.getRightArg() instanceof StatementPattern); |
| final StatementPattern actualFatherSp = (StatementPattern) union3.getRightArg(); |
| final StatementPattern expectedFatherSp = new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", FATHER)); |
| assertEquals(expectedFatherSp, actualFatherSp); |
| } |
| |
| @Test |
| public void testIntersectionOfDisabled() throws Exception { |
| // Configure a mock instance engine with an ontology: |
| final InferenceEngine inferenceEngine = mock(InferenceEngine.class); |
| final Map<Resource, List<Set<Resource>>> intersections = new HashMap<>(); |
| final List<Set<Resource>> motherIntersections = Arrays.asList( |
| Sets.newHashSet(ANIMAL, FEMALE, PARENT), |
| Sets.newHashSet(FEMALE, LEADER, NUN) |
| ); |
| final List<Set<Resource>> fatherIntersections = Arrays.asList( |
| Sets.newHashSet(MAN, PARENT) |
| ); |
| intersections.put(MOTHER, motherIntersections); |
| when(inferenceEngine.getIntersectionsImplying(MOTHER)).thenReturn(motherIntersections); |
| when(inferenceEngine.getIntersectionsImplying(FATHER)).thenReturn(fatherIntersections); |
| // Query for a specific type and rewrite using the visitor: |
| final Projection query = new Projection( |
| new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", MOTHER)), |
| new ProjectionElemList(new ProjectionElem("s", "subject"))); |
| |
| final AccumuloRdfConfiguration disabledConf = conf.clone(); |
| disabledConf.setInferIntersectionOf(false); |
| |
| query.visit(new IntersectionOfVisitor(disabledConf, inferenceEngine)); |
| |
| // Expected structure: the original statement: |
| assertTrue(query.getArg() instanceof StatementPattern); |
| final StatementPattern actualMotherSp = (StatementPattern) query.getArg(); |
| final StatementPattern expectedMotherSp = new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", MOTHER)); |
| assertEquals(expectedMotherSp, actualMotherSp); |
| |
| |
| // Query for a specific type and rewrite using the visitor: |
| final Projection query2 = new Projection( |
| new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", FATHER)), |
| new ProjectionElemList(new ProjectionElem("s", "subject"))); |
| query2.visit(new IntersectionOfVisitor(disabledConf, inferenceEngine)); |
| |
| // Expected structure: the original statement: |
| assertTrue(query2.getArg() instanceof StatementPattern); |
| final StatementPattern actualFatherSp = (StatementPattern) query2.getArg(); |
| final StatementPattern expectedFatherSp = new StatementPattern(new Var("s"), new Var("p", RDF.TYPE), new Var("o", FATHER)); |
| assertEquals(expectedFatherSp, actualFatherSp); |
| } |
| |
| private static void assertStatementPattern(final StatementPattern statementPattern, final URI uri) { |
| assertNotNull(statementPattern.getPredicateVar()); |
| assertEquals(RDF.TYPE, statementPattern.getPredicateVar().getValue()); |
| assertNotNull(statementPattern.getObjectVar()); |
| assertEquals(uri, statementPattern.getObjectVar().getValue()); |
| } |
| } |