You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by ca...@apache.org on 2017/08/23 15:47:06 UTC

[1/3] incubator-rya git commit: RYA-292 Added owl:intersectionOf inference. Closes #206.

Repository: incubator-rya
Updated Branches:
  refs/heads/master 1efa10093 -> e9488ff69


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/PropertyChainVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/PropertyChainVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/PropertyChainVisitor.java
index 67d4365..a966a46 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/PropertyChainVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/PropertyChainVisitor.java
@@ -1,19 +1,3 @@
-package org.apache.rya.rdftriplestore.inference;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-import org.openrdf.model.URI;
-import org.openrdf.model.vocabulary.RDF;
-import org.openrdf.model.vocabulary.RDFS;
-import org.openrdf.model.vocabulary.SESAME;
-import org.openrdf.query.algebra.Join;
-import org.openrdf.query.algebra.QueryModelNode;
-import org.openrdf.query.algebra.StatementPattern;
-import org.openrdf.query.algebra.TupleExpr;
-import org.openrdf.query.algebra.Var;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -22,9 +6,9 @@ import org.openrdf.query.algebra.Var;
  * 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
@@ -32,13 +16,21 @@ import org.openrdf.query.algebra.Var;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.rdftriplestore.inference;
 
-
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
 
 import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.api.utils.NullableStatementImpl;
-import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
-import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
+import org.openrdf.model.URI;
+import org.openrdf.model.vocabulary.RDF;
+import org.openrdf.model.vocabulary.RDFS;
+import org.openrdf.model.vocabulary.SESAME;
+import org.openrdf.query.algebra.Join;
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.Var;
 
 /**
  * All predicates are changed
@@ -48,19 +40,19 @@ import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
  */
 public class PropertyChainVisitor extends AbstractInferVisitor {
 
-    public PropertyChainVisitor(RdfCloudTripleStoreConfiguration conf, InferenceEngine inferenceEngine) {
+    public PropertyChainVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
         super(conf, inferenceEngine);
         include = true;
     }
 
 
     @Override
-    protected void meetSP(StatementPattern node) throws Exception {
-        StatementPattern sp = node.clone();
+    protected void meetSP(final StatementPattern node) throws Exception {
+        final StatementPattern sp = node.clone();
         final Var predVar = sp.getPredicateVar();
 
-        URI pred = (URI) predVar.getValue();
-        String predNamespace = pred.getNamespace();
+        final URI pred = (URI) predVar.getValue();
+        final String predNamespace = pred.getNamespace();
 
         final Var objVar = sp.getObjectVar();
         final Var cntxtVar = sp.getContextVar();
@@ -69,45 +61,45 @@ public class PropertyChainVisitor extends AbstractInferVisitor {
                 !SESAME.NAMESPACE.equals(predNamespace) &&
                 !RDFS.NAMESPACE.equals(predNamespace)
                 && !EXPANDED.equals(cntxtVar)) {
- 
-            URI chainPropURI = (URI) predVar.getValue();
-            List<URI> chain = inferenceEngine.getPropertyChain(chainPropURI);
-            List<StatementPattern> expandedPatterns = new ArrayList<StatementPattern>();
+
+            final URI chainPropURI = (URI) predVar.getValue();
+            final List<URI> chain = inferenceEngine.getPropertyChain(chainPropURI);
+            final List<StatementPattern> expandedPatterns = new ArrayList<StatementPattern>();
             if (chain.size() > 0) {
-            	Var originalSubj = sp.getSubjectVar();
-            	Var originalObj = sp.getObjectVar();
-            	
-            	Var nextSubj = originalSubj;
-            	StatementPattern lastStatementPatternAdded = null;
-            	for (URI chainElement : chain ){
-            		String s = UUID.randomUUID().toString();
-                    Var currentObj = new Var("c-" + s);
+                final Var originalSubj = sp.getSubjectVar();
+                final Var originalObj = sp.getObjectVar();
+
+                Var nextSubj = originalSubj;
+                StatementPattern lastStatementPatternAdded = null;
+                for (final URI chainElement : chain ){
+                    final String s = UUID.randomUUID().toString();
+                    final Var currentObj = new Var("c-" + s);
                     StatementPattern statementPattern = new StatementPattern(nextSubj, new Var(chainElement.stringValue()), currentObj, sp.getContextVar());
                     if (chainElement instanceof InverseURI){
-                    	statementPattern = new StatementPattern(currentObj, new Var(chainElement.stringValue()), nextSubj, sp.getContextVar());
+                        statementPattern = new StatementPattern(currentObj, new Var(chainElement.stringValue()), nextSubj, sp.getContextVar());
                     }
-            		expandedPatterns.add(statementPattern);
-            		lastStatementPatternAdded = statementPattern;
+                    expandedPatterns.add(statementPattern);
+                    lastStatementPatternAdded = statementPattern;
                     nextSubj = currentObj;
-           		
-            	}
-            	lastStatementPatternAdded.setObjectVar(originalObj);
-            	
-            	TupleExpr lastRight = null;
-            	// replace the statement pattern with a series of joins
-            	for (StatementPattern pattern : expandedPatterns){
-            		if (lastRight == null){
-            			lastRight = pattern;
-            		}
-            		else {
-            			Join newJoin = new Join(pattern, lastRight);
-            			lastRight = newJoin;
-            		}
-            	}
-            	if (lastRight != null){
-                	node.replaceWith(lastRight);  	
-            	}
-            	
+
+                }
+                lastStatementPatternAdded.setObjectVar(originalObj);
+
+                TupleExpr lastRight = null;
+                // replace the statement pattern with a series of joins
+                for (final StatementPattern pattern : expandedPatterns){
+                    if (lastRight == null){
+                        lastRight = pattern;
+                    }
+                    else {
+                        final Join newJoin = new Join(pattern, lastRight);
+                        lastRight = newJoin;
+                    }
+                }
+                if (lastRight != null){
+                    node.replaceWith(lastRight);
+                }
+
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
index 7fb1b4a..1f2fd27 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
@@ -6,9 +6,9 @@
  * 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
@@ -18,19 +18,18 @@
  */
 package org.apache.rya.rdftriplestore.inference;
 
+import java.util.Collection;
+import java.util.UUID;
+
 import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
 import org.apache.rya.api.utils.NullableStatementImpl;
 import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
-import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
 import org.openrdf.model.URI;
 import org.openrdf.model.vocabulary.RDF;
 import org.openrdf.model.vocabulary.RDFS;
 import org.openrdf.query.algebra.StatementPattern;
 import org.openrdf.query.algebra.Var;
 
-import java.util.Collection;
-import java.util.UUID;
-
 /**
  * Class SubClassOfVisitor
  * Date: Mar 29, 2011
@@ -38,14 +37,14 @@ import java.util.UUID;
  */
 public class SubClassOfVisitor extends AbstractInferVisitor {
 
-    public SubClassOfVisitor(RdfCloudTripleStoreConfiguration conf, InferenceEngine inferenceEngine) {
+    public SubClassOfVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
         super(conf, inferenceEngine);
         include = conf.isInferSubClassOf();
     }
 
     @Override
-    protected void meetSP(StatementPattern node) throws Exception {
-        StatementPattern sp = node.clone();
+    protected void meetSP(final StatementPattern node) throws Exception {
+        final StatementPattern sp = node.clone();
         final Var predVar = sp.getPredicateVar();
         final Var objVar = sp.getObjectVar();
         final Var conVar = sp.getContextVar();
@@ -62,19 +61,19 @@ public class SubClassOfVisitor extends AbstractInferVisitor {
 //            join.getProperties().put(InferConstants.INFERRED, InferConstants.TRUE);
 //            node.replaceWith(join);
 
-            URI subclassof_uri = (URI) objVar.getValue();
-            Collection<URI> parents = inferenceEngine.findParents(inferenceEngine.getSubClassOfGraph(), subclassof_uri);
+            final URI subclassof_uri = (URI) objVar.getValue();
+            final Collection<URI> parents = InferenceEngine.findParents(inferenceEngine.getSubClassOfGraph(), subclassof_uri);
             if (parents != null && parents.size() > 0) {
-                String s = UUID.randomUUID().toString();
-                Var typeVar = new Var(s);
-                FixedStatementPattern fsp = new FixedStatementPattern(typeVar, new Var("c-" + s, RDFS.SUBCLASSOF), objVar, conVar);
+                final String s = UUID.randomUUID().toString();
+                final Var typeVar = new Var(s);
+                final FixedStatementPattern fsp = new FixedStatementPattern(typeVar, new Var("c-" + s, RDFS.SUBCLASSOF), objVar, conVar);
                 parents.add(subclassof_uri);
-                for (URI u : parents) {
+                for (final URI u : parents) {
                     fsp.statements.add(new NullableStatementImpl(u, RDFS.SUBCLASSOF, subclassof_uri));
                 }
 
-                StatementPattern rdfType = new DoNotExpandSP(sp.getSubjectVar(), sp.getPredicateVar(), typeVar, conVar);
-                InferJoin join = new InferJoin(fsp, rdfType);
+                final StatementPattern rdfType = new DoNotExpandSP(sp.getSubjectVar(), sp.getPredicateVar(), typeVar, conVar);
+                final InferJoin join = new InferJoin(fsp, rdfType);
                 join.getProperties().put(InferConstants.INFERRED, InferConstants.TRUE);
                 node.replaceWith(join);
             }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubPropertyOfVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubPropertyOfVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubPropertyOfVisitor.java
index 9447658..f3a40ab 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubPropertyOfVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubPropertyOfVisitor.java
@@ -6,9 +6,9 @@
  * 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
@@ -18,10 +18,12 @@
  */
 package org.apache.rya.rdftriplestore.inference;
 
+import java.util.Set;
+import java.util.UUID;
+
 import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
 import org.apache.rya.api.utils.NullableStatementImpl;
 import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
-import org.apache.rya.rdftriplestore.utils.FixedStatementPattern;
 import org.openrdf.model.URI;
 import org.openrdf.model.vocabulary.RDF;
 import org.openrdf.model.vocabulary.RDFS;
@@ -29,9 +31,6 @@ import org.openrdf.model.vocabulary.SESAME;
 import org.openrdf.query.algebra.StatementPattern;
 import org.openrdf.query.algebra.Var;
 
-import java.util.Set;
-import java.util.UUID;
-
 /**
  * All predicates are changed
  * Class SubPropertyOfVisitor
@@ -40,18 +39,18 @@ import java.util.UUID;
  */
 public class SubPropertyOfVisitor extends AbstractInferVisitor {
 
-    public SubPropertyOfVisitor(RdfCloudTripleStoreConfiguration conf, InferenceEngine inferenceEngine) {
+    public SubPropertyOfVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
         super(conf, inferenceEngine);
         include = conf.isInferSubPropertyOf();
     }
 
     @Override
-    protected void meetSP(StatementPattern node) throws Exception {
-        StatementPattern sp = node.clone();
+    protected void meetSP(final StatementPattern node) throws Exception {
+        final StatementPattern sp = node.clone();
         final Var predVar = sp.getPredicateVar();
 
-        URI pred = (URI) predVar.getValue();
-        String predNamespace = pred.getNamespace();
+        final URI pred = (URI) predVar.getValue();
+        final String predNamespace = pred.getNamespace();
 
         final Var objVar = sp.getObjectVar();
         final Var cntxtVar = sp.getContextVar();
@@ -95,21 +94,21 @@ public class SubPropertyOfVisitor extends AbstractInferVisitor {
 //                node.replaceWith(new StatementPattern(subjVar, vc, objVar, node.getContextVar()));
 //            }
 
-            URI subprop_uri = (URI) predVar.getValue();
-            Set<URI> parents = inferenceEngine.findParents(inferenceEngine.getSubPropertyOfGraph(), subprop_uri);
+            final URI subprop_uri = (URI) predVar.getValue();
+            final Set<URI> parents = InferenceEngine.findParents(inferenceEngine.getSubPropertyOfGraph(), subprop_uri);
             if (parents != null && parents.size() > 0) {
-                String s = UUID.randomUUID().toString();
-                Var typeVar = new Var(s);
-                FixedStatementPattern fsp = new FixedStatementPattern(typeVar, new Var("c-" + s, RDFS.SUBPROPERTYOF), predVar, cntxtVar);
+                final String s = UUID.randomUUID().toString();
+                final Var typeVar = new Var(s);
+                final FixedStatementPattern fsp = new FixedStatementPattern(typeVar, new Var("c-" + s, RDFS.SUBPROPERTYOF), predVar, cntxtVar);
 //                fsp.statements.add(new NullableStatementImpl(subprop_uri, RDFS.SUBPROPERTYOF, subprop_uri));
                 //add self
                 parents.add(subprop_uri);
-                for (URI u : parents) {
+                for (final URI u : parents) {
                     fsp.statements.add(new NullableStatementImpl(u, RDFS.SUBPROPERTYOF, subprop_uri));
                 }
 
-                StatementPattern rdfType = new DoNotExpandSP(sp.getSubjectVar(), typeVar, sp.getObjectVar(), cntxtVar);
-                InferJoin join = new InferJoin(fsp, rdfType);
+                final StatementPattern rdfType = new DoNotExpandSP(sp.getSubjectVar(), typeVar, sp.getObjectVar(), cntxtVar);
+                final InferJoin join = new InferJoin(fsp, rdfType);
                 join.getProperties().put(InferConstants.INFERRED, InferConstants.TRUE);
                 node.replaceWith(join);
             }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/TransitivePropertyVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/TransitivePropertyVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/TransitivePropertyVisitor.java
index b50da9c..45f74ed 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/TransitivePropertyVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/TransitivePropertyVisitor.java
@@ -1,5 +1,3 @@
-package org.apache.rya.rdftriplestore.inference;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -8,9 +6,9 @@ package org.apache.rya.rdftriplestore.inference;
  * 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
@@ -18,12 +16,10 @@ package org.apache.rya.rdftriplestore.inference;
  * specific language governing permissions and limitations
  * under the License.
  */
-
-
+package org.apache.rya.rdftriplestore.inference;
 
 import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
 import org.apache.rya.rdftriplestore.utils.TransitivePropertySP;
-import org.apache.rya.rdftriplestore.utils.TransitivePropertySP;
 import org.openrdf.model.URI;
 import org.openrdf.model.vocabulary.RDF;
 import org.openrdf.model.vocabulary.RDFS;
@@ -39,18 +35,18 @@ import org.openrdf.query.algebra.Var;
  */
 public class TransitivePropertyVisitor extends AbstractInferVisitor {
 
-    public TransitivePropertyVisitor(RdfCloudTripleStoreConfiguration conf, InferenceEngine inferenceEngine) {
+    public TransitivePropertyVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
         super(conf, inferenceEngine);
         include = conf.isInferTransitiveProperty();
     }
 
     @Override
-    protected void meetSP(StatementPattern node) throws Exception {
-        StatementPattern sp = node.clone();
+    protected void meetSP(final StatementPattern node) throws Exception {
+        final StatementPattern sp = node.clone();
         final Var predVar = sp.getPredicateVar();
 
-        URI pred = (URI) predVar.getValue();
-        String predNamespace = pred.getNamespace();
+        final URI pred = (URI) predVar.getValue();
+        final String predNamespace = pred.getNamespace();
 
         final Var objVar = sp.getObjectVar();
         final Var cntxtVar = sp.getContextVar();
@@ -60,7 +56,7 @@ public class TransitivePropertyVisitor extends AbstractInferVisitor {
                 !RDFS.NAMESPACE.equals(predNamespace)
                 && !EXPANDED.equals(cntxtVar)) {
 
-            URI transPropUri = (URI) predVar.getValue();
+            final URI transPropUri = (URI) predVar.getValue();
             if (inferenceEngine.isTransitiveProperty(transPropUri)) {
                 node.replaceWith(new TransitivePropertySP(sp.getSubjectVar(), sp.getPredicateVar(), sp.getObjectVar(), sp.getContextVar()));
             }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/utils/FixedStatementPattern.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/utils/FixedStatementPattern.java b/sail/src/main/java/org/apache/rya/rdftriplestore/utils/FixedStatementPattern.java
index bfefe12..ee63213 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/utils/FixedStatementPattern.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/utils/FixedStatementPattern.java
@@ -1,5 +1,3 @@
-package org.apache.rya.rdftriplestore.utils;
-
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -8,9 +6,9 @@ package org.apache.rya.rdftriplestore.utils;
  * 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
@@ -18,16 +16,15 @@ package org.apache.rya.rdftriplestore.utils;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.rdftriplestore.utils;
 
-
+import java.util.ArrayList;
+import java.util.Collection;
 
 import org.openrdf.model.Statement;
 import org.openrdf.query.algebra.StatementPattern;
 import org.openrdf.query.algebra.Var;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
 /**
  * StatementPattern gives fixed statements back
  *
@@ -36,24 +33,24 @@ import java.util.Collection;
  * Time: 2:42:06 PM
  */
 public class FixedStatementPattern extends StatementPattern {
-    public Collection<Statement> statements = new ArrayList();
+    public Collection<Statement> statements = new ArrayList<>();
 
     public FixedStatementPattern() {
     }
 
-    public FixedStatementPattern(Var subject, Var predicate, Var object) {
+    public FixedStatementPattern(final Var subject, final Var predicate, final Var object) {
         super(subject, predicate, object);
     }
 
-    public FixedStatementPattern(Scope scope, Var subject, Var predicate, Var object) {
+    public FixedStatementPattern(final Scope scope, final Var subject, final Var predicate, final Var object) {
         super(scope, subject, predicate, object);
     }
 
-    public FixedStatementPattern(Var subject, Var predicate, Var object, Var context) {
+    public FixedStatementPattern(final Var subject, final Var predicate, final Var object, final Var context) {
         super(subject, predicate, object, context);
     }
 
-    public FixedStatementPattern(Scope scope, Var subjVar, Var predVar, Var objVar, Var conVar) {
+    public FixedStatementPattern(final Scope scope, final Var subjVar, final Var predVar, final Var objVar, final Var conVar) {
         super(scope, subjVar, predVar, objVar, conVar);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
----------------------------------------------------------------------
diff --git a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
index 556413f..10edf49 100644
--- a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
+++ b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
@@ -1,4 +1,3 @@
-package org.apache.rya.rdftriplestore.inference;
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,10 +16,12 @@ package org.apache.rya.rdftriplestore.inference;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.rdftriplestore.inference;
 
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -33,7 +34,6 @@ import org.apache.rya.rdftriplestore.RdfCloudTripleStore;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.junit.After;
 import org.junit.Assert;
-
 import org.junit.Test;
 import org.openrdf.model.Resource;
 import org.openrdf.model.URI;
@@ -44,12 +44,14 @@ import org.openrdf.query.QueryLanguage;
 import org.openrdf.repository.sail.SailRepository;
 import org.openrdf.repository.sail.SailRepositoryConnection;
 
+import com.google.common.collect.Sets;
+
 import junit.framework.TestCase;
 
 public class InferenceEngineTest extends TestCase {
     private Connector connector;
     private AccumuloRyaDAO dao;
-    private ValueFactory vf = new ValueFactoryImpl();
+    private final ValueFactory vf = new ValueFactoryImpl();
     private AccumuloRdfConfiguration conf;
     private RdfCloudTripleStore store;
     private InferenceEngine inferenceEngine;
@@ -77,6 +79,7 @@ public class InferenceEngineTest extends TestCase {
         conn = repository.getConnection();
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         conn.close();
@@ -88,7 +91,7 @@ public class InferenceEngineTest extends TestCase {
 
     @Test
     public void testSubClassGraph() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:A> rdfs:subClassOf <urn:C> . \n"
                 + "  <urn:B> rdfs:subClassOf <urn:C> . \n"
                 + "  <urn:C> rdfs:subClassOf <urn:D> . \n"
@@ -99,34 +102,33 @@ public class InferenceEngineTest extends TestCase {
                 + "}}";
         conn.prepareUpdate(QueryLanguage.SPARQL, insert).execute();
         inferenceEngine.refreshGraph();
-        Graph graph = inferenceEngine.getSubClassOfGraph();
-        URI a = vf.createURI("urn:A");
-        URI b = vf.createURI("urn:B");
-        URI c = vf.createURI("urn:C");
-        URI d = vf.createURI("urn:D");
-        URI e = vf.createURI("urn:E");
-        URI f = vf.createURI("urn:F");
-        URI g = vf.createURI("urn:G");
-        URI z = vf.createURI("urn:Z");
-        URI missing = vf.createURI("urn:Missing");
-        Set<URI> empty = new HashSet<>();
-        Set<URI> belowLevel2 = new HashSet<>(Arrays.asList(new URI[] { a, b }));
-        Set<URI> belowLevel3 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e }));
-        Set<URI> belowLevel4 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e, f, g }));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, a));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, b));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, z));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, missing));
-        Assert.assertEquals(belowLevel2, inferenceEngine.findParents(graph, c));
-        Assert.assertEquals(belowLevel3, inferenceEngine.findParents(graph, d));
-        Assert.assertEquals(belowLevel3, inferenceEngine.findParents(graph, e));
-        Assert.assertEquals(belowLevel4, inferenceEngine.findParents(graph, f));
-        Assert.assertEquals(belowLevel4, inferenceEngine.findParents(graph, g));
+        final URI a = vf.createURI("urn:A");
+        final URI b = vf.createURI("urn:B");
+        final URI c = vf.createURI("urn:C");
+        final URI d = vf.createURI("urn:D");
+        final URI e = vf.createURI("urn:E");
+        final URI f = vf.createURI("urn:F");
+        final URI g = vf.createURI("urn:G");
+        final URI z = vf.createURI("urn:Z");
+        final URI missing = vf.createURI("urn:Missing");
+        final Set<URI> empty = new HashSet<>();
+        final Set<URI> belowLevel2 = new HashSet<>(Arrays.asList(new URI[] { a, b }));
+        final Set<URI> belowLevel3 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e }));
+        final Set<URI> belowLevel4 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e, f, g }));
+        Assert.assertEquals(empty, inferenceEngine.getSubClasses(a));
+        Assert.assertEquals(empty, inferenceEngine.getSubClasses(b));
+        Assert.assertEquals(empty, inferenceEngine.getSubClasses(z));
+        Assert.assertEquals(empty, inferenceEngine.getSubClasses(missing));
+        Assert.assertEquals(belowLevel2, inferenceEngine.getSubClasses(c));
+        Assert.assertEquals(belowLevel3, inferenceEngine.getSubClasses(d));
+        Assert.assertEquals(belowLevel3, inferenceEngine.getSubClasses(e));
+        Assert.assertEquals(belowLevel4, inferenceEngine.getSubClasses(f));
+        Assert.assertEquals(belowLevel4, inferenceEngine.getSubClasses(g));
     }
 
     @Test
     public void testSubPropertyGraph() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:p> rdfs:subPropertyOf <urn:q> . \n"
                 + "  <urn:p> rdfs:subPropertyOf <urn:r> . \n"
                 + "  <urn:r> owl:equivalentProperty <urn:s> . \n"
@@ -138,35 +140,35 @@ public class InferenceEngineTest extends TestCase {
                 + "}}";
         conn.prepareUpdate(QueryLanguage.SPARQL, insert).execute();
         inferenceEngine.refreshGraph();
-        Graph graph = inferenceEngine.getSubPropertyOfGraph();
-        URI p = vf.createURI("urn:p");
-        URI q = vf.createURI("urn:q");
-        URI r = vf.createURI("urn:r");
-        URI s = vf.createURI("urn:s");
-        URI t = vf.createURI("urn:t");
-        URI u = vf.createURI("urn:u");
-        URI v = vf.createURI("urn:v");
-        URI w = vf.createURI("urn:w");
-        URI missing = vf.createURI("urn:Missing");
-        Set<URI> empty = new HashSet<>();
-        Set<URI> belowQ = new HashSet<>(Arrays.asList(new URI[] { p }));
-        Set<URI> belowR = new HashSet<>(Arrays.asList(new URI[] { p, r, s }));
-        Set<URI> belowT = new HashSet<>(Arrays.asList(new URI[] { p, q }));
-        Set<URI> belowU = new HashSet<>(Arrays.asList(new URI[] { p, q, r, s, t, u, v }));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, p));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, w));
-        Assert.assertEquals(empty, inferenceEngine.findParents(graph, missing));
-        Assert.assertEquals(belowQ, inferenceEngine.findParents(graph, q));
-        Assert.assertEquals(belowR, inferenceEngine.findParents(graph, r));
-        Assert.assertEquals(belowR, inferenceEngine.findParents(graph, s));
-        Assert.assertEquals(belowT, inferenceEngine.findParents(graph, t));
-        Assert.assertEquals(belowU, inferenceEngine.findParents(graph, u));
-        Assert.assertEquals(belowU, inferenceEngine.findParents(graph, v));
+        final Graph graph = inferenceEngine.getSubPropertyOfGraph();
+        final URI p = vf.createURI("urn:p");
+        final URI q = vf.createURI("urn:q");
+        final URI r = vf.createURI("urn:r");
+        final URI s = vf.createURI("urn:s");
+        final URI t = vf.createURI("urn:t");
+        final URI u = vf.createURI("urn:u");
+        final URI v = vf.createURI("urn:v");
+        final URI w = vf.createURI("urn:w");
+        final URI missing = vf.createURI("urn:Missing");
+        final Set<URI> empty = new HashSet<>();
+        final Set<URI> belowQ = new HashSet<>(Arrays.asList(new URI[] { p }));
+        final Set<URI> belowR = new HashSet<>(Arrays.asList(new URI[] { p, r, s }));
+        final Set<URI> belowT = new HashSet<>(Arrays.asList(new URI[] { p, q }));
+        final Set<URI> belowU = new HashSet<>(Arrays.asList(new URI[] { p, q, r, s, t, u, v }));
+        Assert.assertEquals(empty, InferenceEngine.findParents(graph, p));
+        Assert.assertEquals(empty, InferenceEngine.findParents(graph, w));
+        Assert.assertEquals(empty, InferenceEngine.findParents(graph, missing));
+        Assert.assertEquals(belowQ, InferenceEngine.findParents(graph, q));
+        Assert.assertEquals(belowR, InferenceEngine.findParents(graph, r));
+        Assert.assertEquals(belowR, InferenceEngine.findParents(graph, s));
+        Assert.assertEquals(belowT, InferenceEngine.findParents(graph, t));
+        Assert.assertEquals(belowU, InferenceEngine.findParents(graph, u));
+        Assert.assertEquals(belowU, InferenceEngine.findParents(graph, v));
     }
 
     @Test
     public void testDomainRange() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:p1> rdfs:subPropertyOf <urn:p2> . \n"
                 + "  <urn:p2> rdfs:subPropertyOf <urn:p3> . \n"
                 + "  <urn:q1> rdfs:subPropertyOf <urn:q2> . \n"
@@ -187,25 +189,25 @@ public class InferenceEngineTest extends TestCase {
                 + "}}";
         conn.prepareUpdate(QueryLanguage.SPARQL, insert).execute();
         inferenceEngine.refreshGraph();
-        Set<URI> hasDomainD1 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D1"));
-        Set<URI> hasDomainD2 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D2"));
-        Set<URI> hasDomainD3 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D3"));
-        Set<URI> hasRangeD1 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D1"));
-        Set<URI> hasRangeD2 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D2"));
-        Set<URI> hasRangeD3 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D3"));
-        Set<URI> hasDomainR1 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R1"));
-        Set<URI> hasDomainR2 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R2"));
-        Set<URI> hasDomainR3 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R3"));
-        Set<URI> hasRangeR1 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R1"));
-        Set<URI> hasRangeR2 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R2"));
-        Set<URI> hasRangeR3 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R3"));
-        Set<URI> empty = new HashSet<>();
-        Set<URI> expectedForward = new HashSet<>();
+        final Set<URI> hasDomainD1 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D1"));
+        final Set<URI> hasDomainD2 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D2"));
+        final Set<URI> hasDomainD3 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:D3"));
+        final Set<URI> hasRangeD1 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D1"));
+        final Set<URI> hasRangeD2 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D2"));
+        final Set<URI> hasRangeD3 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:D3"));
+        final Set<URI> hasDomainR1 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R1"));
+        final Set<URI> hasDomainR2 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R2"));
+        final Set<URI> hasDomainR3 = inferenceEngine.getPropertiesWithDomain(vf.createURI("urn:R3"));
+        final Set<URI> hasRangeR1 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R1"));
+        final Set<URI> hasRangeR2 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R2"));
+        final Set<URI> hasRangeR3 = inferenceEngine.getPropertiesWithRange(vf.createURI("urn:R3"));
+        final Set<URI> empty = new HashSet<>();
+        final Set<URI> expectedForward = new HashSet<>();
         expectedForward.add(vf.createURI("urn:p2"));
         expectedForward.add(vf.createURI("urn:p1"));
         expectedForward.add(vf.createURI("urn:q2"));
         expectedForward.add(vf.createURI("urn:q1"));
-        Set<URI> expectedInverse = new HashSet<>();
+        final Set<URI> expectedInverse = new HashSet<>();
         expectedInverse.add(vf.createURI("urn:i1"));
         expectedInverse.add(vf.createURI("urn:i2"));
         expectedInverse.add(vf.createURI("urn:j1"));
@@ -226,7 +228,7 @@ public class InferenceEngineTest extends TestCase {
 
     @Test
     public void testAllValuesFrom() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:Dog> owl:onProperty <urn:relative> ; owl:allValuesFrom <urn:Dog> .\n"
                 + "  <urn:Retriever> rdfs:subClassOf <urn:Dog> .\n"
                 + "  <urn:Terrier> rdfs:subClassOf <urn:Dog> .\n"
@@ -257,7 +259,7 @@ public class InferenceEngineTest extends TestCase {
 
     @Test
     public void testHasValueGivenProperty() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:Biped> owl:onProperty <urn:walksUsingLegs>  . \n"
                 + "  <urn:Biped> owl:hasValue \"2\" . \n"
                 + "  <urn:Mammal> owl:onProperty <urn:taxon> . \n"
@@ -288,7 +290,7 @@ public class InferenceEngineTest extends TestCase {
 
     @Test
     public void testHasValueGivenType() throws Exception {
-        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+        final String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:Biped> owl:onProperty <urn:walksUsingLegs>  . \n"
                 + "  <urn:Biped> owl:hasValue \"2\" . \n"
                 + "  <urn:Mammal> owl:onProperty <urn:taxon> . \n"
@@ -352,11 +354,10 @@ public class InferenceEngineTest extends TestCase {
                 + "}}";
         conn.prepareUpdate(QueryLanguage.SPARQL, ontology).execute();
         inferenceEngine.refreshGraph();
-        Graph subClassGraph = inferenceEngine.getSubClassOfGraph();
-        Set<URI> subClassesA = inferenceEngine.findParents(subClassGraph, vf.createURI("urn:A"));
-        Set<URI> subClassesB = inferenceEngine.findParents(subClassGraph, vf.createURI("urn:B"));
-        Set<URI> expectedA = new HashSet<>();
-        Set<URI> expectedB = new HashSet<>();
+        final Set<URI> subClassesA = inferenceEngine.getSubClasses(vf.createURI("urn:A"));
+        final Set<URI> subClassesB = inferenceEngine.getSubClasses(vf.createURI("urn:B"));
+        final Set<URI> expectedA = new HashSet<>();
+        final Set<URI> expectedB = new HashSet<>();
         expectedB.add(vf.createURI("urn:Y"));
         expectedB.add(vf.createURI("urn:SubY"));
         expectedB.add(vf.createURI("urn:Z"));
@@ -365,4 +366,76 @@ public class InferenceEngineTest extends TestCase {
         Assert.assertEquals(expectedA, subClassesA);
         Assert.assertEquals(expectedB, subClassesB);
     }
+
+    public void testIntersectionOf() throws Exception {
+        final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:Mother> owl:intersectionOf _:bnode1 . \n"
+                + "  _:bnode1 rdf:first <urn:Woman> . \n"
+                + "  _:bnode1 rdf:rest _:bnode2 . \n"
+                + "  _:bnode2 rdf:first <urn:Parent> . \n"
+                + "  _:bnode2 rdf:rest rdf:nil . \n"
+                + "  <urn:Father> owl:intersectionOf _:bnode3 . \n"
+                + "  _:bnode3 rdf:first <urn:Man> . \n"
+                + "  _:bnode3 rdf:rest _:bnode4 . \n"
+                + "  _:bnode4 rdf:first <urn:Parent> . \n"
+                + "  _:bnode4 rdf:rest rdf:nil . \n"
+                + "  <urn:Mom> owl:intersectionOf _:bnode5 . \n"
+                + "  _:bnode5 rdf:first <urn:Woman> . \n"
+                + "  _:bnode5 rdf:rest _:bnode6 . \n"
+                + "  _:bnode6 rdf:first <urn:Parent> . \n"
+                + "  _:bnode6 rdf:rest rdf:nil . \n"
+                + "  <urn:Mother> rdfs:subClassOf <urn:ImmediateFamilyMember> . \n"
+                + "  <urn:ImmediateFamilyMember> rdfs:subClassOf <urn:Relative> . \n"
+                + "}}";
+
+        conn.prepareUpdate(QueryLanguage.SPARQL, ontology).execute();
+        inferenceEngine.refreshGraph();
+
+        final URI mother = vf.createURI("urn:Mother");
+        final URI father = vf.createURI("urn:Father");
+        final URI woman = vf.createURI("urn:Woman");
+        final URI parent = vf.createURI("urn:Parent");
+        final URI man = vf.createURI("urn:Man");
+        final URI mom = vf.createURI("urn:Mom");
+        final URI immediateFamilyMember = vf.createURI("urn:ImmediateFamilyMember");
+        final URI relative = vf.createURI("urn:Relative");
+
+        final List<Set<Resource>> intersectionsImplyingMother = Arrays.asList(Sets.newHashSet(woman, parent));
+        Assert.assertEquals(intersectionsImplyingMother, inferenceEngine.getIntersectionsImplying(mother));
+        final List<Set<Resource>> intersectionsImplyingFather = Arrays.asList(Sets.newHashSet(man, parent));
+        Assert.assertEquals(intersectionsImplyingFather, inferenceEngine.getIntersectionsImplying(father));
+
+        // Check that Mother is a subclassOf Parent and Woman and
+        // ImmediateFamilyMember and Relative. Also, Mother is a subclassOf
+        // Mother and Mom through inferring equivalentClass.
+        final Set<URI> motherSuperClassUris = inferenceEngine.getSuperClasses(mother);
+        Assert.assertNotNull(motherSuperClassUris);
+        Assert.assertEquals(6, motherSuperClassUris.size());
+        Assert.assertTrue(motherSuperClassUris.contains(parent));
+        Assert.assertTrue(motherSuperClassUris.contains(woman));
+        Assert.assertTrue(motherSuperClassUris.contains(immediateFamilyMember));
+        Assert.assertTrue(motherSuperClassUris.contains(relative));
+        Assert.assertTrue(motherSuperClassUris.contains(mother));
+        Assert.assertTrue(motherSuperClassUris.contains(mom));
+        // Check that Father is a subclassOf Parent and Man
+        final Set<URI> fatherSuperClassUris = inferenceEngine.getSuperClasses(father);
+        Assert.assertNotNull(fatherSuperClassUris);
+        Assert.assertEquals(2, fatherSuperClassUris.size());
+        Assert.assertTrue(fatherSuperClassUris.contains(parent));
+        Assert.assertTrue(fatherSuperClassUris.contains(man));
+
+        // Check that Mom is a subclassOf Parent and Woman and
+        // ImmediateFamilyMember and Relative. The last 2 should be inferred
+        // from having the same intersection as Mother. Also, Mom is a
+        // subclassOf Mother and Mom through inferring equivalentClass.
+        final Set<URI> momSuperClassUris = inferenceEngine.getSuperClasses(mom);
+        Assert.assertNotNull(momSuperClassUris);
+        Assert.assertEquals(6, momSuperClassUris.size());
+        Assert.assertTrue(momSuperClassUris.contains(parent));
+        Assert.assertTrue(momSuperClassUris.contains(woman));
+        Assert.assertTrue(momSuperClassUris.contains(immediateFamilyMember));
+        Assert.assertTrue(momSuperClassUris.contains(relative));
+        Assert.assertTrue(momSuperClassUris.contains(mother));
+        Assert.assertTrue(momSuperClassUris.contains(mom));
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
----------------------------------------------------------------------
diff --git a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
index 7d6f7d1..dcda8a9 100644
--- a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
+++ b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
@@ -50,7 +50,7 @@ import junit.framework.TestCase;
 public class InferenceIT extends TestCase {
     private Connector connector;
     private AccumuloRyaDAO dao;
-    private ValueFactory vf = new ValueFactoryImpl();
+    private final ValueFactory vf = new ValueFactoryImpl();
     private AccumuloRdfConfiguration conf;
     private RdfCloudTripleStore store;
     private InferenceEngine inferenceEngine;
@@ -84,20 +84,23 @@ public class InferenceIT extends TestCase {
             @Override
             public void endQueryResult() throws TupleQueryResultHandlerException { }
             @Override
-            public void handleBoolean(boolean arg0) throws QueryResultHandlerException { }
+            public void handleBoolean(final boolean value) throws QueryResultHandlerException { }
             @Override
-            public void handleLinks(List<String> arg0) throws QueryResultHandlerException { }
+            public void handleLinks(final List<String> linkUrls) throws QueryResultHandlerException { }
             @Override
-            public void handleSolution(BindingSet arg0) throws TupleQueryResultHandlerException {
-                solutions.add(arg0);
+            public void handleSolution(final BindingSet bindingSet) throws TupleQueryResultHandlerException {
+                if (bindingSet != null && bindingSet.iterator().hasNext()) {
+                    solutions.add(bindingSet);
+                }
             }
             @Override
-            public void startQueryResult(List<String> arg0) throws TupleQueryResultHandlerException {
+            public void startQueryResult(final List<String> bindingNames) throws TupleQueryResultHandlerException {
                 solutions.clear();
             }
         };
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         conn.close();
@@ -131,12 +134,12 @@ public class InferenceIT extends TestCase {
         inferenceEngine.refreshGraph();
         conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
         conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
-        Set<Value> expected = new HashSet<>();
+        final Set<Value> expected = new HashSet<>();
         expected.add(vf.createURI("urn:Alice"));
         expected.add(vf.createURI("urn:Bob"));
         expected.add(vf.createURI("urn:Eve"));
-        Set<Value> returned = new HashSet<>();
-        for (BindingSet bs : solutions) {
+        final Set<Value> returned = new HashSet<>();
+        for (final BindingSet bs : solutions) {
             returned.add(bs.getBinding("x").getValue());
         }
         Assert.assertEquals(expected, returned);
@@ -174,13 +177,13 @@ public class InferenceIT extends TestCase {
         inferenceEngine.refreshGraph();
         conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
         conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
-        Set<Value> expected = new HashSet<>();
+        final Set<Value> expected = new HashSet<>();
         expected.add(vf.createURI("urn:Professor1"));
         expected.add(vf.createURI("urn:Professor2"));
         expected.add(vf.createURI("urn:Professor3"));
         expected.add(vf.createURI("urn:Professor4"));
-        Set<Value> returned = new HashSet<>();
-        for (BindingSet bs : solutions) {
+        final Set<Value> returned = new HashSet<>();
+        for (final BindingSet bs : solutions) {
             returned.add(bs.getBinding("x").getValue());
         }
         Assert.assertEquals(expected, returned);
@@ -249,14 +252,14 @@ public class InferenceIT extends TestCase {
         inferenceEngine.refreshGraph();
         conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
         conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
-        Set<Value> expected = new HashSet<>();
+        final Set<Value> expected = new HashSet<>();
         expected.add(vf.createURI("urn:Alice"));
         expected.add(vf.createURI("urn:Bob"));
         expected.add(vf.createURI("urn:Carol"));
         expected.add(vf.createURI("urn:Dan"));
         expected.add(vf.createURI("urn:Lucy"));
-        Set<Value> returned = new HashSet<>();
-        for (BindingSet bs : solutions) {
+        final Set<Value> returned = new HashSet<>();
+        for (final BindingSet bs : solutions) {
             returned.add(bs.getBinding("x").getValue());
         }
         Assert.assertEquals(expected, returned);
@@ -286,8 +289,8 @@ public class InferenceIT extends TestCase {
         conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
         inferenceEngine.refreshGraph();
         conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
-        Set<BindingSet> expected = new HashSet<BindingSet>();
-        List<String> varNames = new LinkedList<>();
+        final Set<BindingSet> expected = new HashSet<BindingSet>();
+        final List<String> varNames = new LinkedList<>();
         varNames.add("individual");
         varNames.add("taxon");
         expected.add(new ListBindingSet(varNames, vf.createURI("urn:Alice"), vf.createURI("urn:Hominidae")));
@@ -324,15 +327,77 @@ public class InferenceIT extends TestCase {
         inferenceEngine.refreshGraph();
         conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
         conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
-        Set<Value> expected = new HashSet<>();
+        final Set<Value> expected = new HashSet<>();
         expected.add(vf.createURI("urn:Bob"));
         expected.add(vf.createURI("urn:Carol"));
         expected.add(vf.createURI("urn:Eve"));
-        Set<Value> returned = new HashSet<>();
-        for (BindingSet bs : solutions) {
+        final Set<Value> returned = new HashSet<>();
+        for (final BindingSet bs : solutions) {
             returned.add(bs.getBinding("x").getValue());
         }
         Assert.assertEquals(expected, returned);
         Assert.assertEquals(expected.size(), solutions.size());
     }
+
+    public void testIntersectionOfQuery() throws Exception {
+        final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:Mother> owl:intersectionOf _:bnode1 . \n"
+                + "  _:bnode1 rdf:first <urn:Woman> . \n"
+                + "  _:bnode1 rdf:rest _:bnode2 . \n"
+                + "  _:bnode2 rdf:first <urn:Parent> . \n"
+                + "  _:bnode2 rdf:rest rdf:nil . \n"
+                + "  <urn:Father> owl:intersectionOf _:bnode3 . \n"
+                + "  _:bnode3 rdf:first <urn:Man> . \n"
+                + "  _:bnode3 rdf:rest _:bnode4 . \n"
+                + "  _:bnode4 rdf:first <urn:Parent> . \n"
+                + "  _:bnode4 rdf:rest rdf:nil . \n"
+                + "}}";
+        final String instances = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:Susan> a <urn:Mother> . \n"
+                + "  <urn:Bob> a <urn:Man> . \n"
+                + "  <urn:Bob> a <urn:Parent> . \n"
+                + "}}";
+        conn.prepareUpdate(QueryLanguage.SPARQL, ontology).execute();
+        conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
+        inferenceEngine.refreshGraph();
+
+        final List<String> varNames = new LinkedList<>();
+        varNames.add("individual");
+
+        // Find all <urn:Mother> types (expect 1 result)
+        final String motherQuery = "SELECT ?individual { GRAPH <http://updated/test> { ?individual rdf:type <urn:Mother> } } \n";
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, motherQuery).evaluate(resultHandler);
+        final Set<BindingSet> expectedMothers = new HashSet<>();
+        expectedMothers.add(new ListBindingSet(varNames, vf.createURI("urn:Susan")));
+        Assert.assertEquals(expectedMothers, new HashSet<>(solutions));
+
+        // Find all <urn:Father> types (expect 1 result)
+        final String fatherQuery = "SELECT ?individual { GRAPH <http://updated/test> { ?individual rdf:type <urn:Father> } } \n";
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, fatherQuery).evaluate(resultHandler);
+        final Set<BindingSet> expectedFathers = new HashSet<>();
+        expectedFathers.add(new ListBindingSet(varNames, vf.createURI("urn:Bob")));
+        Assert.assertEquals(expectedFathers, new HashSet<>(solutions));
+
+        // Find all <urn:Parent> types (expect 2 results)
+        final String parentQuery = "SELECT ?individual { GRAPH <http://updated/test> { ?individual rdf:type <urn:Parent> } } \n";
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, parentQuery).evaluate(resultHandler);
+        final Set<BindingSet> expectedParents = new HashSet<>();
+        expectedParents.add(new ListBindingSet(varNames, vf.createURI("urn:Bob")));
+        expectedParents.add(new ListBindingSet(varNames, vf.createURI("urn:Susan")));
+        Assert.assertEquals(expectedParents, new HashSet<>(solutions));
+
+        // Find all <urn:Woman> types (expect 1 result)
+        final String womanQuery = "SELECT ?individual { GRAPH <http://updated/test> { ?individual rdf:type <urn:Woman> } } \n";
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, womanQuery).evaluate(resultHandler);
+        final Set<BindingSet> expectedWomen = new HashSet<>();
+        expectedWomen.add(new ListBindingSet(varNames, vf.createURI("urn:Susan")));
+        Assert.assertEquals(expectedWomen, new HashSet<>(solutions));
+
+        // Find all <urn:Man> types (expect 1 result)
+        final String manQuery = "SELECT ?individual { GRAPH <http://updated/test> { ?individual rdf:type <urn:Man> } } \n";
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, manQuery).evaluate(resultHandler);
+        final Set<BindingSet> expectedMen = new HashSet<>();
+        expectedMen.add(new ListBindingSet(varNames, vf.createURI("urn:Bob")));
+        Assert.assertEquals(expectedMen, new HashSet<>(solutions));
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/test/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitorTest.java
----------------------------------------------------------------------
diff --git a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitorTest.java b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitorTest.java
new file mode 100644
index 0000000..58551a5
--- /dev/null
+++ b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitorTest.java
@@ -0,0 +1,235 @@
+/*
+ * 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());
+    }
+}
\ No newline at end of file


[3/3] incubator-rya git commit: RYA-292 Added owl:intersectionOf inference. Closes #206.

Posted by ca...@apache.org.
RYA-292 Added owl:intersectionOf inference. Closes #206.


Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/e9488ff6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/e9488ff6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/e9488ff6

Branch: refs/heads/master
Commit: e9488ff69f1a88300060c4010956403605cabd66
Parents: 1efa100
Author: eric.white <Er...@parsons.com>
Authored: Wed Aug 2 17:52:10 2017 -0400
Committer: Caleb Meier <ca...@parsons.com>
Committed: Wed Aug 23 08:45:57 2017 -0700

----------------------------------------------------------------------
 .../api/RdfCloudTripleStoreConfiguration.java   | 155 ++--
 .../api/persist/utils/RyaDaoQueryWrapper.java   | 185 ++++
 .../src/main/java/MongoRyaDirectExample.java    | 538 ++++++-----
 .../RdfCloudTripleStoreConnection.java          |  33 +-
 .../evaluation/FilterRangeVisitor.java          |  63 +-
 .../evaluation/PushJoinDownVisitor.java         |  24 +-
 .../evaluation/ReorderJoinVisitor.java          |  24 +-
 .../evaluation/SeparateFilterJoinsVisitor.java  |  31 +-
 .../inference/InferenceEngine.java              | 883 ++++++++++++-------
 .../inference/InferenceEngineException.java     |  12 +-
 .../inference/IntersectionOfVisitor.java        | 210 +++++
 .../rdftriplestore/inference/InverseURI.java    |  94 +-
 .../inference/PropertyChainVisitor.java         | 114 ++-
 .../inference/SubClassOfVisitor.java            |  33 +-
 .../inference/SubPropertyOfVisitor.java         |  37 +-
 .../inference/TransitivePropertyVisitor.java    |  22 +-
 .../utils/FixedStatementPattern.java            |  23 +-
 .../inference/InferenceEngineTest.java          | 225 +++--
 .../rdftriplestore/inference/InferenceIT.java   | 105 ++-
 .../inference/IntersectionOfVisitorTest.java    | 235 +++++
 20 files changed, 2068 insertions(+), 978 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/common/rya.api/src/main/java/org/apache/rya/api/RdfCloudTripleStoreConfiguration.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/RdfCloudTripleStoreConfiguration.java b/common/rya.api/src/main/java/org/apache/rya/api/RdfCloudTripleStoreConfiguration.java
index c72b85a..ee91e6b 100644
--- a/common/rya.api/src/main/java/org/apache/rya/api/RdfCloudTripleStoreConfiguration.java
+++ b/common/rya.api/src/main/java/org/apache/rya/api/RdfCloudTripleStoreConfiguration.java
@@ -26,12 +26,11 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.hadoop.conf.Configuration;
 import org.apache.rya.api.domain.RyaURI;
 import org.apache.rya.api.layout.TableLayoutStrategy;
 import org.apache.rya.api.layout.TablePrefixLayoutStrategy;
 import org.apache.rya.api.persist.RdfEvalStatsDAO;
-
-import org.apache.hadoop.conf.Configuration;
 import org.openrdf.query.algebra.evaluation.QueryOptimizer;
 
 import com.google.common.base.Joiner;
@@ -59,7 +58,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     public static final String CONF_LIMIT = "query.limit";
     public static final String CONF_QUERYPLAN_FLAG = "query.printqueryplan";
     public static final String CONF_QUERY_AUTH = "query.auth";
-	public static final String CONF_RESULT_FORMAT = "query.resultformat";
+    public static final String CONF_RESULT_FORMAT = "query.resultformat";
     public static final String CONF_CV = "conf.cv";
     public static final String CONF_TBL_SPO = "tbl.spo";
     public static final String CONF_TBL_PO = "tbl.po";
@@ -73,6 +72,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     public static final String CONF_STATEMENT_METADATA_PROPERTIES = "statement.metadata.properites";
     public static final String CONF_USE_STATEMENT_METADATA = "use.statement.metadata";
     public static final String STATS_PUSH_EMPTY_RDFTYPE_DOWN = "conf.stats.rdftype.down";
+    public static final String INFER_INCLUDE_INTERSECTION_OF = "infer.include.intersectionof";
     public static final String INFER_INCLUDE_INVERSEOF = "infer.include.inverseof";
     public static final String INFER_INCLUDE_SUBCLASSOF = "infer.include.subclassof";
     public static final String INFER_INCLUDE_SUBPROPOF = "infer.include.subpropof";
@@ -92,7 +92,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     public RdfCloudTripleStoreConfiguration() {
     }
 
-    public RdfCloudTripleStoreConfiguration(Configuration other) {
+    public RdfCloudTripleStoreConfiguration(final Configuration other) {
         super(other);
         if (other instanceof RdfCloudTripleStoreConfiguration) {
             setTableLayoutStrategy(((RdfCloudTripleStoreConfiguration) other).getTableLayoutStrategy());
@@ -100,13 +100,13 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
     @Override
-	public abstract RdfCloudTripleStoreConfiguration clone();
+    public abstract RdfCloudTripleStoreConfiguration clone();
 
     public TableLayoutStrategy getTableLayoutStrategy() {
         return tableLayoutStrategy;
     }
 
-    public void setTableLayoutStrategy(TableLayoutStrategy tableLayoutStrategy) {
+    public void setTableLayoutStrategy(final TableLayoutStrategy tableLayoutStrategy) {
         if (tableLayoutStrategy != null) {
             this.tableLayoutStrategy = tableLayoutStrategy;
         } else {
@@ -120,28 +120,28 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
     public Long getTtl() {
-        String val = get(CONF_TTL);
+        final String val = get(CONF_TTL);
         if (val != null) {
             return Long.valueOf(val);
         }
         return null;
     }
 
-    public void setTtl(Long ttl) {
+    public void setTtl(final Long ttl) {
         Preconditions.checkNotNull(ttl);
         Preconditions.checkArgument(ttl >= 0, "ttl must be non negative");
         set(CONF_TTL, ttl.toString());
     }
 
     public Long getStartTime() {
-        String val = get(CONF_STARTTIME);
+        final String val = get(CONF_STARTTIME);
         if (val != null) {
             return Long.valueOf(val);
         }
         return null;
     }
 
-    public void setStartTime(Long startTime) {
+    public void setStartTime(final Long startTime) {
         Preconditions.checkNotNull(startTime);
         Preconditions.checkArgument(startTime >= 0, "startTime must be non negative");
         set(CONF_STARTTIME, startTime.toString());
@@ -151,7 +151,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getInt(CONF_NUM_THREADS, 2);
     }
 
-    public void setNumThreads(Integer numThreads) {
+    public void setNumThreads(final Integer numThreads) {
         Preconditions.checkNotNull(numThreads);
         Preconditions.checkArgument(numThreads > 0, "numThreads must be greater than 0");
         setInt(CONF_NUM_THREADS, numThreads);
@@ -161,7 +161,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_PERFORMANT, true);
     }
 
-    public void setPerformant(Boolean val) {
+    public void setPerformant(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_PERFORMANT, val);
     }
@@ -170,7 +170,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_INFER, false);
     }
 
-    public void setInfer(Boolean val) {
+    public void setInfer(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_INFER, val);
     }
@@ -179,7 +179,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_USE_STATS, false);
     }
 
-    public void setUseStats(Boolean val) {
+    public void setUseStats(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_USE_STATS, val);
     }
@@ -188,7 +188,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_USE_SELECTIVITY, false);
     }
 
-    public void setUseSelectivity(Boolean val) {
+    public void setUseSelectivity(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_USE_SELECTIVITY, val);
     }
@@ -197,7 +197,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_PREFIX_ROW_WITH_HASH, false);
     }
 
-    public void setPrefixRowsWithHash(Boolean val) {
+    public void setPrefixRowsWithHash(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_PREFIX_ROW_WITH_HASH, val);
     }
@@ -206,49 +206,49 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return get(CONF_TBL_PREFIX, RdfCloudTripleStoreConstants.TBL_PRFX_DEF);
     }
 
-    public void setTablePrefix(String tablePrefix) {
+    public void setTablePrefix(final String tablePrefix) {
         Preconditions.checkNotNull(tablePrefix);
         set(CONF_TBL_PREFIX, tablePrefix);
         setTableLayoutStrategy(new TablePrefixLayoutStrategy(tablePrefix)); //TODO: Should we change the layout strategy
     }
 
     public Integer getBatchSize() {
-        String val = get(CONF_BATCH_SIZE);
+        final String val = get(CONF_BATCH_SIZE);
         if (val != null) {
             return Integer.valueOf(val);
         }
         return null;
     }
 
-    public void setBatchSize(Long batchSize) {
+    public void setBatchSize(final Long batchSize) {
         Preconditions.checkNotNull(batchSize);
         Preconditions.checkArgument(batchSize > 0, "Batch Size must be greater than 0");
         setLong(CONF_BATCH_SIZE, batchSize);
     }
 
     public Long getOffset() {
-        String val = get(CONF_OFFSET);
+        final String val = get(CONF_OFFSET);
         if (val != null) {
             return Long.valueOf(val);
         }
         return null;
     }
 
-    public void setOffset(Long offset) {
+    public void setOffset(final Long offset) {
         Preconditions.checkNotNull(offset);
         Preconditions.checkArgument(offset >= 0, "offset must be positive");
         setLong(CONF_OFFSET, offset);
     }
 
     public Long getLimit() {
-        String val = get(CONF_LIMIT);
+        final String val = get(CONF_LIMIT);
         if (val != null) {
             return Long.valueOf(val);
         }
         return null;
     }
 
-    public void setLimit(Long limit) {
+    public void setLimit(final Long limit) {
         Preconditions.checkNotNull(limit);
         Preconditions.checkArgument(limit >= 0, "limit must be positive");
         setLong(CONF_LIMIT, limit);
@@ -259,7 +259,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_QUERYPLAN_FLAG, false);
     }
 
-    public void setDisplayQueryPlan(Boolean val) {
+    public void setDisplayQueryPlan(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_QUERYPLAN_FLAG, val);
     }
@@ -269,7 +269,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
      * @deprecated
      */
     @Deprecated
-	public String getAuth() {
+    public String getAuth() {
         return Joiner.on(",").join(getAuths());
     }
 
@@ -278,7 +278,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
      * @deprecated
      */
     @Deprecated
-	public void setAuth(String auth) {
+    public void setAuth(final String auth) {
         Preconditions.checkNotNull(auth);
         setStrings(CONF_QUERY_AUTH, auth);
     }
@@ -287,25 +287,25 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getStrings(CONF_QUERY_AUTH, EMPTY_STR_ARR);
     }
 
-    public void setAuths(String... auths) {
+    public void setAuths(final String... auths) {
         Preconditions.checkNotNull(auths);
         setStrings(CONF_QUERY_AUTH, auths);
     }
 
-	public String getEmit() {
-		return get(CONF_RESULT_FORMAT);
+    public String getEmit() {
+        return get(CONF_RESULT_FORMAT);
     }
 
-    public void setEmit(String emit) {
-		Preconditions.checkNotNull(emit);
-		set(CONF_RESULT_FORMAT, emit);
+    public void setEmit(final String emit) {
+        Preconditions.checkNotNull(emit);
+        set(CONF_RESULT_FORMAT, emit);
     }
 
     public String getCv() {
         return get(CONF_CV);
     }
 
-    public void setCv(String cv) {
+    public void setCv(final String cv) {
         Preconditions.checkNotNull(cv);
         set(CONF_CV, cv);
     }
@@ -315,7 +315,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(CONF_USE_COMPOSITE, true);
     }
 
-    public void setCompositeCardinality(Boolean val) {
+    public void setCompositeCardinality(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(CONF_USE_COMPOSITE, val);
     }
@@ -325,16 +325,35 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(STATS_PUSH_EMPTY_RDFTYPE_DOWN, true);
     }
 
-    public void setStatsPushEmptyRdftypeDown(Boolean val) {
+    public void setStatsPushEmptyRdftypeDown(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(STATS_PUSH_EMPTY_RDFTYPE_DOWN, val);
     }
 
+    /**
+     * @return {@code true} if owl:intersectionOf inferencing is enabled.
+     * {@code false} otherwise. Defaults to {@code true} if nothing is
+     * specified.
+     */
+    public Boolean isInferIntersectionOf() {
+        return getBoolean(INFER_INCLUDE_INTERSECTION_OF, true);
+    }
+
+    /**
+     * Sets whether owl:intersectionOf inferencing is enabled or disabled.
+     * @param value {@code true} if owl:intersectionOf inferencing is enabled.
+     * {@code false} otherwise.
+     */
+    public void setInferIntersectionOf(final Boolean value) {
+        Preconditions.checkNotNull(value);
+        setBoolean(INFER_INCLUDE_INTERSECTION_OF, value);
+    }
+
     public Boolean isInferInverseOf() {
         return getBoolean(INFER_INCLUDE_INVERSEOF, true);
     }
 
-    public void setInferInverseOf(Boolean val) {
+    public void setInferInverseOf(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(INFER_INCLUDE_INVERSEOF, val);
     }
@@ -343,7 +362,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(INFER_INCLUDE_SUBCLASSOF, true);
     }
 
-    public void setInferSubClassOf(Boolean val) {
+    public void setInferSubClassOf(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(INFER_INCLUDE_SUBCLASSOF, val);
     }
@@ -352,7 +371,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(INFER_INCLUDE_SUBPROPOF, true);
     }
 
-    public void setInferSubPropertyOf(Boolean val) {
+    public void setInferSubPropertyOf(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(INFER_INCLUDE_SUBPROPOF, val);
     }
@@ -361,7 +380,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(INFER_INCLUDE_SYMMPROP, true);
     }
 
-    public void setInferSymmetricProperty(Boolean val) {
+    public void setInferSymmetricProperty(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(INFER_INCLUDE_SYMMPROP, val);
     }
@@ -370,12 +389,12 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return getBoolean(INFER_INCLUDE_TRANSITIVEPROP, true);
     }
 
-    public void setInferTransitiveProperty(Boolean val) {
+    public void setInferTransitiveProperty(final Boolean val) {
         Preconditions.checkNotNull(val);
         setBoolean(INFER_INCLUDE_TRANSITIVEPROP, val);
     }
 
-    public void setRdfEvalStatsDaoClass(Class<? extends RdfEvalStatsDAO> rdfEvalStatsDaoClass) {
+    public void setRdfEvalStatsDaoClass(final Class<? extends RdfEvalStatsDAO> rdfEvalStatsDaoClass) {
         Preconditions.checkNotNull(rdfEvalStatsDaoClass);
         setClass(RDF_EVAL_STATS_DAO_CLASS, rdfEvalStatsDaoClass, RdfEvalStatsDAO.class);
     }
@@ -385,50 +404,50 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
 
-    public void setPcjTables(List<String> indexTables) {
+    public void setPcjTables(final List<String> indexTables) {
         Preconditions.checkNotNull(indexTables);
         setStrings(CONF_PCJ_TABLES, indexTables.toArray(new String[]{}));
     }
 
 
     public List<String> getPcjTables() {
-        List<String> pcjTables = Lists.newArrayList();
-        String[] tables = getStrings(CONF_PCJ_TABLES);
+        final List<String> pcjTables = Lists.newArrayList();
+        final String[] tables = getStrings(CONF_PCJ_TABLES);
         if(tables == null) {
             return pcjTables;
         }
-        for(String table: tables) {
+        for(final String table: tables) {
             Preconditions.checkNotNull(table);
             pcjTables.add(table);
         }
         return pcjTables;
     }
-    
-    public void setUseStatementMetadata(boolean useMetadata) {
+
+    public void setUseStatementMetadata(final boolean useMetadata) {
         setBoolean(CONF_USE_STATEMENT_METADATA, useMetadata);
     }
-    
+
     public boolean getUseStatementMetadata() {
         return getBoolean(CONF_USE_STATEMENT_METADATA, false);
     }
-    
-    public void setStatementMetadataProperties(Set<RyaURI> metadataProperties) {
-        
-        String[] propArray = new String[metadataProperties.size()];
+
+    public void setStatementMetadataProperties(final Set<RyaURI> metadataProperties) {
+
+        final String[] propArray = new String[metadataProperties.size()];
         int i = 0;
-        for(RyaURI uri: metadataProperties) {
+        for(final RyaURI uri: metadataProperties) {
             propArray[i] = uri.getData();
             i++;
         }
         setStrings(CONF_STATEMENT_METADATA_PROPERTIES, propArray);
     }
-    
-    
+
+
     public Set<RyaURI> getStatementMetadataProperties() {
-        Set<RyaURI> uriSet = new HashSet<>();
-        String[] uriStrings = getStrings(CONF_STATEMENT_METADATA_PROPERTIES);
+        final Set<RyaURI> uriSet = new HashSet<>();
+        final String[] uriStrings = getStrings(CONF_STATEMENT_METADATA_PROPERTIES);
         if (uriStrings != null) {
-            for (String s : uriStrings) {
+            for (final String s : uriStrings) {
                 uriSet.add(new RyaURI(s));
             }
         }
@@ -436,13 +455,13 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
 
-    public void setPcjOptimizer(Class<? extends QueryOptimizer> optimizer) {
+    public void setPcjOptimizer(final Class<? extends QueryOptimizer> optimizer) {
         Preconditions.checkNotNull(optimizer);
         setClass(CONF_PCJ_OPTIMIZER, optimizer, QueryOptimizer.class);
     }
 
     public Class<QueryOptimizer> getPcjOptimizer() {
-        Class<? extends QueryOptimizer> opt = getClass(CONF_PCJ_OPTIMIZER, null, QueryOptimizer.class);
+        final Class<? extends QueryOptimizer> opt = getClass(CONF_PCJ_OPTIMIZER, null, QueryOptimizer.class);
         if (opt != null) {
             Preconditions.checkArgument(QueryOptimizer.class.isAssignableFrom(opt));
             return (Class<QueryOptimizer>) opt;
@@ -452,10 +471,10 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
 
-    public void setOptimizers(List<Class<? extends QueryOptimizer>> optimizers) {
+    public void setOptimizers(final List<Class<? extends QueryOptimizer>> optimizers) {
         Preconditions.checkNotNull(optimizers);
-        List<String> strs = Lists.newArrayList();
-        for (Class ai : optimizers){
+        final List<String> strs = Lists.newArrayList();
+        for (final Class ai : optimizers){
             Preconditions.checkNotNull(ai);
             strs.add(ai.getName());
         }
@@ -464,8 +483,8 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
     }
 
     public List<Class<QueryOptimizer>> getOptimizers() {
-        List<Class<QueryOptimizer>> opts = Lists.newArrayList();
-        for (Class<?> clazz : getClasses(CONF_OPTIMIZERS)){
+        final List<Class<QueryOptimizer>> opts = Lists.newArrayList();
+        for (final Class<?> clazz : getClasses(CONF_OPTIMIZERS)){
             Preconditions.checkArgument(QueryOptimizer.class.isAssignableFrom(clazz));
             opts.add((Class<QueryOptimizer>) clazz);
         }
@@ -479,7 +498,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return get(REGEX_SUBJECT);
     }
 
-    public void setRegexSubject(String regexSubject) {
+    public void setRegexSubject(final String regexSubject) {
         Preconditions.checkNotNull(regexSubject);
         set(REGEX_SUBJECT, regexSubject);
     }
@@ -488,7 +507,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return get(REGEX_PREDICATE);
     }
 
-    public void setRegexPredicate(String regex) {
+    public void setRegexPredicate(final String regex) {
         Preconditions.checkNotNull(regex);
         set(REGEX_PREDICATE, regex);
     }
@@ -497,7 +516,7 @@ public abstract class RdfCloudTripleStoreConfiguration extends Configuration {
         return get(REGEX_OBJECT);
     }
 
-    public void setRegexObject(String regex) {
+    public void setRegexObject(final String regex) {
         Preconditions.checkNotNull(regex);
         set(REGEX_OBJECT, regex);
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/common/rya.api/src/main/java/org/apache/rya/api/persist/utils/RyaDaoQueryWrapper.java
----------------------------------------------------------------------
diff --git a/common/rya.api/src/main/java/org/apache/rya/api/persist/utils/RyaDaoQueryWrapper.java b/common/rya.api/src/main/java/org/apache/rya/api/persist/utils/RyaDaoQueryWrapper.java
new file mode 100644
index 0000000..af7af8a
--- /dev/null
+++ b/common/rya.api/src/main/java/org/apache/rya/api/persist/utils/RyaDaoQueryWrapper.java
@@ -0,0 +1,185 @@
+/*
+ * 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.api.persist.utils;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.apache.rya.api.domain.RyaStatement;
+import org.apache.rya.api.persist.RyaDAO;
+import org.apache.rya.api.resolver.RyaToRdfConversions;
+import org.openrdf.model.Resource;
+import org.openrdf.model.Statement;
+import org.openrdf.model.URI;
+import org.openrdf.model.Value;
+import org.openrdf.query.QueryEvaluationException;
+import org.openrdf.rio.RDFHandler;
+
+import info.aduna.iteration.CloseableIteration;
+
+/**
+ * Wraps Rya DAO queries into a simpler interface that just passes in the
+ * statement to query for and a handler for dealing with each statement in the
+ * query result. This handles iterating over the query, throwing any exceptions,
+ * and closing the query iterator when done. The same wrapper can be re-used
+ * for multiple queries.
+ */
+public class RyaDaoQueryWrapper {
+    private final RyaDAO<?> ryaDao;
+    private final RdfCloudTripleStoreConfiguration conf;
+
+    /**
+     * Creates a new instance of {@link RyaDaoQueryWrapper}.
+     * @param ryaDao the {@link RyaDAO}. (not {@code null})
+     * @param conf the {@link RdfCloudTripleStoreConfiguration}.
+     * (not {@code null})
+     */
+    public RyaDaoQueryWrapper(final RyaDAO<?> ryaDao, final RdfCloudTripleStoreConfiguration conf) {
+        this.ryaDao = checkNotNull(ryaDao);
+        this.conf = checkNotNull(conf);
+    }
+
+    /**
+     * Creates a new instance of {@link RyaDaoQueryWrapper}.
+     * @param ryaDao the {@link RyaDAO}. (not {@code null})
+     */
+    public RyaDaoQueryWrapper(final RyaDAO<?> ryaDao) {
+        this(checkNotNull(ryaDao), ryaDao.getConf());
+    }
+
+    /**
+     * Handles all results of a query. Closes the query iterator when done.
+     * @param subject the subject {@link Resource} to query for.
+     * @param predicate the predicate {@link URI} to query for.
+     * @param object the object {@link Value} to query for.
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
+     * each statement returned. (not {@code null})
+     * @param contexts the context {@link Resource}s to query for.
+     * @throws QueryEvaluationException
+     */
+    public void queryAll(final Resource subject, final URI predicate, final Value object, final RDFHandler rdfStatementHandler, final Resource... contexts) throws QueryEvaluationException {
+        checkNotNull(rdfStatementHandler);
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDao, subject, predicate, object, conf, contexts);
+        try {
+            while (iter.hasNext()) {
+                final Statement statement = iter.next();
+                try {
+                    rdfStatementHandler.handleStatement(statement);
+                } catch (final Exception e) {
+                    throw new QueryEvaluationException("Error handling statement.", e);
+                }
+            }
+        } finally {
+            if (iter != null) {
+                iter.close();
+            }
+        }
+    }
+
+    /**
+     * Handles all results of a query. Closes the query iterator when done.
+     * @param statement the {@link Statement} to query for. (not {@code null})
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
+     * each statement returned. (not {@code null})
+     * @throws QueryEvaluationException
+     */
+    public void queryAll(final Statement statement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
+        final Resource subject = statement.getSubject();
+        final URI predicate = statement.getPredicate();
+        final Value object = statement.getObject();
+        final Resource context = statement.getContext();
+        queryAll(subject, predicate, object, rdfStatementHandler, context);
+    }
+
+    /**
+     * Handles all results of a query. Closes the query iterator when done.
+     * @param ryaStatement the {@link RyaStatement} to query for.
+     * (not {@code null})
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling
+     * each statement returned. (not {@code null})
+     * @throws QueryEvaluationException
+     */
+    public void queryAll(final RyaStatement ryaStatement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
+        checkNotNull(ryaStatement);
+        final Statement statement = RyaToRdfConversions.convertStatement(ryaStatement);
+        queryAll(statement, rdfStatementHandler);
+    }
+
+    /**
+     * Handles only the first result of a query. Closes the query iterator when
+     * done.
+     * @param subject the subject {@link Resource} to query for.
+     * @param predicate the predicate {@link URI} to query for.
+     * @param object the object {@link Value} to query for.
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
+     * first statement returned. (not {@code null})
+     * @param contexts the context {@link Resource}s to query for.
+     * @throws QueryEvaluationException
+     */
+    public void queryFirst(final Resource subject, final URI predicate, final Value object, final RDFHandler rdfStatementHandler, final Resource... contexts) throws QueryEvaluationException {
+        checkNotNull(rdfStatementHandler);
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDao, subject, predicate, object, conf, contexts);
+        try {
+            if (iter.hasNext()) {
+                final Statement statement = iter.next();
+                try {
+                    rdfStatementHandler.handleStatement(statement);
+                } catch (final Exception e) {
+                    throw new QueryEvaluationException("Error handling statement.", e);
+                }
+            }
+        } finally {
+            if (iter != null) {
+                iter.close();
+            }
+        }
+    }
+
+    /**
+     * Handles only the first result of a query. Closes the query iterator when
+     * done.
+     * @param statement the {@link Statement} to query for. (not {@code null})
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
+     * first statement returned. (not {@code null})
+     * @throws QueryEvaluationException
+     */
+    public void queryFirst(final Statement statement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
+        checkNotNull(statement);
+        final Resource subject = statement.getSubject();
+        final URI predicate = statement.getPredicate();
+        final Value object = statement.getObject();
+        final Resource context = statement.getContext();
+        queryFirst(subject, predicate, object, rdfStatementHandler, context);
+    }
+
+    /**
+     * Handles only the first result of a query. Closes the query iterator when
+     * done.
+     * @param ryaStatement the {@link RyaStatement} to query for.
+     * (not {@code null})
+     * @param rdfStatementHandler the {@link RDFHandler} to use for handling the
+     * first statement returned. (not {@code null})
+     * @throws QueryEvaluationException
+     */
+    public void queryFirst(final RyaStatement ryaStatement, final RDFHandler rdfStatementHandler) throws QueryEvaluationException {
+        checkNotNull(ryaStatement);
+        final Statement statement = RyaToRdfConversions.convertStatement(ryaStatement);
+        queryFirst(statement, rdfStatementHandler);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/extras/indexingExample/src/main/java/MongoRyaDirectExample.java
----------------------------------------------------------------------
diff --git a/extras/indexingExample/src/main/java/MongoRyaDirectExample.java b/extras/indexingExample/src/main/java/MongoRyaDirectExample.java
index 1294a44..342916a 100644
--- a/extras/indexingExample/src/main/java/MongoRyaDirectExample.java
+++ b/extras/indexingExample/src/main/java/MongoRyaDirectExample.java
@@ -6,9 +6,9 @@
  * 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
@@ -22,7 +22,20 @@ import java.util.List;
 
 import org.apache.commons.lang.Validate;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.apache.rya.indexing.accumulo.ConfigUtils;
+import org.apache.rya.indexing.mongodb.MongoIndexingConfiguration;
+import org.apache.rya.indexing.mongodb.MongoIndexingConfiguration.MongoDBIndexingConfigBuilder;
+import org.apache.rya.mongodb.MockMongoFactory;
+import org.apache.rya.mongodb.MongoConnectorFactory;
+import org.apache.rya.rdftriplestore.RdfCloudTripleStore;
+import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
+import org.apache.rya.sail.config.RyaSailFactory;
+import org.apache.zookeeper.ClientCnxn;
 import org.openrdf.model.Namespace;
 import org.openrdf.model.URI;
 import org.openrdf.model.ValueFactory;
@@ -48,21 +61,13 @@ import org.openrdf.sail.Sail;
 import com.mongodb.MongoClient;
 import com.mongodb.ServerAddress;
 
-import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.indexing.GeoConstants;
-import org.apache.rya.indexing.accumulo.ConfigUtils;
-import org.apache.rya.indexing.mongodb.MongoIndexingConfiguration;
-import org.apache.rya.indexing.mongodb.MongoIndexingConfiguration.MongoDBIndexingConfigBuilder;
-import org.apache.rya.mongodb.MockMongoFactory;
-import org.apache.rya.mongodb.MongoConnectorFactory;
-import org.apache.rya.mongodb.MongoDBRdfConfiguration;
-import org.apache.rya.rdftriplestore.RdfCloudTripleStore;
-import org.apache.rya.rdftriplestore.inference.InferenceEngineException;
-import org.apache.rya.sail.config.RyaSailFactory;
+import info.aduna.iteration.Iterations;
 
 public class MongoRyaDirectExample {
     private static final Logger log = Logger.getLogger(MongoRyaDirectExample.class);
 
+    private static final boolean IS_DETAILED_LOGGING_ENABLED = false;
+
     //
     // Connection configuration parameters
     //
@@ -75,19 +80,33 @@ public class MongoRyaDirectExample {
     private static final String MONGO_INSTANCE_URL = "localhost";
     private static final String MONGO_INSTANCE_PORT = "27017";
 
-    public static void main(String[] args) throws Exception {
-        Configuration conf = getConf();
+    public static void setupLogging() {
+        final Logger rootLogger = LogManager.getRootLogger();
+        rootLogger.setLevel(Level.OFF);
+        final ConsoleAppender ca = (ConsoleAppender) rootLogger.getAppender("stdout");
+        ca.setLayout(new PatternLayout("%d{MMM dd yyyy HH:mm:ss} %5p [%t] (%F:%L) - %m%n"));
+        rootLogger.setLevel(Level.INFO);
+        // Filter out noisy messages from the following classes.
+        Logger.getLogger(ClientCnxn.class).setLevel(Level.OFF);
+        Logger.getLogger(MockMongoFactory.class).setLevel(Level.OFF);
+    }
+
+    public static void main(final String[] args) throws Exception {
+        if (IS_DETAILED_LOGGING_ENABLED) {
+            setupLogging();
+        }
+        final Configuration conf = getConf();
         conf.setBoolean(ConfigUtils.DISPLAY_QUERY_PLAN, PRINT_QUERIES);
-  
+
         SailRepository repository = null;
         SailRepositoryConnection conn = null;
         try {
             log.info("Connecting to Indexing Sail Repository.");
-            Sail sail = RyaSailFactory.getInstance(conf);
+            final Sail sail = RyaSailFactory.getInstance(conf);
             repository = new SailRepository(sail);
             conn = repository.getConnection();
 
-            long start = System.currentTimeMillis();
+            final long start = System.currentTimeMillis();
             log.info("Running SPARQL Example: Add and Delete");
             testAddAndDelete(conn);
             testAddAndDeleteNoContext(conn);
@@ -96,10 +115,11 @@ public class MongoRyaDirectExample {
             testAddAndFreeTextSearchWithPCJ(conn);
            //  to test out inference, set inference to true in the conf
             if (USE_INFER){
-            	testInfer(conn, sail);
-            	testPropertyChainInference(conn, sail);
-            	testPropertyChainInferenceAltRepresentation(conn, sail);
-            	testAllValuesFromInference(conn, sail);
+                testInfer(conn, sail);
+                testPropertyChainInference(conn, sail);
+                testPropertyChainInferenceAltRepresentation(conn, sail);
+                testAllValuesFromInference(conn, sail);
+                testIntersectionOfInference(conn, sail);
             }
 
             log.info("TIME: " + (System.currentTimeMillis() - start) / 1000.);
@@ -169,30 +189,30 @@ public class MongoRyaDirectExample {
 //        Validate.isTrue(tupleHandler.getCount() == 0);
 //    }
 
-    private static void closeQuietly(SailRepository repository) {
+    private static void closeQuietly(final SailRepository repository) {
         if (repository != null) {
             try {
                 repository.shutDown();
-            } catch (RepositoryException e) {
+            } catch (final RepositoryException e) {
                 // quietly absorb this exception
             }
         }
     }
 
-    private static void closeQuietly(SailRepositoryConnection conn) {
+    private static void closeQuietly(final SailRepositoryConnection conn) {
         if (conn != null) {
             try {
                 conn.close();
-            } catch (RepositoryException e) {
+            } catch (final RepositoryException e) {
                 // quietly absorb this exception
             }
         }
     }
 
-    private static void testAddAndFreeTextSearchWithPCJ(SailRepositoryConnection conn) throws Exception {
+    private static void testAddAndFreeTextSearchWithPCJ(final SailRepositoryConnection conn) throws Exception {
         // add data to the repository using the SailRepository add methods
-        ValueFactory f = conn.getValueFactory();
-        URI person = f.createURI("http://example.org/ontology/Person");
+        final ValueFactory f = conn.getValueFactory();
+        final URI person = f.createURI("http://example.org/ontology/Person");
 
         String uuid;
 
@@ -272,184 +292,237 @@ public class MongoRyaDirectExample {
     private static MockMongoFactory mock = null;
     private static Configuration getConf() throws IOException {
 
-    	MongoDBIndexingConfigBuilder builder = MongoIndexingConfiguration.builder()
-    		.setUseMockMongo(USE_MOCK).setUseInference(USE_INFER).setAuths("U");
+        MongoDBIndexingConfigBuilder builder = MongoIndexingConfiguration.builder()
+            .setUseMockMongo(USE_MOCK).setUseInference(USE_INFER).setAuths("U");
 
         if (USE_MOCK) {
             mock = MockMongoFactory.newFactory();
-            MongoClient c = mock.newMongoClient();
-            ServerAddress address = c.getAddress();
-            String url = address.getHost();
-            String port = Integer.toString(address.getPort());
+            final MongoClient c = mock.newMongoClient();
+            final ServerAddress address = c.getAddress();
+            final String url = address.getHost();
+            final String port = Integer.toString(address.getPort());
             c.close();
             builder.setMongoHost(url).setMongoPort(port);
         } else {
             // User name and password must be filled in:
-        	builder = builder.setMongoUser("fill this in")
-        					 .setMongoPassword("fill this in")
-        					 .setMongoHost(MONGO_INSTANCE_URL)
-        					 .setMongoPort(MONGO_INSTANCE_PORT);
+            builder = builder.setMongoUser("fill this in")
+                             .setMongoPassword("fill this in")
+                             .setMongoHost(MONGO_INSTANCE_URL)
+                             .setMongoPort(MONGO_INSTANCE_PORT);
         }
-        
+
         return builder.setMongoDBName(MONGO_DB)
                .setMongoCollectionPrefix(MONGO_COLL_PREFIX)
                .setUseMongoFreetextIndex(true)
                .setMongoFreeTextPredicates(RDFS.LABEL.stringValue()).build();
-        
+
     }
 
 
-    public static void testAddAndDelete(SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
+    public static void testAddAndDelete(final SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException {
 
-    	// Add data
-    	String query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <http://acme.com/people/Mike> " //
-    			+ "       <http://acme.com/actions/likes> \"A new book\" ;\n"//
-    			+ "       <http://acme.com/actions/likes> \"Avocados\" .\n" + "} }";
+        // Add data
+        String query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <http://acme.com/people/Mike> " //
+                + "       <http://acme.com/actions/likes> \"A new book\" ;\n"//
+                + "       <http://acme.com/actions/likes> \"Avocados\" .\n" + "} }";
 
-    	log.info("Performing Query");
+        log.info("Performing Query");
 
-    	Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
+        Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
 
-    	query = "select ?p ?o { GRAPH <http://updated/test> {<http://acme.com/people/Mike> ?p ?o . }}";
-    	CountingResultHandler resultHandler = new CountingResultHandler();
-    	TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        query = "select ?p ?o { GRAPH <http://updated/test> {<http://acme.com/people/Mike> ?p ?o . }}";
+        final CountingResultHandler resultHandler = new CountingResultHandler();
+        TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
-    	Validate.isTrue(resultHandler.getCount() == 2);
+        Validate.isTrue(resultHandler.getCount() == 2);
 
-    	resultHandler.resetCount();
+        resultHandler.resetCount();
 
-    	// Delete Data
-    	query = "DELETE DATA\n" //
-    			+ "{ GRAPH <http://updated/test> {\n"
-    			+ "  <http://acme.com/people/Mike> <http://acme.com/actions/likes> \"A new book\" ;\n"
-    			+ "   <http://acme.com/actions/likes> \"Avocados\" .\n" + "}}";
+        // Delete Data
+        query = "DELETE DATA\n" //
+                + "{ GRAPH <http://updated/test> {\n"
+                + "  <http://acme.com/people/Mike> <http://acme.com/actions/likes> \"A new book\" ;\n"
+                + "   <http://acme.com/actions/likes> \"Avocados\" .\n" + "}}";
 
-    	update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
 
-    	query = "select ?p ?o { GRAPH <http://updated/test> {<http://acme.com/people/Mike> ?p ?o . }}";
-    	tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        query = "select ?p ?o { GRAPH <http://updated/test> {<http://acme.com/people/Mike> ?p ?o . }}";
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
-    	Validate.isTrue(resultHandler.getCount() == 0);
+        Validate.isTrue(resultHandler.getCount() == 0);
     }
 
-    
-    public static void testPropertyChainInferenceAltRepresentation(SailRepositoryConnection conn, Sail sail) throws MalformedQueryException, RepositoryException,
+
+    public static void testPropertyChainInferenceAltRepresentation(final SailRepositoryConnection conn, final Sail sail) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException, InferenceEngineException {
 
-    	// Add data
-    	String query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <urn:jenGreatGranMother> <urn:Motherof> <urn:jenGranMother> . "
-    			+ "  <urn:jenGranMother> <urn:isChildOf> <urn:jenGreatGranMother> . "
-    			+ "  <urn:jenGranMother> <urn:Motherof> <urn:jenMother> . " 
-    			+ "  <urn:jenMother> <urn:isChildOf> <urn:jenGranMother> . "
-    			+ " <urn:jenMother> <urn:Motherof> <urn:jen> . "
-    			+ "  <urn:jen> <urn:isChildOf> <urn:jenMother> . "
-    			+ " <urn:jen> <urn:Motherof> <urn:jenDaughter> .  }}";
-
-    	log.info("Performing Query");
-
-    	Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-
-    	query = "select ?p { GRAPH <http://updated/test> {?s <urn:Motherof>/<urn:Motherof> ?p}}";
-    	CountingResultHandler resultHandler = new CountingResultHandler();
-    	TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
-
-
-    	// try adding a property chain and querying for it
-    	query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <urn:greatMother> owl:propertyChainAxiom <urn:12342>  . " + 
-    			" <urn:12342> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:node1atjakcvbx15023 . " + 
-    			" _:node1atjakcvbx15023 <http://www.w3.org/2002/07/owl#inverseOf> <urn:isChildOf> . " + 
-    			" <urn:12342> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:node1atjakcvbx15123 . " + 
-       			" _:node1atjakcvbx15123 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . " + 
-    			" _:node1atjakcvbx15123 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <urn:MotherOf> .  }}";
-    	update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-    	((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
-
-    	resultHandler.resetCount();
-    	query = "select ?x { GRAPH <http://updated/test> {<urn:jenGreatGranMother> <urn:greatMother> ?x}}";
-    	resultHandler = new CountingResultHandler();
-    	tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        // Add data
+        String query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <urn:jenGreatGranMother> <urn:Motherof> <urn:jenGranMother> . "
+                + "  <urn:jenGranMother> <urn:isChildOf> <urn:jenGreatGranMother> . "
+                + "  <urn:jenGranMother> <urn:Motherof> <urn:jenMother> . "
+                + "  <urn:jenMother> <urn:isChildOf> <urn:jenGranMother> . "
+                + " <urn:jenMother> <urn:Motherof> <urn:jen> . "
+                + "  <urn:jen> <urn:isChildOf> <urn:jenMother> . "
+                + " <urn:jen> <urn:Motherof> <urn:jenDaughter> .  }}";
+
+        log.info("Performing Query");
+
+        Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
+
+        query = "select ?p { GRAPH <http://updated/test> {?s <urn:Motherof>/<urn:Motherof> ?p}}";
+        CountingResultHandler resultHandler = new CountingResultHandler();
+        TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+
+
+        // try adding a property chain and querying for it
+        query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <urn:greatMother> owl:propertyChainAxiom <urn:12342>  . " +
+                " <urn:12342> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:node1atjakcvbx15023 . " +
+                " _:node1atjakcvbx15023 <http://www.w3.org/2002/07/owl#inverseOf> <urn:isChildOf> . " +
+                " <urn:12342> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:node1atjakcvbx15123 . " +
+                   " _:node1atjakcvbx15123 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> . " +
+                " _:node1atjakcvbx15123 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <urn:MotherOf> .  }}";
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
+        ((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
+
+        resultHandler.resetCount();
+        query = "select ?x { GRAPH <http://updated/test> {<urn:jenGreatGranMother> <urn:greatMother> ?x}}";
+        resultHandler = new CountingResultHandler();
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
     }
-    
-    public static void testPropertyChainInference(SailRepositoryConnection conn, Sail sail) throws MalformedQueryException, RepositoryException,
+
+    public static void testPropertyChainInference(final SailRepositoryConnection conn, final Sail sail) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException, InferenceEngineException {
 
-    	// Add data
-    	String query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <urn:paulGreatGrandfather> <urn:father> <urn:paulGrandfather> . "
-    			+ "  <urn:paulGrandfather> <urn:father> <urn:paulFather> . " + 
-    			" <urn:paulFather> <urn:father> <urn:paul> . " + 
-    			" <urn:paul> <urn:father> <urn:paulSon> .  }}";
-
-    	log.info("Performing Query");
-
-    	Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-
-    	query = "select ?p { GRAPH <http://updated/test> {<urn:paulGreatGrandfather> <urn:father>/<urn:father> ?p}}";
-    	CountingResultHandler resultHandler = new CountingResultHandler();
-    	TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
-
-
-    	// try adding a property chain and querying for it
-    	query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <urn:greatGrandfather> owl:propertyChainAxiom <urn:1234>  . " + 
-    			" <urn:1234> <http://www.w3.org/2000/10/swap/list#length> 3 . " + 
-    			" <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (0 <urn:father>) . " + 
-    			" <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (1 <urn:father>) . " + 
-    			" <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (2 <urn:father>) .  }}";
-    	update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-    	query = "INSERT DATA\n"//
-    			+ "{ GRAPH <http://updated/test> {\n"//
-    			+ "  <urn:grandfather> owl:propertyChainAxiom <urn:12344>  . " + 
-    			" <urn:12344> <http://www.w3.org/2000/10/swap/list#length> 2 . " + 
-    			" <urn:12344> <http://www.w3.org/2000/10/swap/list#index> (0 <urn:father>) . " + 
-    			" <urn:12344> <http://www.w3.org/2000/10/swap/list#index> (1 <urn:father>) .  }}";
-    	update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-    	((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
-
-    	resultHandler.resetCount();
-    	query = "select ?p { GRAPH <http://updated/test> {<urn:paulGreatGrandfather> <urn:greatGrandfather> ?p}}";
-    	resultHandler = new CountingResultHandler();
-    	tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
-
-    	resultHandler.resetCount();
-    	query = "select ?s ?p { GRAPH <http://updated/test> {?s <urn:grandfather> ?p}}";
-    	resultHandler = new CountingResultHandler();
-    	tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        // Add data
+        String query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <urn:paulGreatGrandfather> <urn:father> <urn:paulGrandfather> . "
+                + "  <urn:paulGrandfather> <urn:father> <urn:paulFather> . " +
+                " <urn:paulFather> <urn:father> <urn:paul> . " +
+                " <urn:paul> <urn:father> <urn:paulSon> .  }}";
+
+        log.info("Performing Query");
+
+        Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
+
+        query = "select ?p { GRAPH <http://updated/test> {<urn:paulGreatGrandfather> <urn:father>/<urn:father> ?p}}";
+        CountingResultHandler resultHandler = new CountingResultHandler();
+        TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+
+
+        // try adding a property chain and querying for it
+        query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <urn:greatGrandfather> owl:propertyChainAxiom <urn:1234>  . " +
+                " <urn:1234> <http://www.w3.org/2000/10/swap/list#length> 3 . " +
+                " <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (0 <urn:father>) . " +
+                " <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (1 <urn:father>) . " +
+                " <urn:1234> <http://www.w3.org/2000/10/swap/list#index> (2 <urn:father>) .  }}";
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
+        query = "INSERT DATA\n"//
+                + "{ GRAPH <http://updated/test> {\n"//
+                + "  <urn:grandfather> owl:propertyChainAxiom <urn:12344>  . " +
+                " <urn:12344> <http://www.w3.org/2000/10/swap/list#length> 2 . " +
+                " <urn:12344> <http://www.w3.org/2000/10/swap/list#index> (0 <urn:father>) . " +
+                " <urn:12344> <http://www.w3.org/2000/10/swap/list#index> (1 <urn:father>) .  }}";
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
+        ((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
+
+        resultHandler.resetCount();
+        query = "select ?p { GRAPH <http://updated/test> {<urn:paulGreatGrandfather> <urn:greatGrandfather> ?p}}";
+        resultHandler = new CountingResultHandler();
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+
+        resultHandler.resetCount();
+        query = "select ?s ?p { GRAPH <http://updated/test> {?s <urn:grandfather> ?p}}";
+        resultHandler = new CountingResultHandler();
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
     }
 
-    public static void testAllValuesFromInference(SailRepositoryConnection conn, Sail sail) throws MalformedQueryException, RepositoryException,
+    public static void testIntersectionOfInference(final SailRepositoryConnection conn, final Sail sail) throws MalformedQueryException, RepositoryException, UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException, InferenceEngineException {
+        log.info("Adding Data");
+        final String instances = "INSERT DATA\n"
+                + "{ GRAPH <http://updated/test> {\n"
+                + "  <urn:Susan> a <urn:Mother> . \n"
+                + "  <urn:Mary> a <urn:Woman> . \n"
+                + "  <urn:Mary> a <urn:Parent> . \n"
+                + "}}";
+        Update update = conn.prepareUpdate(QueryLanguage.SPARQL, instances);
+        update.execute();
+        final String inferQuery = "select distinct ?x { GRAPH <http://updated/test> { ?x a <urn:Mother> }}";
+        final String explicitQuery = "select distinct ?x { GRAPH <http://updated/test> {\n"
+                + "  { ?x a <urn:Mother> }\n"
+                + "  UNION {\n"
+                + "    ?x a <urn:Woman> .\n"
+                + "    ?x a <urn:Parent> .\n"
+                + "  }\n"
+                + "}}";
+        log.info("Running Explicit Query");
+        CountingResultHandler resultHandler = new CountingResultHandler();
+        TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, explicitQuery);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+        Validate.isTrue(resultHandler.getCount() == 2);
+        log.info("Running Inference-dependant Query");
+        resultHandler.resetCount();
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, inferQuery);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+        Validate.isTrue(resultHandler.getCount() == 1);
+        log.info("Adding owl:intersectionOf Schema");
+        // ONTOLOGY - :Mother intersectionOf[:Woman, :Parent]
+        final String ontology = "INSERT DATA\n"
+                + "{ GRAPH <http://updated/test> {\n"
+                + "  <urn:Mother> owl:intersectionOf _:bnode1 . \n"
+                + "  _:bnode1 rdf:first <urn:Woman> . \n"
+                + "  _:bnode1 rdf:rest _:bnode2 . \n"
+                + "  _:bnode2 rdf:first <urn:Parent> . \n"
+                + "  _:bnode2 rdf:rest rdf:nil . \n"
+               + "}}";
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, ontology);
+        update.execute();
+        log.info("Refreshing InferenceEngine");
+        ((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
+        log.info("Re-running Inference-dependant Query");
+        resultHandler.resetCount();
+        resultHandler = new CountingResultHandler();
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, inferQuery);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+        Validate.isTrue(resultHandler.getCount() == 2);
+    }
+
+    public static void testAllValuesFromInference(final SailRepositoryConnection conn, final Sail sail) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException, InferenceEngineException {
         log.info("Adding Data");
         String insert = "INSERT DATA\n"
@@ -469,7 +542,7 @@ public class MongoRyaDirectExample {
                 + "  }\n"
                 + "}}";
         log.info("Running Explicit Query");
-        CountingResultHandler resultHandler = new CountingResultHandler();
+        final CountingResultHandler resultHandler = new CountingResultHandler();
         TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, explicitQuery);
         tupleQuery.evaluate(resultHandler);
         log.info("Result count : " + resultHandler.getCount());
@@ -498,84 +571,85 @@ public class MongoRyaDirectExample {
         log.info("Result count : " + resultHandler.getCount());
         Validate.isTrue(resultHandler.getCount() == 2);
     }
-    
-    public static void testInfer(SailRepositoryConnection conn, Sail sail) throws MalformedQueryException, RepositoryException, 
+
+    public static void testInfer(final SailRepositoryConnection conn, final Sail sail) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException, InferenceEngineException {
 
-    	// Add data
-    	String query = "INSERT DATA\n"//
-    			+ "{ \n"//
-    			+ " <http://acme.com/people/Mike> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <urn:type1>.  "
-    			+ " <urn:type1> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <urn:superclass>.  }";
+        // Add data
+        String query = "INSERT DATA\n"//
+                + "{ \n"//
+                + " <http://acme.com/people/Mike> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <urn:type1>.  "
+                + " <urn:type1> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <urn:superclass>.  }";
 
-    	log.info("Performing Query");
+        log.info("Performing Query");
 
-    	Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
-    	
-    	// refresh the graph for inferencing (otherwise there is a five minute wait)
-    	((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
+        final Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
 
-    	query = "select ?s { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <urn:superclass> . }";
-    	CountingResultHandler resultHandler = new CountingResultHandler();
-    	TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        // refresh the graph for inferencing (otherwise there is a five minute wait)
+        ((RdfCloudTripleStore) sail).getInferenceEngine().refreshGraph();
 
-    	Validate.isTrue(resultHandler.getCount() == 1);
+        query = "select ?s { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <urn:superclass> . }";
+        final CountingResultHandler resultHandler = new CountingResultHandler();
+        final TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
+
+        Validate.isTrue(resultHandler.getCount() == 1);
 
-    	resultHandler.resetCount();
+        resultHandler.resetCount();
     }
-    public static void testAddNamespaces(SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
+
+    public static void testAddNamespaces(final SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException {
 
-    	conn.setNamespace("rya", "http://rya.com");
-    	RepositoryResult<Namespace> results = conn.getNamespaces();
-    	for (Namespace space : results.asList()){
-    		System.out.println(space.getName() + ", " + space.getPrefix());
-    	}
+        conn.setNamespace("rya", "http://rya.com");
+        final RepositoryResult<Namespace> results = conn.getNamespaces();
+        for (final Namespace space : Iterations.asList(results)){
+            System.out.println(space.getName() + ", " + space.getPrefix());
+        }
       }
 
-    public static void testAddAndDeleteNoContext(SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
+    public static void testAddAndDeleteNoContext(final SailRepositoryConnection conn) throws MalformedQueryException, RepositoryException,
     UpdateExecutionException, QueryEvaluationException, TupleQueryResultHandlerException {
 
-    	// Add data
-    	String query = "INSERT DATA\n"//
-    			+ "{ \n"//
-    			+ "  <http://acme.com/people/Mike> " //
-    			+ "       <http://acme.com/actions/likes> \"A new book\" ;\n"//
-    			+ "       <http://acme.com/actions/likes> \"Avocados\" .\n" + " }";
+        // Add data
+        String query = "INSERT DATA\n"//
+                + "{ \n"//
+                + "  <http://acme.com/people/Mike> " //
+                + "       <http://acme.com/actions/likes> \"A new book\" ;\n"//
+                + "       <http://acme.com/actions/likes> \"Avocados\" .\n" + " }";
 
-    	log.info("Performing Query");
+        log.info("Performing Query");
 
-    	Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
+        Update update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
 
-    	query = "select ?p ?o {<http://acme.com/people/Mike> ?p ?o . }";
-    	CountingResultHandler resultHandler = new CountingResultHandler();
-    	TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        query = "select ?p ?o {<http://acme.com/people/Mike> ?p ?o . }";
+        final CountingResultHandler resultHandler = new CountingResultHandler();
+        TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
-    	Validate.isTrue(resultHandler.getCount() == 2);
+        Validate.isTrue(resultHandler.getCount() == 2);
 
-    	resultHandler.resetCount();
+        resultHandler.resetCount();
 
-    	// Delete Data
-    	query = "DELETE DATA\n" //
-    			+ "{ \n"
-    			+ "  <http://acme.com/people/Mike> <http://acme.com/actions/likes> \"A new book\" ;\n"
-    			+ "   <http://acme.com/actions/likes> \"Avocados\" .\n" + "}";
+        // Delete Data
+        query = "DELETE DATA\n" //
+                + "{ \n"
+                + "  <http://acme.com/people/Mike> <http://acme.com/actions/likes> \"A new book\" ;\n"
+                + "   <http://acme.com/actions/likes> \"Avocados\" .\n" + "}";
 
-    	update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
-    	update.execute();
+        update = conn.prepareUpdate(QueryLanguage.SPARQL, query);
+        update.execute();
 
-    	query = "select ?p ?o { {<http://acme.com/people/Mike> ?p ?o . }}";
-    	tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
-    	tupleQuery.evaluate(resultHandler);
-    	log.info("Result count : " + resultHandler.getCount());
+        query = "select ?p ?o { {<http://acme.com/people/Mike> ?p ?o . }}";
+        tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, query);
+        tupleQuery.evaluate(resultHandler);
+        log.info("Result count : " + resultHandler.getCount());
 
-    	Validate.isTrue(resultHandler.getCount() == 0);
+        Validate.isTrue(resultHandler.getCount() == 0);
     }
 
     private static class CountingResultHandler implements TupleQueryResultHandler {
@@ -590,11 +664,11 @@ public class MongoRyaDirectExample {
         }
 
         @Override
-        public void startQueryResult(List<String> arg0) throws TupleQueryResultHandlerException {
+        public void startQueryResult(final List<String> arg0) throws TupleQueryResultHandlerException {
         }
 
         @Override
-        public void handleSolution(BindingSet arg0) throws TupleQueryResultHandlerException {
+        public void handleSolution(final BindingSet arg0) throws TupleQueryResultHandlerException {
             count++;
             System.out.println(arg0);
         }
@@ -604,15 +678,11 @@ public class MongoRyaDirectExample {
         }
 
         @Override
-        public void handleBoolean(boolean arg0) throws QueryResultHandlerException {
-          // TODO Auto-generated method stub
-          
+        public void handleBoolean(final boolean arg0) throws QueryResultHandlerException {
         }
 
         @Override
-        public void handleLinks(List<String> arg0) throws QueryResultHandlerException {
-          // TODO Auto-generated method stub
-          
+        public void handleLinks(final List<String> arg0) throws QueryResultHandlerException {
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/RdfCloudTripleStoreConnection.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/RdfCloudTripleStoreConnection.java b/sail/src/main/java/org/apache/rya/rdftriplestore/RdfCloudTripleStoreConnection.java
index ec93da8..a64c0ec 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/RdfCloudTripleStoreConnection.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/RdfCloudTripleStoreConnection.java
@@ -46,6 +46,7 @@ import org.apache.rya.api.persist.utils.RyaDAOHelper;
 import org.apache.rya.api.resolver.RdfToRyaConversions;
 import org.apache.rya.rdftriplestore.evaluation.FilterRangeVisitor;
 import org.apache.rya.rdftriplestore.evaluation.ParallelEvaluationStrategyImpl;
+import org.apache.rya.rdftriplestore.evaluation.QueryJoinOptimizer;
 import org.apache.rya.rdftriplestore.evaluation.QueryJoinSelectOptimizer;
 import org.apache.rya.rdftriplestore.evaluation.RdfCloudTripleStoreEvaluationStatistics;
 import org.apache.rya.rdftriplestore.evaluation.RdfCloudTripleStoreSelectivityEvaluationStatistics;
@@ -54,6 +55,7 @@ import org.apache.rya.rdftriplestore.inference.AllValuesFromVisitor;
 import org.apache.rya.rdftriplestore.inference.DomainRangeVisitor;
 import org.apache.rya.rdftriplestore.inference.HasValueVisitor;
 import org.apache.rya.rdftriplestore.inference.InferenceEngine;
+import org.apache.rya.rdftriplestore.inference.IntersectionOfVisitor;
 import org.apache.rya.rdftriplestore.inference.InverseOfVisitor;
 import org.apache.rya.rdftriplestore.inference.PropertyChainVisitor;
 import org.apache.rya.rdftriplestore.inference.SameAsVisitor;
@@ -103,7 +105,6 @@ import org.openrdf.sail.helpers.SailConnectionBase;
 import info.aduna.iteration.CloseableIteration;
 
 public class RdfCloudTripleStoreConnection extends SailConnectionBase {
-
     private final RdfCloudTripleStore store;
 
     private RdfEvalStatsDAO rdfEvalStatsDAO;
@@ -114,7 +115,7 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
     private final RdfCloudTripleStoreConfiguration conf;
 
 
-	private ProvenanceCollector provenanceCollector;
+    private ProvenanceCollector provenanceCollector;
 
     public RdfCloudTripleStoreConnection(final RdfCloudTripleStore sailBase, final RdfCloudTripleStoreConfiguration conf, final ValueFactory vf)
             throws SailException {
@@ -218,12 +219,11 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
         verifyIsOpen();
         logger.trace("Incoming query model:\n{}", tupleExpr.toString());
         if (provenanceCollector != null){
-        	try {
-				provenanceCollector.recordQuery(tupleExpr.toString());
-			} catch (final ProvenanceCollectionException e) {
-				// TODO silent fail
-				e.printStackTrace();
-			}
+            try {
+                provenanceCollector.recordQuery(tupleExpr.toString());
+            } catch (final ProvenanceCollectionException e) {
+                logger.trace("Provenance failed to record query.", e);
+            }
         }
         tupleExpr = tupleExpr.clone();
 
@@ -354,6 +354,7 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
                     tupleExpr.visit(new DomainRangeVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new AllValuesFromVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new HasValueVisitor(queryConf, inferenceEngine));
+                    tupleExpr.visit(new IntersectionOfVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new PropertyChainVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new TransitivePropertyVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new SymmetricPropertyVisitor(queryConf, inferenceEngine));
@@ -362,7 +363,7 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
                     tupleExpr.visit(new SubClassOfVisitor(queryConf, inferenceEngine));
                     tupleExpr.visit(new SameAsVisitor(queryConf, inferenceEngine));
                 } catch (final Exception e) {
-                    e.printStackTrace();
+                    logger.error("Error encountered while visiting query node.", e);
                 }
             }
             if (queryConf.isPerformant()) {
@@ -388,13 +389,11 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
             if (stats != null) {
 
                 if (stats instanceof RdfCloudTripleStoreSelectivityEvaluationStatistics) {
-
-                    (new QueryJoinSelectOptimizer(stats,
-                            selectEvalDAO)).optimize(tupleExpr, dataset, bindings);
+                    final QueryJoinSelectOptimizer qjso = new QueryJoinSelectOptimizer(stats, selectEvalDAO);
+                    qjso.optimize(tupleExpr, dataset, bindings);
                 } else {
-
-                    (new org.apache.rya.rdftriplestore.evaluation.QueryJoinOptimizer(stats)).optimize(tupleExpr, dataset,
-                            bindings); // TODO: Make pluggable
+                    final QueryJoinOptimizer qjo = new QueryJoinOptimizer(stats);
+                    qjo.optimize(tupleExpr, dataset, bindings); // TODO: Make pluggable
                 }
             }
 
@@ -611,7 +610,7 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
         }
 
         @Override
-		public CloseableIteration<Statement, QueryEvaluationException> getStatements(
+        public CloseableIteration<Statement, QueryEvaluationException> getStatements(
                 final Resource subject, final URI predicate, final Value object,
                 final Resource... contexts) throws QueryEvaluationException {
             return RyaDAOHelper.query(ryaDAO, subject, predicate, object, conf, contexts);
@@ -625,7 +624,7 @@ public class RdfCloudTripleStoreConnection extends SailConnectionBase {
         }
 
         @Override
-		public ValueFactory getValueFactory() {
+        public ValueFactory getValueFactory() {
             return RdfCloudTripleStoreConstants.VALUE_FACTORY;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/FilterRangeVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/FilterRangeVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/FilterRangeVisitor.java
index db5ba78..27b799f 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/FilterRangeVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/FilterRangeVisitor.java
@@ -1,5 +1,11 @@
 package org.apache.rya.rdftriplestore.evaluation;
 
+import static org.apache.rya.api.RdfCloudTripleStoreConstants.RANGE;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -8,9 +14,9 @@ package org.apache.rya.rdftriplestore.evaluation;
  * 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
@@ -27,47 +33,46 @@ import org.apache.rya.api.domain.RangeValue;
 import org.openrdf.model.Value;
 import org.openrdf.model.impl.BooleanLiteralImpl;
 import org.openrdf.query.QueryEvaluationException;
-import org.openrdf.query.algebra.*;
+import org.openrdf.query.algebra.Filter;
+import org.openrdf.query.algebra.FunctionCall;
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.ValueConstant;
+import org.openrdf.query.algebra.ValueExpr;
+import org.openrdf.query.algebra.Var;
 import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.apache.rya.api.RdfCloudTripleStoreConstants.RANGE;
-
 /**
  * Class FilterTimeIndexVisitor
  * Date: Apr 11, 2011
  * Time: 10:16:15 PM
  */
-public class FilterRangeVisitor extends QueryModelVisitorBase {
+public class FilterRangeVisitor extends QueryModelVisitorBase<Exception> {
 
-    private RdfCloudTripleStoreConfiguration conf;
-    private Map<Var, RangeValue> rangeValues = new HashMap<Var, RangeValue>();
+    private final RdfCloudTripleStoreConfiguration conf;
+    private final Map<Var, RangeValue> rangeValues = new HashMap<Var, RangeValue>();
 
-    public FilterRangeVisitor(RdfCloudTripleStoreConfiguration conf) {
+    public FilterRangeVisitor(final RdfCloudTripleStoreConfiguration conf) {
         this.conf = conf;
     }
 
     @Override
-    public void meet(Filter node) throws Exception {
+    public void meet(final Filter node) throws Exception {
         super.meet(node);
 
-        ValueExpr arg = node.getCondition();
+        final ValueExpr arg = node.getCondition();
         if (arg instanceof FunctionCall) {
-            FunctionCall fc = (FunctionCall) arg;
+            final FunctionCall fc = (FunctionCall) arg;
             if (RANGE.stringValue().equals(fc.getURI())) {
                 //range(?var, start, end)
-                List<ValueExpr> valueExprs = fc.getArgs();
+                final List<ValueExpr> valueExprs = fc.getArgs();
                 if (valueExprs.size() != 3) {
                     throw new QueryEvaluationException("org.apache:range must have 3 parameters: variable, start, end");
                 }
-                Var var = (Var) valueExprs.get(0);
-                ValueConstant startVc = (ValueConstant) valueExprs.get(1);
-                ValueConstant endVc = (ValueConstant) valueExprs.get(2);
-                Value start = startVc.getValue();
-                Value end = endVc.getValue();
+                final Var var = (Var) valueExprs.get(0);
+                final ValueConstant startVc = (ValueConstant) valueExprs.get(1);
+                final ValueConstant endVc = (ValueConstant) valueExprs.get(2);
+                final Value start = startVc.getValue();
+                final Value end = endVc.getValue();
                 rangeValues.put(var, new RangeValue(start, end));
                 node.setCondition(new ValueConstant(BooleanLiteralImpl.TRUE));
             }
@@ -75,15 +80,15 @@ public class FilterRangeVisitor extends QueryModelVisitorBase {
     }
 
     @Override
-    public void meet(StatementPattern node) throws Exception {
+    public void meet(final StatementPattern node) throws Exception {
         super.meet(node);
 
-        Var subjectVar = node.getSubjectVar();
-        RangeValue subjRange = rangeValues.get(subjectVar);
-        Var predVar = node.getPredicateVar();
-        RangeValue predRange = rangeValues.get(predVar);
-        Var objVar = node.getObjectVar();
-        RangeValue objRange = rangeValues.get(objVar);
+        final Var subjectVar = node.getSubjectVar();
+        final RangeValue subjRange = rangeValues.get(subjectVar);
+        final Var predVar = node.getPredicateVar();
+        final RangeValue predRange = rangeValues.get(predVar);
+        final Var objVar = node.getObjectVar();
+        final RangeValue objRange = rangeValues.get(objVar);
         if(subjRange != null) {
             subjectVar.setValue(new RangeURI(subjRange));//Assumes no blank nodes can be ranges
         }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/PushJoinDownVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/PushJoinDownVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/PushJoinDownVisitor.java
index ebf9737..ecf4c7b 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/PushJoinDownVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/PushJoinDownVisitor.java
@@ -8,9 +8,9 @@ package org.apache.rya.rdftriplestore.evaluation;
  * 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
@@ -30,13 +30,13 @@ import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
  * Date: Apr 11, 2011
  * Time: 10:16:15 PM
  */
-public class PushJoinDownVisitor extends QueryModelVisitorBase {
+public class PushJoinDownVisitor extends QueryModelVisitorBase<Exception> {
     @Override
-    public void meet(Join node) throws Exception {
+    public void meet(final Join node) throws Exception {
         super.meet(node);
 
-        TupleExpr leftArg = node.getLeftArg();
-        TupleExpr rightArg = node.getRightArg();
+        final TupleExpr leftArg = node.getLeftArg();
+        final TupleExpr rightArg = node.getRightArg();
 
         /**
          * if join(join(1, 2), join(3,4))
@@ -44,12 +44,12 @@ public class PushJoinDownVisitor extends QueryModelVisitorBase {
          * join(join(join(1,2), 3), 4)
          */
         if (leftArg instanceof Join && rightArg instanceof Join) {
-            Join leftJoin = (Join) leftArg;
-            Join rightJoin = (Join) rightArg;
-            TupleExpr right_LeftArg = rightJoin.getLeftArg();
-            TupleExpr right_rightArg = rightJoin.getRightArg();
-            Join inner = new Join(leftJoin, right_LeftArg);
-            Join outer = new Join(inner, right_rightArg);
+            final Join leftJoin = (Join) leftArg;
+            final Join rightJoin = (Join) rightArg;
+            final TupleExpr right_LeftArg = rightJoin.getLeftArg();
+            final TupleExpr right_rightArg = rightJoin.getRightArg();
+            final Join inner = new Join(leftJoin, right_LeftArg);
+            final Join outer = new Join(inner, right_rightArg);
             node.replaceWith(outer);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/ReorderJoinVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/ReorderJoinVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/ReorderJoinVisitor.java
index 9ff09b2..2ae159f 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/ReorderJoinVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/ReorderJoinVisitor.java
@@ -8,9 +8,9 @@ package org.apache.rya.rdftriplestore.evaluation;
  * 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
@@ -31,13 +31,13 @@ import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
  * Date: Apr 11, 2011
  * Time: 10:16:15 PM
  */
-public class ReorderJoinVisitor extends QueryModelVisitorBase {
+public class ReorderJoinVisitor extends QueryModelVisitorBase<Exception> {
     @Override
-    public void meet(Join node) throws Exception {
+    public void meet(final Join node) throws Exception {
         super.meet(node);
-        
-        TupleExpr leftArg = node.getLeftArg();
-        TupleExpr rightArg = node.getRightArg();
+
+        final TupleExpr leftArg = node.getLeftArg();
+        final TupleExpr rightArg = node.getRightArg();
 
         /**
          * if join(stmtPattern1, join(stmtPattern2, anything)
@@ -45,10 +45,10 @@ public class ReorderJoinVisitor extends QueryModelVisitorBase {
          * join(join(stmtPattern1, stmtPattern2), anything)
          */
         if (leftArg instanceof StatementPattern && rightArg instanceof Join) {
-            Join rightJoin = (Join) rightArg;
+            final Join rightJoin = (Join) rightArg;
             //find the stmtPattern in the right side
-            TupleExpr right_LeftArg = rightJoin.getLeftArg();
-            TupleExpr right_rightArg = rightJoin.getRightArg();
+            final TupleExpr right_LeftArg = rightJoin.getLeftArg();
+            final TupleExpr right_rightArg = rightJoin.getRightArg();
             if (right_LeftArg instanceof StatementPattern || right_rightArg instanceof StatementPattern) {
                 StatementPattern stmtPattern = null;
                 TupleExpr anything = null;
@@ -60,8 +60,8 @@ public class ReorderJoinVisitor extends QueryModelVisitorBase {
                     anything = right_LeftArg;
                 }
 
-                Join inner = new Join(leftArg, stmtPattern);
-                Join outer = new Join(inner, anything);
+                final Join inner = new Join(leftArg, stmtPattern);
+                final Join outer = new Join(inner, anything);
                 node.replaceWith(outer);
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/SeparateFilterJoinsVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/SeparateFilterJoinsVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/SeparateFilterJoinsVisitor.java
index fc16c15..8f24220 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/SeparateFilterJoinsVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/evaluation/SeparateFilterJoinsVisitor.java
@@ -8,9 +8,9 @@ package org.apache.rya.rdftriplestore.evaluation;
  * 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
@@ -18,10 +18,11 @@ package org.apache.rya.rdftriplestore.evaluation;
  * specific language governing permissions and limitations
  * under the License.
  */
-
-
-
-import org.openrdf.query.algebra.*;
+import org.openrdf.query.algebra.Filter;
+import org.openrdf.query.algebra.Join;
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.ValueExpr;
 import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
 
 /**
@@ -30,24 +31,24 @@ import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
  * Date: Apr 11, 2011
  * Time: 10:16:15 PM
  */
-public class SeparateFilterJoinsVisitor extends QueryModelVisitorBase {
+public class SeparateFilterJoinsVisitor extends QueryModelVisitorBase<Exception> {
     @Override
-    public void meet(Filter node) throws Exception {
+    public void meet(final Filter node) throws Exception {
         super.meet(node);
 
-        ValueExpr condition = node.getCondition();
-        TupleExpr arg = node.getArg();
+        final ValueExpr condition = node.getCondition();
+        final TupleExpr arg = node.getArg();
         if (!(arg instanceof Join)) {
             return;
         }
 
-        Join join = (Join) arg;
-        TupleExpr leftArg = join.getLeftArg();
-        TupleExpr rightArg = join.getRightArg();
+        final Join join = (Join) arg;
+        final TupleExpr leftArg = join.getLeftArg();
+        final TupleExpr rightArg = join.getRightArg();
 
         if (leftArg instanceof StatementPattern && rightArg instanceof StatementPattern) {
-            Filter left = new Filter(leftArg, condition);
-            Filter right = new Filter(rightArg, condition);
+            final Filter left = new Filter(leftArg, condition);
+            final Filter right = new Filter(rightArg, condition);
             node.replaceWith(new Join(left, right));
         }
 



[2/3] incubator-rya git commit: RYA-292 Added owl:intersectionOf inference. Closes #206.

Posted by ca...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
index 05b847b..a2f8d63 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
@@ -6,9 +6,9 @@
  * 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
@@ -25,8 +25,10 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.Stack;
 import java.util.Timer;
@@ -34,6 +36,18 @@ import java.util.TimerTask;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.log4j.Logger;
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.apache.rya.api.persist.RyaDAO;
+import org.apache.rya.api.persist.RyaDAOException;
+import org.apache.rya.api.persist.utils.RyaDAOHelper;
+import org.apache.rya.api.persist.utils.RyaDaoQueryWrapper;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
 import org.openrdf.model.Resource;
 import org.openrdf.model.Statement;
 import org.openrdf.model.URI;
@@ -45,21 +59,12 @@ import org.openrdf.model.vocabulary.OWL;
 import org.openrdf.model.vocabulary.RDF;
 import org.openrdf.model.vocabulary.RDFS;
 import org.openrdf.query.QueryEvaluationException;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.openrdf.rio.RDFHandlerException;
+import org.openrdf.rio.helpers.RDFHandlerBase;
 
-import com.google.common.collect.Iterators;
+import com.google.common.collect.Sets;
 
 import info.aduna.iteration.CloseableIteration;
-import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
-import org.apache.rya.api.persist.RyaDAO;
-import org.apache.rya.api.persist.RyaDAOException;
-import org.apache.rya.api.persist.utils.RyaDAOHelper;
 
 /**
  * Will pull down inference relationships from dao every x seconds. <br>
@@ -67,6 +72,7 @@ import org.apache.rya.api.persist.utils.RyaDAOHelper;
  * Will cache relationships in Graph for later use. <br>
  */
 public class InferenceEngine {
+    private static final Logger log = Logger.getLogger(InferenceEngine.class);
 
     private Graph subClassOfGraph;
     private Graph subPropertyOfGraph;
@@ -78,15 +84,17 @@ public class InferenceEngine {
     private Map<Resource, Map<URI, Value>> hasValueByType;
     private Map<URI, Map<Resource, Value>> hasValueByProperty;
     private Map<Resource, Map<Resource, URI>> allValuesFromByValueType;
+    private final ConcurrentHashMap<Resource, List<Set<Resource>>> intersections = new ConcurrentHashMap<>();
 
-    private RyaDAO ryaDAO;
+    private RyaDAO<?> ryaDAO;
     private RdfCloudTripleStoreConfiguration conf;
+    private RyaDaoQueryWrapper ryaDaoQueryWrapper;
     private boolean initialized = false;
     private boolean schedule = true;
 
     private long refreshGraphSchedule = 5 * 60 * 1000; //5 min
     private Timer timer;
-	private HashMap<URI, List<URI>> propertyChainPropertyToChain = new HashMap<URI, List<URI>>();
+    private HashMap<URI, List<URI>> propertyChainPropertyToChain = new HashMap<>();
     public static final String URI_PROP = "uri";
 
     public void init() throws InferenceEngineException {
@@ -98,9 +106,10 @@ public class InferenceEngine {
             checkNotNull(conf, "Configuration is null");
             checkNotNull(ryaDAO, "RdfDao is null");
             checkArgument(ryaDAO.isInitialized(), "RdfDao is not initialized");
+            ryaDaoQueryWrapper = new RyaDaoQueryWrapper(ryaDAO, conf);
 
             if (schedule) {
-            	refreshGraph();
+                refreshGraph();
                 timer = new Timer(InferenceEngine.class.getName());
                 timer.scheduleAtFixedRate(new TimerTask() {
 
@@ -108,7 +117,7 @@ public class InferenceEngine {
                     public void run() {
                         try {
                             refreshGraph();
-                        } catch (InferenceEngineException e) {
+                        } catch (final InferenceEngineException e) {
                             throw new RuntimeException(e);
                         }
                     }
@@ -117,7 +126,7 @@ public class InferenceEngine {
             }
             refreshGraph();
             setInitialized(true);
-        } catch (RyaDAOException e) {
+        } catch (final RyaDAOException e) {
             throw new InferenceEngineException(e);
         }
     }
@@ -130,7 +139,7 @@ public class InferenceEngine {
     }
 
     public void refreshGraph() throws InferenceEngineException {
-        ValueFactory vf = ValueFactoryImpl.getInstance();
+        final ValueFactory vf = ValueFactoryImpl.getInstance();
         try {
             CloseableIteration<Statement, QueryEvaluationException> iter;
             //get all subclassof
@@ -146,20 +155,20 @@ public class InferenceEngine {
             iter = RyaDAOHelper.query(ryaDAO, null, OWL.UNIONOF, null, conf);
             try {
                 while (iter.hasNext()) {
-                    Statement st = iter.next();
-                    Value unionType = st.getSubject();
+                    final Statement st = iter.next();
+                    final Value unionType = st.getSubject();
                     // Traverse the list of types constituting the union
                     Value current = st.getObject();
                     while (current instanceof Resource && !RDF.NIL.equals(current)) {
-                        Resource listNode = (Resource) current;
+                        final Resource listNode = (Resource) current;
                         CloseableIteration<Statement, QueryEvaluationException> listIter = RyaDAOHelper.query(ryaDAO,
                                 listNode, RDF.FIRST, null, conf);
                         try {
                             if (listIter.hasNext()) {
-                                Statement firstStatement = listIter.next();
+                                final Statement firstStatement = listIter.next();
                                 if (firstStatement.getObject() instanceof Resource) {
-                                    Resource subclass = (Resource) firstStatement.getObject();
-                                    Statement subclassStatement = vf.createStatement(subclass, RDFS.SUBCLASSOF, unionType);
+                                    final Resource subclass = (Resource) firstStatement.getObject();
+                                    final Statement subclassStatement = vf.createStatement(subclass, RDFS.SUBCLASSOF, unionType);
                                     addStatementEdge(graph, RDFS.SUBCLASSOF.stringValue(), subclassStatement);
                                 }
                             }
@@ -192,11 +201,13 @@ public class InferenceEngine {
             addPredicateEdges(OWL.EQUIVALENTPROPERTY, Direction.BOTH, graph, RDFS.SUBPROPERTYOF.stringValue());
             subPropertyOfGraph = graph; //TODO: Should this be synchronized?
 
+            refreshIntersectionOf();
+
             iter = RyaDAOHelper.query(ryaDAO, null, RDF.TYPE, OWL.SYMMETRICPROPERTY, conf);
-            Set<URI> symProp = new HashSet();
+            final Set<URI> symProp = new HashSet<>();
             try {
                 while (iter.hasNext()) {
-                    Statement st = iter.next();
+                    final Statement st = iter.next();
                     symProp.add((URI) st.getSubject()); //safe to assume it is a URI?
                 }
             } finally {
@@ -207,10 +218,10 @@ public class InferenceEngine {
             symmetricPropertySet = symProp;
 
             iter = RyaDAOHelper.query(ryaDAO, null, RDF.TYPE, OWL.TRANSITIVEPROPERTY, conf);
-            Set<URI> transProp = new HashSet();
+            final Set<URI> transProp = new HashSet<>();
             try {
                 while (iter.hasNext()) {
-                    Statement st = iter.next();
+                    final Statement st = iter.next();
                     transProp.add((URI) st.getSubject());
                 }
             } finally {
@@ -221,10 +232,10 @@ public class InferenceEngine {
             transitivePropertySet = transProp;
 
             iter = RyaDAOHelper.query(ryaDAO, null, OWL.INVERSEOF, null, conf);
-            Map<URI, URI> invProp = new HashMap();
+            final Map<URI, URI> invProp = new HashMap<>();
             try {
                 while (iter.hasNext()) {
-                    Statement st = iter.next();
+                    final Statement st = iter.next();
                     invProp.put((URI) st.getSubject(), (URI) st.getObject());
                     invProp.put((URI) st.getObject(), (URI) st.getSubject());
                 }
@@ -234,153 +245,153 @@ public class InferenceEngine {
                 }
             }
             inverseOfMap = invProp;
-            
-            iter = RyaDAOHelper.query(ryaDAO, null, 
-            		vf.createURI("http://www.w3.org/2002/07/owl#propertyChainAxiom"),
-            		null, conf);
-            Map<URI,URI> propertyChainPropertiesToBNodes = new HashMap<URI, URI>();
-            propertyChainPropertyToChain = new HashMap<URI, List<URI>>();
+
+            iter = RyaDAOHelper.query(ryaDAO, null,
+                    vf.createURI("http://www.w3.org/2002/07/owl#propertyChainAxiom"),
+                    null, conf);
+            final Map<URI,URI> propertyChainPropertiesToBNodes = new HashMap<>();
+            propertyChainPropertyToChain = new HashMap<>();
             try {
-            	while (iter.hasNext()){
-            		Statement st = iter.next();
-            		propertyChainPropertiesToBNodes.put((URI)st.getSubject(), (URI)st.getObject());
-            	}
+                while (iter.hasNext()){
+                    final Statement st = iter.next();
+                    propertyChainPropertiesToBNodes.put((URI)st.getSubject(), (URI)st.getObject());
+                }
             } finally {
                 if (iter != null) {
                     iter.close();
                 }
             }
             // now for each property chain bNode, get the indexed list of properties associated with that chain
-            for (URI propertyChainProperty : propertyChainPropertiesToBNodes.keySet()){
-            	URI bNode = propertyChainPropertiesToBNodes.get(propertyChainProperty);
-            	// query for the list of indexed properties
-            	iter = RyaDAOHelper.query(ryaDAO, bNode, vf.createURI("http://www.w3.org/2000/10/swap/list#index"),
-            			null, conf);
-            	TreeMap<Integer, URI> orderedProperties = new TreeMap<Integer, URI>();
-            	// TODO refactor this.  Wish I could execute sparql
-            	try {
-            		while (iter.hasNext()){
-            		  Statement st = iter.next();
-            		  String indexedElement = st.getObject().stringValue();
-            		  System.out.println(indexedElement);
-            		  CloseableIteration<Statement, QueryEvaluationException>  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(st.getObject().stringValue()), RDF.FIRST,
-                    			null, conf);
-            		  String integerValue = "";
-            		  Value anonPropNode = null;
-            		  Value propURI = null;
-            		  if (iter2 != null){
-            			  while (iter2.hasNext()){
-            				  Statement iter2Statement = iter2.next();
-            				  integerValue = iter2Statement.getObject().stringValue();
-            				  break;
-            			  }
-            			  iter2.close();
-            		  }
-            		  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(st.getObject().stringValue()), RDF.REST,
-                  			null, conf);
-            		  if (iter2 != null){
-            			  while (iter2.hasNext()){
-            				  Statement iter2Statement = iter2.next();
-            				  anonPropNode = iter2Statement.getObject();
-            				  break;
-            			  }
-            			  iter2.close();
-            			  if (anonPropNode != null){
-            				  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(anonPropNode.stringValue()), RDF.FIRST,
-                            			null, conf);
-            				  while (iter2.hasNext()){
-                				  Statement iter2Statement = iter2.next();
-                				  propURI = iter2Statement.getObject();
-                				  break;
-                			  }
-                			  iter2.close();
-            			  }
-            		  }
-            		  if (!integerValue.isEmpty() && propURI!=null) {
-            			  try {
-                			  int indexValue = Integer.parseInt(integerValue);
-                			  URI chainPropURI = vf.createURI(propURI.stringValue());
-                			  orderedProperties.put(indexValue, chainPropURI);
-            			  }
-            			  catch (Exception ex){
-            				  // TODO log an error here
-            				  
-            			  }
-            		  }
-            		}
-            	} finally{
-            		if (iter != null){
-            			iter.close();
-            		}
-            	}
-            	List<URI> properties = new ArrayList<URI>();
-            	for (Map.Entry<Integer, URI> entry : orderedProperties.entrySet()){
-            		properties.add(entry.getValue());
-            	}
-            	propertyChainPropertyToChain.put(propertyChainProperty, properties);
+            for (final URI propertyChainProperty : propertyChainPropertiesToBNodes.keySet()){
+                final URI bNode = propertyChainPropertiesToBNodes.get(propertyChainProperty);
+                // query for the list of indexed properties
+                iter = RyaDAOHelper.query(ryaDAO, bNode, vf.createURI("http://www.w3.org/2000/10/swap/list#index"),
+                        null, conf);
+                final TreeMap<Integer, URI> orderedProperties = new TreeMap<>();
+                // TODO refactor this.  Wish I could execute sparql
+                try {
+                    while (iter.hasNext()){
+                        final Statement st = iter.next();
+                        final String indexedElement = st.getObject().stringValue();
+                        log.info(indexedElement);
+                        CloseableIteration<Statement, QueryEvaluationException>  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(st.getObject().stringValue()), RDF.FIRST,
+                                null, conf);
+                        String integerValue = "";
+                        Value anonPropNode = null;
+                        Value propURI = null;
+                        if (iter2 != null){
+                            while (iter2.hasNext()){
+                                final Statement iter2Statement = iter2.next();
+                                integerValue = iter2Statement.getObject().stringValue();
+                                break;
+                            }
+                            iter2.close();
+                        }
+                        iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(st.getObject().stringValue()), RDF.REST,
+                                null, conf);
+                        if (iter2 != null){
+                            while (iter2.hasNext()){
+                                final Statement iter2Statement = iter2.next();
+                                anonPropNode = iter2Statement.getObject();
+                                break;
+                            }
+                            iter2.close();
+                            if (anonPropNode != null){
+                                iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(anonPropNode.stringValue()), RDF.FIRST,
+                                        null, conf);
+                                while (iter2.hasNext()){
+                                    final Statement iter2Statement = iter2.next();
+                                    propURI = iter2Statement.getObject();
+                                    break;
+                                }
+                                iter2.close();
+                            }
+                        }
+                        if (!integerValue.isEmpty() && propURI!=null) {
+                            try {
+                                final int indexValue = Integer.parseInt(integerValue);
+                                final URI chainPropURI = vf.createURI(propURI.stringValue());
+                                orderedProperties.put(indexValue, chainPropURI);
+                            }
+                            catch (final Exception ex){
+                                // TODO log an error here
+
+                            }
+                        }
+                    }
+                } finally{
+                    if (iter != null){
+                        iter.close();
+                    }
+                }
+                final List<URI> properties = new ArrayList<>();
+                for (final Map.Entry<Integer, URI> entry : orderedProperties.entrySet()){
+                    properties.add(entry.getValue());
+                }
+                propertyChainPropertyToChain.put(propertyChainProperty, properties);
             }
-            
+
             // could also be represented as a list of properties (some of which may be blank nodes)
-            for (URI propertyChainProperty : propertyChainPropertiesToBNodes.keySet()){
-            	List<URI> existingChain = propertyChainPropertyToChain.get(propertyChainProperty);
-            	// if we didn't get a chain, try to get it through following the collection
-            	if ((existingChain == null) || existingChain.isEmpty()) {
-            		
-          		  CloseableIteration<Statement, QueryEvaluationException>  iter2 = RyaDAOHelper.query(ryaDAO, propertyChainPropertiesToBNodes.get(propertyChainProperty), RDF.FIRST,
-              			null, conf);
-          		  List<URI> properties = new ArrayList<URI>();
-          		  URI previousBNode = propertyChainPropertiesToBNodes.get(propertyChainProperty);
-            	  if (iter2.hasNext()) {
-            		  Statement iter2Statement = iter2.next();
-            		  Value currentPropValue = iter2Statement.getObject();
-            		  while ((currentPropValue != null) && (!currentPropValue.stringValue().equalsIgnoreCase(RDF.NIL.stringValue()))){
-                		  if (currentPropValue instanceof URI){
-                    		  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(currentPropValue.stringValue()), RDF.FIRST,
-                          			null, conf);
-                			  if (iter2.hasNext()){
-                				  iter2Statement = iter2.next();
-                				  if (iter2Statement.getObject() instanceof URI){
-                					  properties.add((URI)iter2Statement.getObject());
-                				  }
-                			  }
-                			  // otherwise see if there is an inverse declaration
-                			  else {
-                				  iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(currentPropValue.stringValue()), OWL.INVERSEOF,
-                                			null, conf);
-                				  if (iter2.hasNext()){
-                    				  iter2Statement = iter2.next();
-                    				  if (iter2Statement.getObject() instanceof URI){
-                    					  properties.add(new InverseURI((URI)iter2Statement.getObject()));
-                    				  }
-                    			  }
-                			  }
-            				  // get the next prop pointer
-            				  iter2 = RyaDAOHelper.query(ryaDAO, previousBNode, RDF.REST,
-                            			null, conf);
-            				  if (iter2.hasNext()){
-                				  iter2Statement = iter2.next();
-                				  previousBNode = (URI)currentPropValue;
-                				  currentPropValue = iter2Statement.getObject();
-                			  }
-            				  else {
-            					  currentPropValue = null;
-            				  }
-                		  }
-                		  else {
-                		    currentPropValue = null;
-                		  }
-            			  
-            		  }
-                  	propertyChainPropertyToChain.put(propertyChainProperty, properties);
-            	  }
-            	}
+            for (final URI propertyChainProperty : propertyChainPropertiesToBNodes.keySet()){
+                final List<URI> existingChain = propertyChainPropertyToChain.get(propertyChainProperty);
+                // if we didn't get a chain, try to get it through following the collection
+                if ((existingChain == null) || existingChain.isEmpty()) {
+
+                    CloseableIteration<Statement, QueryEvaluationException>  iter2 = RyaDAOHelper.query(ryaDAO, propertyChainPropertiesToBNodes.get(propertyChainProperty), RDF.FIRST,
+                            null, conf);
+                    final List<URI> properties = new ArrayList<>();
+                    URI previousBNode = propertyChainPropertiesToBNodes.get(propertyChainProperty);
+                    if (iter2.hasNext()) {
+                        Statement iter2Statement = iter2.next();
+                        Value currentPropValue = iter2Statement.getObject();
+                        while ((currentPropValue != null) && (!currentPropValue.stringValue().equalsIgnoreCase(RDF.NIL.stringValue()))){
+                            if (currentPropValue instanceof URI){
+                                iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(currentPropValue.stringValue()), RDF.FIRST,
+                                        null, conf);
+                                if (iter2.hasNext()){
+                                    iter2Statement = iter2.next();
+                                    if (iter2Statement.getObject() instanceof URI){
+                                        properties.add((URI)iter2Statement.getObject());
+                                    }
+                                }
+                                // otherwise see if there is an inverse declaration
+                                else {
+                                    iter2 = RyaDAOHelper.query(ryaDAO, vf.createURI(currentPropValue.stringValue()), OWL.INVERSEOF,
+                                            null, conf);
+                                    if (iter2.hasNext()){
+                                        iter2Statement = iter2.next();
+                                        if (iter2Statement.getObject() instanceof URI){
+                                            properties.add(new InverseURI((URI)iter2Statement.getObject()));
+                                        }
+                                    }
+                                }
+                                // get the next prop pointer
+                                iter2 = RyaDAOHelper.query(ryaDAO, previousBNode, RDF.REST,
+                                        null, conf);
+                                if (iter2.hasNext()){
+                                    iter2Statement = iter2.next();
+                                    previousBNode = (URI)currentPropValue;
+                                    currentPropValue = iter2Statement.getObject();
+                                }
+                                else {
+                                    currentPropValue = null;
+                                }
+                            }
+                            else {
+                                currentPropValue = null;
+                            }
+
+                        }
+                        propertyChainPropertyToChain.put(propertyChainProperty, properties);
+                    }
+                }
             }
 
             refreshDomainRange();
 
             refreshPropertyRestrictions();
 
-        } catch (QueryEvaluationException e) {
+        } catch (final QueryEvaluationException e) {
             throw new InferenceEngineException(e);
         }
     }
@@ -396,13 +407,13 @@ public class InferenceEngine {
      * @param edgeName Label that will be given to all added edges
      * @throws QueryEvaluationException
      */
-    private void addPredicateEdges(URI predicate, Direction dir, Graph graph, String edgeName)
+    private void addPredicateEdges(final URI predicate, final Direction dir, final Graph graph, final String edgeName)
             throws QueryEvaluationException {
-        CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO,
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO,
                 null, predicate, null, conf);
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
+                final Statement st = iter.next();
                 if (Direction.OUT.equals(dir) || Direction.BOTH.equals(dir)) {
                     addStatementEdge(graph, edgeName, st);
                 }
@@ -434,15 +445,15 @@ public class InferenceEngine {
      * @throws QueryEvaluationException
      */
     private void refreshDomainRange() throws QueryEvaluationException {
-        Map<URI, Set<URI>> domainByTypePartial = new ConcurrentHashMap<>();
-        Map<URI, Set<URI>> rangeByTypePartial = new ConcurrentHashMap<>();
+        final Map<URI, Set<URI>> domainByTypePartial = new ConcurrentHashMap<>();
+        final Map<URI, Set<URI>> rangeByTypePartial = new ConcurrentHashMap<>();
         // First, populate domain and range based on direct domain/range triples.
         CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, RDFS.DOMAIN, null, conf);
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
-                Resource property = st.getSubject();
-                Value domainType = st.getObject();
+                final Statement st = iter.next();
+                final Resource property = st.getSubject();
+                final Value domainType = st.getObject();
                 if (domainType instanceof URI && property instanceof URI) {
                     if (!domainByTypePartial.containsKey(domainType)) {
                         domainByTypePartial.put((URI) domainType, new HashSet<>());
@@ -458,9 +469,9 @@ public class InferenceEngine {
         iter = RyaDAOHelper.query(ryaDAO, null, RDFS.RANGE, null, conf);
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
-                Resource property = st.getSubject();
-                Value rangeType = st.getObject();
+                final Statement st = iter.next();
+                final Resource property = st.getSubject();
+                final Value rangeType = st.getObject();
                 if (rangeType instanceof URI && property instanceof URI) {
                     if (!rangeByTypePartial.containsKey(rangeType)) {
                         rangeByTypePartial.put((URI) rangeType, new HashSet<>());
@@ -475,26 +486,26 @@ public class InferenceEngine {
         }
         // Then combine with the subclass/subproperty graphs and the inverse property map to compute
         // the closure of domain and range per class.
-        Set<URI> domainRangeTypeSet = new HashSet<>(domainByTypePartial.keySet());
+        final Set<URI> domainRangeTypeSet = new HashSet<>(domainByTypePartial.keySet());
         domainRangeTypeSet.addAll(rangeByTypePartial.keySet());
         // Extend to subproperties: make sure that using a more specific form of a property
         // still triggers its domain/range inferences.
         // Mirror for inverse properties: make sure that using the inverse form of a property
         // triggers the inverse domain/range inferences.
         // These two rules can recursively trigger one another.
-        for (URI domainRangeType : domainRangeTypeSet) {
-            Set<URI> propertiesWithDomain = domainByTypePartial.getOrDefault(domainRangeType, new HashSet<>());
-            Set<URI> propertiesWithRange = rangeByTypePartial.getOrDefault(domainRangeType, new HashSet<>());
+        for (final URI domainRangeType : domainRangeTypeSet) {
+            final Set<URI> propertiesWithDomain = domainByTypePartial.getOrDefault(domainRangeType, new HashSet<>());
+            final Set<URI> propertiesWithRange = rangeByTypePartial.getOrDefault(domainRangeType, new HashSet<>());
             // Since findParents will traverse the subproperty graph and find all indirect
             // subproperties, the subproperty rule does not need to trigger itself directly.
             // And since no more than one inverseOf relationship is stored for any property, the
             // inverse property rule does not need to trigger itself directly. However, each rule
             // can trigger the other, so keep track of how the inferred domains/ranges were
             // discovered so we can apply only those rules that might yield new information.
-            Stack<URI> domainViaSuperProperty  = new Stack<>();
-            Stack<URI> rangeViaSuperProperty  = new Stack<>();
-            Stack<URI> domainViaInverseProperty  = new Stack<>();
-            Stack<URI> rangeViaInverseProperty  = new Stack<>();
+            final Stack<URI> domainViaSuperProperty  = new Stack<>();
+            final Stack<URI> rangeViaSuperProperty  = new Stack<>();
+            final Stack<URI> domainViaInverseProperty  = new Stack<>();
+            final Stack<URI> rangeViaInverseProperty  = new Stack<>();
             // Start with the direct domain/range assertions, which can trigger any rule.
             domainViaSuperProperty.addAll(propertiesWithDomain);
             domainViaInverseProperty.addAll(propertiesWithDomain);
@@ -507,8 +518,8 @@ public class InferenceEngine {
                 // For a type c and property p, if c is a domain of p, then c is the range of any
                 // inverse of p. Would be redundant for properties discovered via inverseOf.
                 while (!domainViaSuperProperty.isEmpty()) {
-                    URI property = domainViaSuperProperty.pop();
-                    URI inverseProperty = findInverseOf(property);
+                    final URI property = domainViaSuperProperty.pop();
+                    final URI inverseProperty = findInverseOf(property);
                     if (inverseProperty != null && propertiesWithRange.add(inverseProperty)) {
                         rangeViaInverseProperty.push(inverseProperty);
                     }
@@ -516,8 +527,8 @@ public class InferenceEngine {
                 // For a type c and property p, if c is a range of p, then c is the domain of any
                 // inverse of p. Would be redundant for properties discovered via inverseOf.
                 while (!rangeViaSuperProperty.isEmpty()) {
-                    URI property = rangeViaSuperProperty.pop();
-                    URI inverseProperty = findInverseOf(property);
+                    final URI property = rangeViaSuperProperty.pop();
+                    final URI inverseProperty = findInverseOf(property);
                     if (inverseProperty != null && propertiesWithDomain.add(inverseProperty)) {
                         domainViaInverseProperty.push(inverseProperty);
                     }
@@ -525,8 +536,8 @@ public class InferenceEngine {
                 // For a type c and property p, if c is a domain of p, then c is also a domain of
                 // p's subproperties. Would be redundant for properties discovered via this rule.
                 while (!domainViaInverseProperty.isEmpty()) {
-                    URI property = domainViaInverseProperty.pop();
-                    Set<URI> subProperties = findParents(subPropertyOfGraph, property);
+                    final URI property = domainViaInverseProperty.pop();
+                    final Set<URI> subProperties = findParents(subPropertyOfGraph, property);
                     subProperties.removeAll(propertiesWithDomain);
                     propertiesWithDomain.addAll(subProperties);
                     domainViaSuperProperty.addAll(subProperties);
@@ -534,8 +545,8 @@ public class InferenceEngine {
                 // For a type c and property p, if c is a range of p, then c is also a range of
                 // p's subproperties. Would be redundant for properties discovered via this rule.
                 while (!rangeViaInverseProperty.isEmpty()) {
-                    URI property = rangeViaInverseProperty.pop();
-                    Set<URI> subProperties = findParents(subPropertyOfGraph, property);
+                    final URI property = rangeViaInverseProperty.pop();
+                    final Set<URI> subProperties = findParents(subPropertyOfGraph, property);
                     subProperties.removeAll(propertiesWithRange);
                     propertiesWithRange.addAll(subProperties);
                     rangeViaSuperProperty.addAll(subProperties);
@@ -551,23 +562,23 @@ public class InferenceEngine {
         // Once all properties have been found for each domain/range class, extend to superclasses:
         // make sure that the consequent of a domain/range inference goes on to apply any more
         // general classes as well.
-        for (URI subtype : domainRangeTypeSet) {
-            Set<URI> supertypes = findChildren(subClassOfGraph, subtype);
-            Set<URI> propertiesWithDomain = domainByTypePartial.getOrDefault(subtype, new HashSet<>());
-            Set<URI> propertiesWithRange = rangeByTypePartial.getOrDefault(subtype, new HashSet<>());
-            for (URI supertype : supertypes) {
+        for (final URI subtype : domainRangeTypeSet) {
+            final Set<URI> supertypes = getSuperClasses(subtype);
+            final Set<URI> propertiesWithDomain = domainByTypePartial.getOrDefault(subtype, new HashSet<>());
+            final Set<URI> propertiesWithRange = rangeByTypePartial.getOrDefault(subtype, new HashSet<>());
+            for (final URI supertype : supertypes) {
                 // For a property p and its domain c: all of c's superclasses are also domains of p.
                 if (!propertiesWithDomain.isEmpty() && !domainByTypePartial.containsKey(supertype)) {
                     domainByTypePartial.put(supertype, new HashSet<>());
                 }
-                for (URI property : propertiesWithDomain) {
+                for (final URI property : propertiesWithDomain) {
                     domainByTypePartial.get(supertype).add(property);
                 }
                 // For a property p and its range c: all of c's superclasses are also ranges of p.
                 if (!propertiesWithRange.isEmpty() && !rangeByTypePartial.containsKey(supertype)) {
                     rangeByTypePartial.put(supertype, new HashSet<>());
                 }
-                for (URI property : propertiesWithRange) {
+                for (final URI property : propertiesWithRange) {
                     rangeByTypePartial.get(supertype).add(property);
                 }
             }
@@ -578,11 +589,11 @@ public class InferenceEngine {
 
     private void refreshPropertyRestrictions() throws QueryEvaluationException {
         // Get a set of all property restrictions of any type
-        CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.ONPROPERTY, null, conf);
-        Map<Resource, URI> restrictions = new HashMap<>();
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.ONPROPERTY, null, conf);
+        final Map<Resource, URI> restrictions = new HashMap<>();
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
+                final Statement st = iter.next();
                 restrictions.put(st.getSubject(), (URI) st.getObject());
             }
         } finally {
@@ -595,17 +606,17 @@ public class InferenceEngine {
         refreshAllValuesFromRestrictions(restrictions);
     }
 
-    private void refreshHasValueRestrictions(Map<Resource, URI> restrictions) throws QueryEvaluationException {
+    private void refreshHasValueRestrictions(final Map<Resource, URI> restrictions) throws QueryEvaluationException {
         hasValueByType = new HashMap<>();
         hasValueByProperty = new HashMap<>();
-        CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.HASVALUE, null, conf);
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.HASVALUE, null, conf);
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
-                Resource restrictionClass = st.getSubject();
+                final Statement st = iter.next();
+                final Resource restrictionClass = st.getSubject();
                 if (restrictions.containsKey(restrictionClass)) {
-                    URI property = restrictions.get(restrictionClass);
-                    Value value = st.getObject();
+                    final URI property = restrictions.get(restrictionClass);
+                    final Value value = st.getObject();
                     if (!hasValueByType.containsKey(restrictionClass)) {
                         hasValueByType.put(restrictionClass, new HashMap<>());
                     }
@@ -623,22 +634,22 @@ public class InferenceEngine {
         }
     }
 
-    private void refreshAllValuesFromRestrictions(Map<Resource, URI> restrictions) throws QueryEvaluationException {
+    private void refreshAllValuesFromRestrictions(final Map<Resource, URI> restrictions) throws QueryEvaluationException {
         allValuesFromByValueType = new HashMap<>();
-        CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.ALLVALUESFROM, null, conf);
+        final CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.ALLVALUESFROM, null, conf);
         try {
             while (iter.hasNext()) {
-                Statement st = iter.next();
+                final Statement st = iter.next();
                 if (restrictions.containsKey(st.getSubject()) && st.getObject() instanceof URI) {
-                    URI property = restrictions.get(st.getSubject());
-                    URI valueClass = (URI) st.getObject();
+                    final URI property = restrictions.get(st.getSubject());
+                    final URI valueClass = (URI) st.getObject();
                     // Should also be triggered by subclasses of the property restriction
-                    Set<Resource> restrictionClasses = new HashSet<>();
+                    final Set<Resource> restrictionClasses = new HashSet<>();
                     restrictionClasses.add(st.getSubject());
                     if (st.getSubject() instanceof URI) {
-                        restrictionClasses.addAll(findParents(subClassOfGraph, (URI) st.getSubject()));
+                        restrictionClasses.addAll(getSubClasses((URI) st.getSubject()));
                     }
-                    for (Resource restrictionClass : restrictionClasses) {
+                    for (final Resource restrictionClass : restrictionClasses) {
                         if (!allValuesFromByValueType.containsKey(valueClass)) {
                             allValuesFromByValueType.put(valueClass, new HashMap<>());
                         }
@@ -653,136 +664,356 @@ public class InferenceEngine {
         }
     }
 
-    private static Vertex getVertex(Graph graph, Object id) {
-        Iterator<Vertex> it = graph.vertices(id.toString());
+    private void refreshIntersectionOf() throws QueryEvaluationException {
+        final Map<Resource, List<Set<Resource>>> intersectionsProp = new HashMap<>();
+
+        // First query for all the owl:intersectionOf's.
+        // If we have the following intersectionOf:
+        // :A owl:intersectionOf[:B, :C]
+        // It will be represented by triples following a pattern similar to:
+        // <:A> owl:intersectionOf _:bnode1 .
+        //  _:bnode1 rdf:first <:B> .
+        //  _:bnode1 rdf:rest _:bnode2 .
+        // _:bnode2 rdf:first <:C> .
+        // _:bnode2 rdf:rest rdf:nil .
+        ryaDaoQueryWrapper.queryAll(null, OWL.INTERSECTIONOF, null, new RDFHandlerBase() {
+            @Override
+            public void handleStatement(final Statement statement) throws RDFHandlerException {
+                final Resource type = statement.getSubject();
+                // head will point to a type that is part of the intersection.
+                final URI head = (URI) statement.getObject();
+                if (!intersectionsProp.containsKey(type)) {
+                    intersectionsProp.put(type, new ArrayList<Set<Resource>>());
+                }
+
+                // head should point to a list of items that forms the
+                // intersection.
+                try {
+                    final Set<Resource> intersection = new LinkedHashSet<>(getList(head));
+                    if (!intersection.isEmpty()) {
+                        // Add this intersection for this type. There may be more
+                        // intersections for this type so each type has a list of
+                        // intersection sets.
+                        intersectionsProp.get(type).add(intersection);
+                    }
+                } catch (final QueryEvaluationException e) {
+                    throw new RDFHandlerException("Error getting intersection list.", e);
+                }
+            }
+        });
+
+        intersections.clear();
+        for (final Entry<Resource, List<Set<Resource>>> entry : intersectionsProp.entrySet()) {
+            final Resource type = entry.getKey();
+            final List<Set<Resource>> intersectionList = entry.getValue();
+            final Set<Resource> otherTypes = new HashSet<>();
+            // Combine all of a type's intersections together.
+            for (final Set<Resource> intersection : intersectionList) {
+                otherTypes.addAll(intersection);
+            }
+            for (final Resource other : otherTypes) {
+                // :A intersectionOf[:B, :C] implies that
+                // :A subclassOf :B
+                // :A subclassOf :C
+                // So add each type that's part of the intersection to the
+                // subClassOf graph.
+                addSubClassOf(type, other);
+                for (final Set<Resource> intersection : intersectionList) {
+                    if (!intersection.contains(other)) {
+                        addIntersection(intersection, other);
+                    }
+                }
+            }
+            for (final Set<Resource> intersection : intersectionList) {
+                addIntersection(intersection, type);
+            }
+        }
+        for (final Entry<Resource, List<Set<Resource>>> entry : intersectionsProp.entrySet()) {
+            final Resource type = entry.getKey();
+            final List<Set<Resource>> intersectionList = entry.getValue();
+
+            final Set<URI> superClasses = getSuperClasses((URI) type);
+            for (final URI superClass : superClasses) {
+                // Add intersections to super classes if applicable.
+                // IF:
+                // :A intersectionOf[:B, :C]
+                // AND
+                // :A subclassOf :D
+                // Then we can infer:
+                // intersectionOf[:B, :C] subclassOf :D
+                for (final Set<Resource> intersection : intersectionList) {
+                    addIntersection(intersection, superClass);
+                }
+            }
+            // Check if other keys have any of the same intersections and infer
+            // the same subclass logic to them that we know from the current
+            // type. Propagating up through all the superclasses.
+            for (final Set<Resource> intersection : intersectionList) {
+                final Set<Resource> otherKeys = Sets.newHashSet(intersectionsProp.keySet());
+                otherKeys.remove(type);
+                for (final Resource otherKey : otherKeys) {
+                    if (intersectionsProp.get(otherKey).contains(intersection)) {
+                        addSubClassOf(otherKey, type);
+                        addSubClassOf(type, otherKey);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Queries for all items that are in a list of the form:
+     * <pre>
+     *     <:A> ?x _:bnode1 .
+     *     _:bnode1 rdf:first <:B> .
+     *     _:bnode1 rdf:rest _:bnode2 .
+     *     _:bnode2 rdf:first <:C> .
+     *     _:bnode2 rdf:rest rdf:nil .
+     * </pre>
+     * Where {@code :_bnode1} represents the first item in the list and
+     * {@code ?x} is some restriction on {@code <:A>}. This will return the
+     * list of resources, {@code [<:B>, <:C>]}.
+     * @param firstItem the first item in the list.
+     * @return the {@link List} of {@link Resource}s.
+     * @throws QueryEvaluationException
+     */
+    private List<Resource> getList(final URI firstItem) throws QueryEvaluationException {
+        URI head = firstItem;
+        final List<Resource> list = new ArrayList<>();
+        // Go through and find all bnodes that are part of the defined list.
+        while (!RDF.NIL.equals(head)) {
+            // rdf.first will point to a type item that is in the list.
+            ryaDaoQueryWrapper.queryFirst(head, RDF.FIRST, null, new RDFHandlerBase() {
+                @Override
+                public void handleStatement(final Statement statement) throws RDFHandlerException {
+                    // The object found in the query represents a type
+                    // that should be included in the list.
+                    final URI object = (URI) statement.getObject();
+                    list.add(object);
+                }
+            });
+            final MutableObject<URI> headHolder = new MutableObject<>();
+            // rdf.rest will point to the next bnode that's part of the list.
+            ryaDaoQueryWrapper.queryFirst(head, RDF.REST, null, new RDFHandlerBase() {
+                @Override
+                public void handleStatement(final Statement statement) throws RDFHandlerException {
+                    // This object is the next bnode head to look for.
+                    final URI object = (URI) statement.getObject();
+                    headHolder.setValue(object);
+                }
+            });
+            // As long as we get a new head there are more bnodes that are part
+            // of the list. Keep going until we reach rdf.nil.
+            if (headHolder.getValue() != null) {
+                head = headHolder.getValue();
+            } else {
+                head = RDF.NIL;
+            }
+        }
+        return list;
+    }
+
+    private void addSubClassOf(final Resource s, final Resource o) {
+        final Statement statement = new StatementImpl(s, RDFS.SUBCLASSOF, o);
+        final String edgeName = RDFS.SUBCLASSOF.stringValue();
+        addStatementEdge(subClassOfGraph, edgeName, statement);
+    }
+
+    private void addIntersection(final Set<Resource> intersection, final Resource type) {
+        if (type != null && intersection != null && !intersection.isEmpty()) {
+            List<Set<Resource>> intersectionList = intersections.get(type);
+            if (intersectionList == null) {
+                intersectionList = new ArrayList<>();
+            }
+            if (!intersectionList.contains(intersection)) {
+                intersectionList.add(intersection);
+            }
+            intersections.put(type, intersectionList);
+        }
+    }
+
+    private static Vertex getVertex(final Graph graph, final Object id) {
+        final Iterator<Vertex> it = graph.vertices(id.toString());
         if (it.hasNext()) {
             return it.next();
         }
         return null;
     }
 
-    private void addStatementEdge(Graph graph, String edgeName, Statement st) {
-        Resource subj = st.getSubject();
+    private static void addStatementEdge(final Graph graph, final String edgeName, final Statement st) {
+        final Resource subj = st.getSubject();
         Vertex a = getVertex(graph, subj);
         if (a == null) {
             a = graph.addVertex(T.id, subj.toString());
             a.property(URI_PROP, subj);
         }
-        Value obj = st.getObject();
+        final Value obj = st.getObject();
         Vertex b = getVertex(graph, obj);
         if (b == null) {
             b = graph.addVertex(T.id, obj.toString());
             b.property(URI_PROP, obj);
         }
         a.addEdge(edgeName, b);
-   }
+    }
+
+    /**
+     * Returns all super class types of the specified type based on the
+     * internal subclass graph.
+     * @param type the type {@link URI} to find super classes for.
+     * @return the {@link Set} of {@link URI} types that are super classes types
+     * of the specified {@code type}. Returns an empty set if nothing was found.
+     */
+    public Set<URI> getSuperClasses(final URI type) {
+        return findChildren(subClassOfGraph, type);
+    }
+
+    /**
+     * Returns all sub class types of the specified type based on the
+     * internal subclass graph.
+     * @param type the type {@link URI} to find sub classes for.
+     * @return the {@link Set} of {@link URI} types that are sub classes types
+     * of the specified {@code type}. Returns an empty set if nothing was found.
+     */
+    public Set<URI> getSubClasses(final URI type) {
+        return findParents(subClassOfGraph, type);
+    }
+
+    public static Set<URI> findParents(final Graph graph, final URI vertexId) {
+        return findParents(graph, vertexId, true);
+    }
+
+    public static Set<URI> findParents(final Graph graph, final URI vertexId, final boolean isRecursive) {
+        return findConnected(graph, vertexId, Direction.IN, isRecursive);
+    }
 
-    public Set<URI> findParents(Graph graph, URI vertexId) {
-        return findConnected(graph, vertexId, Direction.IN);
+    public static Set<URI> findChildren(final Graph graph, final URI vertexId) {
+        return findChildren(graph, vertexId, true);
     }
 
-    public Set<URI> findChildren(Graph graph, URI vertexId) {
-        return findConnected(graph, vertexId, Direction.OUT);
+    public static Set<URI> findChildren(final Graph graph, final URI vertexId, final boolean isRecursive) {
+        return findConnected(graph, vertexId, Direction.OUT, isRecursive);
     }
 
-    private Set<URI> findConnected(Graph graph, URI vertexId, Direction traversal) {
-        Set<URI> connected = new HashSet<>();
+    private static Set<URI> findConnected(final Graph graph, final URI vertexId, final Direction traversal, final boolean isRecursive) {
+        final Set<URI> connected = new HashSet<>();
         if (graph == null) {
             return connected;
         }
-        Vertex v = getVertex(graph, vertexId);
+        final Vertex v = getVertex(graph, vertexId);
         if (v == null) {
             return connected;
         }
-        addConnected(v, connected, traversal);
+        addConnected(v, connected, traversal, isRecursive);
         return connected;
     }
 
-    private static void addConnected(Vertex v, Set<URI> connected, Direction traversal) {
+    private static void addConnected(final Vertex v, final Set<URI> connected, final Direction traversal, final boolean isRecursive) {
         v.edges(traversal).forEachRemaining(edge -> {
-            Vertex ov = edge.vertices(traversal.opposite()).next();
-            Object o = ov.property(URI_PROP).value();
+            final Vertex ov = edge.vertices(traversal.opposite()).next();
+            final Object o = ov.property(URI_PROP).value();
             if (o != null && o instanceof URI) {
-                boolean contains = connected.contains(o);
+                final boolean contains = connected.contains(o);
                 if (!contains) {
                     connected.add((URI) o);
-                    addConnected(ov, connected, traversal);
+                    if (isRecursive) {
+                        addConnected(ov, connected, traversal, isRecursive);
+                    }
                 }
             }
         });
     }
 
-    public boolean isSymmetricProperty(URI prop) {
+    public boolean isSymmetricProperty(final URI prop) {
         return (symmetricPropertySet != null) && symmetricPropertySet.contains(prop);
     }
 
-    public URI findInverseOf(URI prop) {
+    public URI findInverseOf(final URI prop) {
         return (inverseOfMap != null) ? inverseOfMap.get(prop) : (null);
     }
 
-    public boolean isTransitiveProperty(URI prop) {
+    public boolean isTransitiveProperty(final URI prop) {
         return (transitivePropertySet != null) && transitivePropertySet.contains(prop);
     }
 
     /**
      * TODO: This chaining can be slow at query execution. the other option is to perform this in the query itself, but that will be constrained to how many levels we decide to go
      */
-    public Set<Statement> findTransitiveProperty(Resource subj, URI prop, Value obj, Resource... contxts) throws InferenceEngineException {
+    public Set<Statement> findTransitiveProperty(final Resource subj, final URI prop, final Value obj, final Resource... contxts) throws InferenceEngineException {
         if (transitivePropertySet.contains(prop)) {
-            Set<Statement> sts = new HashSet();
-            boolean goUp = subj == null;
+            final Set<Statement> sts = new HashSet<>();
+            final boolean goUp = subj == null;
             chainTransitiveProperty(subj, prop, obj, (goUp) ? (obj) : (subj), sts, goUp, contxts);
             return sts;
-        } else
+        } else {
             return null;
+        }
     }
 
     /**
      * TODO: This chaining can be slow at query execution. the other option is to perform this in the query itself, but that will be constrained to how many levels we decide to go
      */
-    public Set<Resource> findSameAs(Resource value, Resource... contxts) throws InferenceEngineException{
-		Set<Resource> sameAs = new HashSet<Resource>();
-		sameAs.add(value);
-		findSameAsChaining(value, sameAs, contxts);
-		return sameAs;
+    public Set<Resource> findSameAs(final Resource value, final Resource... contxts) throws InferenceEngineException{
+        final Set<Resource> sameAs = new HashSet<>();
+        sameAs.add(value);
+        findSameAsChaining(value, sameAs, contxts);
+        return sameAs;
+    }
+
+    public CloseableIteration<Statement, QueryEvaluationException> queryDao(final Resource subject, final URI predicate, final Value object, final Resource... contexts) throws QueryEvaluationException {
+        return RyaDAOHelper.query(ryaDAO, subject, predicate, object, conf, contexts);
     }
 
     /**
      * TODO: This chaining can be slow at query execution. the other option is to perform this in the query itself, but that will be constrained to how many levels we decide to go
      */
-    public void findSameAsChaining(Resource subj, Set<Resource> currentSameAs, Resource[] contxts) throws InferenceEngineException{
+    public void findSameAsChaining(final Resource subj, final Set<Resource> currentSameAs, final Resource[] contxts) throws InferenceEngineException{
+        CloseableIteration<Statement, QueryEvaluationException> subjIter = null;
+        CloseableIteration<Statement, QueryEvaluationException> objIter = null;
         try {
-			CloseableIteration<Statement, QueryEvaluationException> subjIter = RyaDAOHelper.query(ryaDAO, subj, OWL.SAMEAS, null, conf, contxts);
-			while (subjIter.hasNext()){
-				Statement st = subjIter.next();
-				if (!currentSameAs.contains(st.getObject())){
-					Resource castedObj = (Resource) st.getObject();
-					currentSameAs.add(castedObj);
-					findSameAsChaining(castedObj, currentSameAs, contxts);
-				}
-			}
-			subjIter.close();
-			CloseableIteration<Statement, QueryEvaluationException> objIter = RyaDAOHelper.query(ryaDAO, null, OWL.SAMEAS, subj, conf, contxts);
-			while (objIter.hasNext()){
-				Statement st = objIter.next();
-				if (!currentSameAs.contains(st.getSubject())){
-					Resource sameAsSubj = st.getSubject();
-					currentSameAs.add(sameAsSubj);
-					findSameAsChaining(sameAsSubj, currentSameAs, contxts);
-				}
-			}
-			objIter.close();
-		} catch (QueryEvaluationException e) {
-			throw new InferenceEngineException(e);
-		}
-
+            subjIter = queryDao(subj, OWL.SAMEAS, null, contxts);
+            while (subjIter.hasNext()){
+                final Statement st = subjIter.next();
+                if (!currentSameAs.contains(st.getObject())){
+                    final Resource castedObj = (Resource) st.getObject();
+                    currentSameAs.add(castedObj);
+                    findSameAsChaining(castedObj, currentSameAs, contxts);
+                }
+            }
+            objIter = queryDao(null, OWL.SAMEAS, subj, contxts);
+            while (objIter.hasNext()){
+                final Statement st = objIter.next();
+                if (!currentSameAs.contains(st.getSubject())){
+                    final Resource sameAsSubj = st.getSubject();
+                    currentSameAs.add(sameAsSubj);
+                    findSameAsChaining(sameAsSubj, currentSameAs, contxts);
+                }
+            }
+        } catch (final QueryEvaluationException e) {
+            throw new InferenceEngineException(e);
+        } finally {
+            if (subjIter != null) {
+                try {
+                    subjIter.close();
+                } catch (final QueryEvaluationException e) {
+                    throw new InferenceEngineException("Error while closing \"same as chaining\" statement subject iterator.", e);
+                }
+            }
+            if (objIter != null) {
+                try {
+                    objIter.close();
+                } catch (final QueryEvaluationException e) {
+                    throw new InferenceEngineException("Error while closing \"same as chaining\" statement object iterator.", e);
+                }
+            }
+        }
     }
 
-    protected void chainTransitiveProperty(Resource subj, URI prop, Value obj, Value core, Set<Statement> sts, boolean goUp, Resource[] contxts) throws InferenceEngineException {
+    protected void chainTransitiveProperty(final Resource subj, final URI prop, final Value obj, final Value core, final Set<Statement> sts, final boolean goUp, final Resource[] contxts) throws InferenceEngineException {
+        CloseableIteration<Statement, QueryEvaluationException> iter = null;
         try {
-            CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, subj, prop, obj, conf, contxts);
+            iter = queryDao(subj, prop, obj, contxts);
             while (iter.hasNext()) {
-                Statement st = iter.next();
+                final Statement st = iter.next();
                 sts.add(new StatementImpl((goUp) ? (st.getSubject()) : (Resource) (core), prop, (!goUp) ? (st.getObject()) : (core)));
                 if (goUp) {
                     chainTransitiveProperty(null, prop, st.getSubject(), core, sts, goUp, contxts);
@@ -790,9 +1021,16 @@ public class InferenceEngine {
                     chainTransitiveProperty((Resource) st.getObject(), prop, null, core, sts, goUp, contxts);
                 }
             }
-            iter.close();
-        } catch (QueryEvaluationException e) {
+        } catch (final QueryEvaluationException e) {
             throw new InferenceEngineException(e);
+        } finally {
+            if (iter != null) {
+                try {
+                    iter.close();
+                } catch (final QueryEvaluationException e) {
+                    throw new InferenceEngineException("Error while closing \"chain transitive\" property statement iterator.", e);
+                }
+            }
         }
     }
 
@@ -800,23 +1038,24 @@ public class InferenceEngine {
         return initialized;
     }
 
-    public void setInitialized(boolean initialized) {
+    public void setInitialized(final boolean initialized) {
         this.initialized = initialized;
     }
 
-    public RyaDAO getRyaDAO() {
+    public RyaDAO<?> getRyaDAO() {
         return ryaDAO;
     }
 
-    public void setRyaDAO(RyaDAO ryaDAO) {
+    public void setRyaDAO(final RyaDAO<?> ryaDAO) {
         this.ryaDAO = ryaDAO;
+        this.ryaDaoQueryWrapper = new RyaDaoQueryWrapper(ryaDAO);
     }
 
     public RdfCloudTripleStoreConfiguration getConf() {
         return conf;
     }
 
-    public void setConf(RdfCloudTripleStoreConfiguration conf) {
+    public void setConf(final RdfCloudTripleStoreConfiguration conf) {
         this.conf = conf;
     }
 
@@ -828,10 +1067,10 @@ public class InferenceEngine {
         return propertyChainPropertyToChain;
     }
 
-    public List<URI> getPropertyChain(URI chainProp) {
-    	if (propertyChainPropertyToChain.containsKey(chainProp)){
-    		return propertyChainPropertyToChain.get(chainProp);
-    	}
+    public List<URI> getPropertyChain(final URI chainProp) {
+        if (propertyChainPropertyToChain.containsKey(chainProp)){
+            return propertyChainPropertyToChain.get(chainProp);
+        }
         return new ArrayList<URI>();
     }
 
@@ -843,7 +1082,7 @@ public class InferenceEngine {
         return refreshGraphSchedule;
     }
 
-    public void setRefreshGraphSchedule(long refreshGraphSchedule) {
+    public void setRefreshGraphSchedule(final long refreshGraphSchedule) {
         this.refreshGraphSchedule = refreshGraphSchedule;
     }
 
@@ -851,7 +1090,7 @@ public class InferenceEngine {
         return symmetricPropertySet;
     }
 
-    public void setSymmetricPropertySet(Set<URI> symmetricPropertySet) {
+    public void setSymmetricPropertySet(final Set<URI> symmetricPropertySet) {
         this.symmetricPropertySet = symmetricPropertySet;
     }
 
@@ -859,7 +1098,7 @@ public class InferenceEngine {
         return inverseOfMap;
     }
 
-    public void setInverseOfMap(Map<URI, URI> inverseOfMap) {
+    public void setInverseOfMap(final Map<URI, URI> inverseOfMap) {
         this.inverseOfMap = inverseOfMap;
     }
 
@@ -867,7 +1106,7 @@ public class InferenceEngine {
         return transitivePropertySet;
     }
 
-    public void setTransitivePropertySet(Set<URI> transitivePropertySet) {
+    public void setTransitivePropertySet(final Set<URI> transitivePropertySet) {
         this.transitivePropertySet = transitivePropertySet;
     }
 
@@ -875,7 +1114,7 @@ public class InferenceEngine {
         return schedule;
     }
 
-    public void setSchedule(boolean schedule) {
+    public void setSchedule(final boolean schedule) {
         this.schedule = schedule;
     }
 
@@ -889,17 +1128,17 @@ public class InferenceEngine {
      * @return For each relevant property, a set of values such that whenever a resource has that
      *      value for that property, it is implied to belong to the type.
      */
-    public Map<URI, Set<Value>> getHasValueByType(Resource type) {
-        Map<URI, Set<Value>> implications = new HashMap<>();
+    public Map<URI, Set<Value>> getHasValueByType(final Resource type) {
+        final Map<URI, Set<Value>> implications = new HashMap<>();
         if (hasValueByType != null) {
-            Set<Resource> types = new HashSet<>();
+            final Set<Resource> types = new HashSet<>();
             types.add(type);
             if (type instanceof URI) {
-                types.addAll(findParents(subClassOfGraph, (URI) type));
+                types.addAll(getSubClasses((URI) type));
             }
-            for (Resource relevantType : types) {
+            for (final Resource relevantType : types) {
                 if (hasValueByType.containsKey(relevantType)) {
-                    for (Map.Entry<URI, Value> propertyToValue : hasValueByType.get(relevantType).entrySet()) {
+                    for (final Map.Entry<URI, Value> propertyToValue : hasValueByType.get(relevantType).entrySet()) {
                         if (!implications.containsKey(propertyToValue.getKey())) {
                             implications.put(propertyToValue.getKey(), new HashSet<>());
                         }
@@ -922,17 +1161,17 @@ public class InferenceEngine {
      * @return A mapping from type (URIs or bnodes) to the set of any values that belonging to that
      *      type implies.
      */
-    public Map<Resource, Set<Value>> getHasValueByProperty(URI property) {
-        Map<Resource, Set<Value>> implications = new HashMap<>();
+    public Map<Resource, Set<Value>> getHasValueByProperty(final URI property) {
+        final Map<Resource, Set<Value>> implications = new HashMap<>();
         if (hasValueByProperty != null && hasValueByProperty.containsKey(property)) {
-            for (Map.Entry<Resource, Value> typeToValue : hasValueByProperty.get(property).entrySet()) {
-                Resource type = typeToValue.getKey();
+            for (final Map.Entry<Resource, Value> typeToValue : hasValueByProperty.get(property).entrySet()) {
+                final Resource type = typeToValue.getKey();
                 if (!implications.containsKey(type)) {
                     implications.put(type, new HashSet<>());
                 }
                 implications.get(type).add(typeToValue.getValue());
                 if (type instanceof URI) {
-                    for (URI subtype : findParents(subClassOfGraph, (URI) type)) {
+                    for (final URI subtype : getSubClasses((URI) type)) {
                         if (!implications.containsKey(subtype)) {
                             implications.put(subtype, new HashSet<>());
                         }
@@ -954,8 +1193,8 @@ public class InferenceEngine {
      * @return The set of properties with domain of that type, meaning that any triple whose
      *      predicate belongs to that set implies that the triple's subject belongs to the type.
      */
-    public Set<URI> getPropertiesWithDomain(URI domainType) {
-        Set<URI> properties = new HashSet<>();
+    public Set<URI> getPropertiesWithDomain(final URI domainType) {
+        final Set<URI> properties = new HashSet<>();
         if (domainByType.containsKey(domainType)) {
             properties.addAll(domainByType.get(domainType));
         }
@@ -972,8 +1211,8 @@ public class InferenceEngine {
      * @return The set of properties with range of that type, meaning that any triple whose
      *      predicate belongs to that set implies that the triple's object belongs to the type.
      */
-    public Set<URI> getPropertiesWithRange(URI rangeType) {
-        Set<URI> properties = new HashSet<>();
+    public Set<URI> getPropertiesWithRange(final URI rangeType) {
+        final Set<URI> properties = new HashSet<>();
         if (rangeByType.containsKey(rangeType)) {
             properties.addAll(rangeByType.get(rangeType));
         }
@@ -996,23 +1235,23 @@ public class InferenceEngine {
      *      subproperties) such that for any individual which belongs to the subject type, all
      *      values it has for any of those properties belong to the value type.
      */
-    public Map<Resource, Set<URI>> getAllValuesFromByValueType(Resource valueType) {
-        Map<Resource, Set<URI>> implications = new HashMap<>();
+    public Map<Resource, Set<URI>> getAllValuesFromByValueType(final Resource valueType) {
+        final Map<Resource, Set<URI>> implications = new HashMap<>();
         if (allValuesFromByValueType != null) {
             // Check for any subtypes which would in turn imply the value type
-            HashSet<Resource> valueTypes = new HashSet<>();
+            final HashSet<Resource> valueTypes = new HashSet<>();
             valueTypes.add(valueType);
             if (valueType instanceof URI) {
-                valueTypes.addAll(findParents(subClassOfGraph, (URI) valueType));
+                valueTypes.addAll(getSubClasses((URI) valueType));
             }
-            for (Resource valueSubType : valueTypes) {
+            for (final Resource valueSubType : valueTypes) {
                 if (allValuesFromByValueType.containsKey(valueSubType)) {
-                    Map<Resource, URI> restrictionToProperty = allValuesFromByValueType.get(valueSubType);
-                    for (Resource restrictionType : restrictionToProperty.keySet()) {
+                    final Map<Resource, URI> restrictionToProperty = allValuesFromByValueType.get(valueSubType);
+                    for (final Resource restrictionType : restrictionToProperty.keySet()) {
                         if (!implications.containsKey(restrictionType)) {
                             implications.put(restrictionType, new HashSet<>());
                         }
-                        URI property = restrictionToProperty.get(restrictionType);
+                        final URI property = restrictionToProperty.get(restrictionType);
                         implications.get(restrictionType).add(property);
                         // Also add subproperties that would in turn imply the property
                         implications.get(restrictionType).addAll(findParents(subPropertyOfGraph, property));
@@ -1022,4 +1261,24 @@ public class InferenceEngine {
         }
         return implications;
     }
+
+    /**
+     * For a given type, return all sets of types such that owl:intersectionOf
+     * restrictions on those properties could imply this type.  A type can have
+     * multiple intersections and each intersection is a set of types so a list
+     * of all the type sets is returned.
+     * @param type The type (URI or bnode) to check against the known
+     * intersections.
+     * @return A {@link List} of {@link Resource} type {@link Set}s that
+     * represents all the known intersections that imply the specified type.
+     * {@code null} is returned if no intersections were found for the specified
+     * type.
+     */
+    public List<Set<Resource>> getIntersectionsImplying(final Resource type) {
+        if (intersections != null) {
+            final List<Set<Resource>> intersectionList = intersections.get(type);
+            return intersectionList;
+        }
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngineException.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngineException.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngineException.java
index 45bdfd7..af1805d 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngineException.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngineException.java
@@ -8,9 +8,9 @@ package org.apache.rya.rdftriplestore.inference;
  * 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
@@ -26,18 +26,20 @@ package org.apache.rya.rdftriplestore.inference;
  * Time: 11:03 AM
  */
 public class InferenceEngineException extends Exception {
+    private static final long serialVersionUID = 1L;
+
     public InferenceEngineException() {
     }
 
-    public InferenceEngineException(String s) {
+    public InferenceEngineException(final String s) {
         super(s);
     }
 
-    public InferenceEngineException(String s, Throwable throwable) {
+    public InferenceEngineException(final String s, final Throwable throwable) {
         super(s, throwable);
     }
 
-    public InferenceEngineException(Throwable throwable) {
+    public InferenceEngineException(final Throwable throwable) {
         super(throwable);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitor.java
new file mode 100644
index 0000000..b4853c0
--- /dev/null
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/IntersectionOfVisitor.java
@@ -0,0 +1,210 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.log4j.Logger;
+import org.apache.rya.api.RdfCloudTripleStoreConfiguration;
+import org.openrdf.model.Resource;
+import org.openrdf.model.URI;
+import org.openrdf.model.vocabulary.RDF;
+import org.openrdf.query.algebra.StatementPattern;
+import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.Union;
+import org.openrdf.query.algebra.Var;
+
+/**
+ * Visitor for handling owl:intersectionOf inferencing on a node.
+ */
+public class IntersectionOfVisitor extends AbstractInferVisitor {
+    private static final Logger log = Logger.getLogger(IntersectionOfVisitor.class);
+
+    /**
+     * Creates a new instance of {@link IntersectionOfVisitor}.
+     * @param conf the {@link RdfCloudeTripleStoreConfiguration}.
+     * @param inferenceEngine the {@link InferenceEngine}.
+     */
+    public IntersectionOfVisitor(final RdfCloudTripleStoreConfiguration conf, final InferenceEngine inferenceEngine) {
+        super(conf, inferenceEngine);
+        include = conf.isInferIntersectionOf();
+    }
+
+    @Override
+    protected void meetSP(final StatementPattern node) throws Exception {
+        final StatementPattern currentNode = node.clone();
+        final Var subVar = node.getSubjectVar();
+        final Var predVar = node.getPredicateVar();
+        final Var objVar = node.getObjectVar();
+        final Var conVar = node.getContextVar();
+        if (predVar != null && objVar != null && objVar.getValue() != null && RDF.TYPE.equals(predVar.getValue()) && !EXPANDED.equals(conVar)) {
+            final List<Set<Resource>> intersections = inferenceEngine.getIntersectionsImplying((URI) objVar.getValue());
+            if (intersections != null && !intersections.isEmpty()) {
+                final List<TupleExpr> joins = new ArrayList<>();
+                for (final Set<Resource> intersection : intersections) {
+                    final Set<Resource> sortedIntersection = new TreeSet<>(new ResourceComparator());
+                    sortedIntersection.addAll(intersection);
+
+                    // Create a join tree of all statement patterns in the
+                    // current intersection.
+                    final TupleExpr joinTree = createJoinTree(new ArrayList<>(sortedIntersection), subVar, conVar);
+                    if (joinTree != null) {
+                        joins.add(joinTree);
+                    }
+                }
+
+                if (!joins.isEmpty()) {
+                    // Combine all the intersection join trees for the type
+                    // together into a union tree.  This will be a join tree if
+                    // only one intersection exists.
+                    final TupleExpr unionTree = createUnionTree(joins);
+                    // Union the above union tree of intersections with the
+                    // original node.
+                    final Union union = new InferUnion(unionTree, currentNode);
+                    node.replaceWith(union);
+                    log.trace("Replacing node with inferred intersection union: " + union);
+                }
+            }
+        }
+    }
+
+    /**
+     * Recursively creates a {@link TupleExpr} tree comprised of
+     * {@link InferJoin}s and {@link StatementPattern}s. The left arg is a
+     * {@link StatementPattern} and the right arg is either a
+     * {@link StatementPattern} if it's the final element or a nested
+     * {@link InferJoin}.<p>
+     * A list of {@code [:A, :B, :C, :D, :E]} with type {@code ?x} returns:
+     * <pre>
+     * InferJoin(
+     *     StatementPattern(?x, rdf:type, :A),
+     *     InferJoin(
+     *         StatementPattern(?x, rdf:type, :B),
+     *         InferJoin(
+     *             StatementPattern(?x, rdf:type, :C),
+     *             InferJoin(
+     *                 StatementPattern(?x, rdf:type, :D),
+     *                 StatementPattern(?x, rdf:type, :E)
+     *             )
+     *         )
+     *     )
+     * )
+     * </pre>
+     * @param intersection a {@link List} of {@link Resource}s.
+     * @param typeVar the type {@link Var} to use as the subject for the
+     * {@link StatementPattern}.
+     * @param conVar the {@link Var} to use as the context for the
+     * {@link StatementPattern}.
+     * @return the {@link TupleExpr} tree. Returns {@code null} if
+     * {@code intersection} is empty. Returns a {@link StatementPattern} if
+     * {@code intersection}'s size is 1.  Otherwise, returns an
+     * {@link InferJoin} which may contain more nested {@link InferJoin}s.
+     */
+    private static TupleExpr createJoinTree(final List<Resource> intersection, final Var typeVar, final Var conVar) {
+        if (intersection.isEmpty()) {
+            return null;
+        } else {
+            final Var predVar = new Var(RDF.TYPE.toString(), RDF.TYPE);
+            final Resource resource = intersection.get(0);
+            final Var valueVar = new Var(resource.toString(), resource);
+            final StatementPattern left = new StatementPattern(typeVar, predVar, valueVar, conVar);
+            if (intersection.size() == 1) {
+                return left;
+            } else {
+                final List<Resource> subList = intersection.subList(1, intersection.size());
+                final TupleExpr right = createJoinTree(subList, typeVar, conVar);
+                final InferJoin join = new InferJoin(left, right);
+                join.getProperties().put(InferConstants.INFERRED, InferConstants.TRUE);
+                return join;
+            }
+        }
+    }
+
+    /**
+     * Recursively creates a {@link TupleExpr} tree comprised of
+     * {@link InferUnion}s and {@link InferJoin}s. The left arg is a
+     * {@link InferJoin} and the right arg is either a {@link InferJoin} if it's
+     * the final element or a nested {@link InferUnion}.<p>
+     * A list of {@code [JoinA, JoinB, JoinC, JoinD, JoinE]} returns:
+     * <pre>
+     * InferUnion(
+     *     JoinA,
+     *     InferUnion(
+     *         JoinB,
+     *         InferUnion(
+     *             JoinC,
+     *             InferUnion(
+     *                 JoinD,
+     *                 JoinE
+     *             )
+     *         )
+     *     )
+     * )
+     * </pre>
+     * @param joins a {@link List} of {@link TupleExpr}s that is most likely
+     * comprised of {@link Join}s but may be a single {@link StatementPattern}.
+     * @return the {@link TupleExpr} tree. Returns {@code null} if
+     * {@code joins} is empty. Might return a {@link StatementPattern} if
+     * {@code joins}' size is 1.  Otherwise, returns an
+     * {@link InferUnion} which may contain more nested {@link InferUnion}s.
+     */
+    private static TupleExpr createUnionTree(final List<TupleExpr> joins) {
+        if (joins.isEmpty()) {
+            return null;
+        } else {
+            final TupleExpr left = joins.get(0);
+            if (joins.size() == 1) {
+                return left;
+            } else {
+                final List<TupleExpr> subList = joins.subList(1, joins.size());
+                final TupleExpr right = createUnionTree(subList);
+                return new InferUnion(left, right);
+            }
+        }
+    }
+
+    /**
+     * Sorts {@link Resource}s in ascending order based on their string values.
+     */
+    public static class ResourceComparator implements Comparator<Resource> {
+        private static final Comparator<String> NULL_SAFE_STRING_COMPARATOR =
+            Comparator.nullsFirst(String::compareTo);
+
+        private static final Comparator<Resource> RESOURCE_COMPARATOR =
+            Comparator.comparing(Resource::stringValue, NULL_SAFE_STRING_COMPARATOR);
+
+        @Override
+        public int compare(final Resource r1, final Resource r2) {
+            if (r1 == null && r2 != null) {
+                return -1;
+            }
+            if (r1 != null && r2 == null) {
+                return 1;
+            }
+            if (r1 == null && r2 == null) {
+                return 0;
+            }
+            return RESOURCE_COMPARATOR.compare(r1, r2);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/e9488ff6/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InverseURI.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InverseURI.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InverseURI.java
index 6ad9225..13c068a 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InverseURI.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InverseURI.java
@@ -1,4 +1,3 @@
-package org.apache.rya.rdftriplestore.inference;
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -7,9 +6,9 @@ package org.apache.rya.rdftriplestore.inference;
  * 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
@@ -17,64 +16,49 @@ package org.apache.rya.rdftriplestore.inference;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.rya.rdftriplestore.inference;
+
 import org.openrdf.model.URI;
-import org.openrdf.model.impl.URIImpl;
-/*
- * 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.
- */
+
 public class InverseURI implements URI {
+    private static final long serialVersionUID = 1L;
+
+    private final URI impl;
+
+    public InverseURI(final URI uri) {
+        this.impl = uri;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((impl == null) ? 0 : impl.hashCode());
+        return result;
+    }
 
-	private URI impl;
-	
-	public InverseURI(URI uri) {
-		this.impl = uri;
-	}
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof InverseURI){
+            return impl.equals(((InverseURI) obj).impl);
+        }
+        return false;
+    }
 
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((impl == null) ? 0 : impl.hashCode());
-		return result;
-	}
+    @Override
+    public String stringValue() {
+        return impl.stringValue();
+    }
 
-	@Override
-	public boolean equals(Object obj) {
-		if (obj instanceof InverseURI){
-			return impl.equals(((InverseURI) obj).impl);
-		}
-		return false;
-	}
+    @Override
+    public String getNamespace() {
+        return impl.getNamespace();
+    }
 
-	@Override
-	public String stringValue() {
-		return impl.stringValue();
-	}
+    @Override
+    public String getLocalName() {
+        return impl.getLocalName();
+    }
 
-	@Override
-	public String getNamespace() {
-		return impl.getNamespace();
-	}
 
-	@Override
-	public String getLocalName() {
-		return impl.getLocalName();
-	}
-	
-	
 }