Merge pull request #642 from afs/iso

JENA-1789: Isomorphism fix and refactor
diff --git a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
index c77a5f5..dfbc981 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
@@ -611,8 +611,10 @@
         }
     }
 
-    protected static QueryExecution make(Query query, Dataset dataset)
-    { return make(query, dataset.asDatasetGraph()); }
+    protected static QueryExecution make(Query query, Dataset dataset) {
+        DatasetGraph dsg = dataset==null ? null : dataset.asDatasetGraph();
+        return make(query, dsg);
+    }
 
     protected static QueryExecution make(Query query, DatasetGraph datasetGraph)
     { return QueryExecution.create().query(query).dataset(datasetGraph).build(); }
diff --git a/jena-cmds/src/main/java/shacl/shacl_validate.java b/jena-cmds/src/main/java/shacl/shacl_validate.java
index 756c6c1..8b86837 100644
--- a/jena-cmds/src/main/java/shacl/shacl_validate.java
+++ b/jena-cmds/src/main/java/shacl/shacl_validate.java
@@ -91,7 +91,7 @@
             dataGraph = shapesGraph;
         else
             dataGraph = RDFDataMgr.loadGraph(datafile);
-        ValidationReport report = ValidationProc.simpleValidatation(shapesGraph, dataGraph, isVerbose());
+        ValidationReport report = ValidationProc.simpleValidation(shapesGraph, dataGraph, isVerbose());
         if ( textOutput )
             ShLib.printReport(report);
         else
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ValidationGraph.java b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ValidationGraph.java
index a4b3430..28ada2e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ValidationGraph.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ValidationGraph.java
@@ -128,7 +128,7 @@
 
         // Execute. If there are any validation results of any severity, abort, and return the ValidationReport.
         private ValidationReport validateCommit() {
-            ValidationReport report = ValidationProc.simpleValidatation(graphValidate.shapes, graphValidate.get(), false);
+            ValidationReport report = ValidationProc.simpleValidation(graphValidate.shapes, graphValidate.get(), false);
             if ( report.conforms() ) {
                 other.commit();
                 return null;
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ShaclSimpleValidator.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ShaclSimpleValidator.java
index a4090aa..c1212f2 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ShaclSimpleValidator.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ShaclSimpleValidator.java
@@ -76,13 +76,13 @@
     /** Produce a full validation report. */
     @Override
     public ValidationReport validate(Shapes shapes, Graph data) {
-        return ValidationProc.simpleValidatation(shapes, data, false);
+        return ValidationProc.simpleValidation(shapes, data, false);
     }
 
     /** Produce a full validation report for this node in the data. */
     @Override
     public ValidationReport validate(Shapes shapes, Graph data, Node node) {
-        return ValidationProc.simpleValidatationNode(shapes, data, node, false);
+        return ValidationProc.simpleValidationNode(shapes, data, node, false);
     }
 
     /** Produce a full validation report. */
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java
index 97e4105..12e1027 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/ValidationProc.java
@@ -37,6 +37,9 @@
 import org.apache.jena.sparql.path.Path;
 import org.apache.jena.vocabulary.RDF;
 
+import static org.apache.jena.shacl.lib.G.hasType;
+import static org.apache.jena.shacl.lib.G.isOfType;
+
 public class ValidationProc {
     /* 3.4 Validation
      *
@@ -83,56 +86,55 @@
 
     private static IndentedWriter out  = IndentedWriter.stdout;
 
-    public static ValidationReport simpleValidatation(Graph shapesGraph, Graph data) {
-        return simpleValidatation(shapesGraph, data, false);
+    public static ValidationReport simpleValidation(Graph shapesGraph, Graph data) {
+        return simpleValidation(shapesGraph, data, false);
     }
 
-    public static ValidationReport simpleValidatation(Graph shapesGraph, Graph data, boolean verbose) {
+    public static ValidationReport simpleValidation(Graph shapesGraph, Graph data, boolean verbose) {
         Shapes shapes = Shapes.parse(shapesGraph);
-        return simpleValidatation(shapes, data, verbose);
+        return simpleValidation(shapes, data, verbose);
     }
 
-    public static ValidationReport simpleValidatation(Shapes shapes, Graph data, boolean verbose) {
+    public static ValidationReport simpleValidation(Shapes shapes, Graph data, boolean verbose) {
         int x = out.getAbsoluteIndent();
         try {
             ValidationContext vCxt = new ValidationContext(shapes, data);
             vCxt.setVerbose(verbose);
-            return simpleValidatation(vCxt, shapes, data);
+            return simpleValidation(vCxt, shapes, data);
         //} catch (ShaclParseException ex) {
         } finally { out.setAbsoluteIndent(x); }
     }
 
-    public static ValidationReport simpleValidatation(ValidationContext vCxt, Iterable<Shape> shapes, Graph data) {
+    public static ValidationReport simpleValidation(ValidationContext vCxt, Iterable<Shape> shapes, Graph data) {
         //vCxt.setVerbose(true);
         for ( Shape shape : shapes ) {
-            simpleValidatation(vCxt, data, shape);
+            simpleValidation(vCxt, data, shape);
         }
         if ( vCxt.isVerbose() )
             out.ensureStartOfLine();
         return vCxt.generateReport();
     }
 
-    public static void simpleValidatation(ValidationContext vCxt, Graph data, Shape shape) {
-        simpleValidatationInternal(vCxt, data, null, shape);
+    public static void simpleValidation(ValidationContext vCxt, Graph data, Shape shape) {
+        simpleValidationInternal(vCxt, data, null, shape);
     }
     
     // ---- Single node.
-    
-    public static ValidationReport simpleValidatationNode(Shapes shapes, Graph data, Node node, boolean verbose) {
+
+    public static ValidationReport simpleValidationNode(Shapes shapes, Graph data, Node node, boolean verbose) {
         int x = out.getAbsoluteIndent();
         try {
             ValidationContext vCxt = new ValidationContext(shapes, data);
             vCxt.setVerbose(verbose);
-            return simpleValidatationNode(vCxt, shapes, node, data);
+            return simpleValidationNode(vCxt, shapes, node, data);
         //} catch (ShaclParseException ex) {
         } finally { out.setAbsoluteIndent(x); }
     }
 
-    
-    private static ValidationReport simpleValidatationNode(ValidationContext vCxt, Shapes shapes, Node node, Graph data) {
+    private static ValidationReport simpleValidationNode(ValidationContext vCxt, Shapes shapes, Node node, Graph data) {
         //vCxt.setVerbose(true);
         for ( Shape shape : shapes ) {
-            simpleValidatationNode(vCxt, data, node, shape);
+            simpleValidationNode(vCxt, data, node, shape);
         }
         if ( vCxt.isVerbose() )
             out.ensureStartOfLine();
@@ -140,17 +142,26 @@
 
     }
 
-    private static void simpleValidatationNode(ValidationContext vCxt, Graph data, Node node, Shape shape) {
-        simpleValidatationInternal(vCxt, data, node, shape);
+    private static void simpleValidationNode(ValidationContext vCxt, Graph data, Node node, Shape shape) {
+        simpleValidationInternal(vCxt, data, node, shape);
     }
 
     // --- Top of process
-    private static void simpleValidatationInternal(ValidationContext vCxt, Graph data, Node node, Shape shape) {
-        Collection<Node> focusNodes = getFocusNodes(data, shape);
-        if ( node != null ) { 
-            if ( ! focusNodes.contains(node) )
+    
+    /**
+     * Validation process.
+     * Either all focusNode for the shape (argument node == null)
+     * or just for one node of the focusNodes of the shape.
+     */
+    private static void simpleValidationInternal(ValidationContext vCxt, Graph data, Node node, Shape shape) {
+        Collection<Node> focusNodes;
+   
+        if ( node != null ) {
+            if (! isFocusNode(shape, node, data))
                 return ;
             focusNodes = Collections.singleton(node);
+        } else {
+            focusNodes = getFocusNodes(data, shape);
         }
         
         if ( vCxt.isVerbose() ) {
@@ -254,11 +265,11 @@
     private static Collection<Node> getFocusNodes(Graph data, Shape shape) {
         Collection<Node> acc = new HashSet<>();
         shape.getTargets().forEach(target->
-            acc.addAll(getFocusNodes(data, shape, target)));
+            acc.addAll(getFocusNodes(data, target)));
         return acc;
     }
 
-    private static Collection<Node> getFocusNodes(Graph data, Shape shape, Target target) {
+    private static Collection<Node> getFocusNodes(Graph data, Target target) {
         Node targetObj = target.getObject();
         switch(target.getTargetType()) {
             case targetClass:
@@ -276,4 +287,28 @@
                 return Collections.emptyList();
         }
     }
+
+    private static boolean isFocusNode(Shape shape, Node node, Graph data) {
+        return shape.getTargets()
+                .stream()
+                .anyMatch(target -> isFocusNode(target, node, data));
+    }
+
+    private static boolean isFocusNode(Target target, Node node, Graph data) {
+        Node targetObject = target.getObject();
+        switch (target.getTargetType()) {
+            case targetClass:
+                return hasType(data, node, targetObject);
+            case targetNode:
+                return targetObject.equals(node);
+            case targetObjectsOf:
+                return data.contains(null, targetObject, node);
+            case targetSubjectsOf:
+                return data.contains(node, targetObject, null);
+            case implicitClass:
+                return isOfType(data, node, targetObject);
+            default:
+                return false;
+        }
+    }
 }
diff --git a/jena-shacl/src/test/java/org/apache/jena/shacl/testing/ShaclTest.java b/jena-shacl/src/test/java/org/apache/jena/shacl/testing/ShaclTest.java
index 9a56972..983f4a7 100644
--- a/jena-shacl/src/test/java/org/apache/jena/shacl/testing/ShaclTest.java
+++ b/jena-shacl/src/test/java/org/apache/jena/shacl/testing/ShaclTest.java
@@ -55,7 +55,7 @@
             boolean generalFailure = test.isGeneralFailure();
             if ( generalFailure ) {
                 try {
-                    ValidationReport testReport = ValidationProc.simpleValidatation(shapesGraph, dataGraph, verbose);
+                    ValidationReport testReport = ValidationProc.simpleValidation(shapesGraph, dataGraph, verbose);
                     if ( testReport.conforms() )
                         fail("Expect a test failure: "+test.origin());
                 } catch (RuntimeException ex) {
@@ -68,7 +68,7 @@
             ValidationReport vReportGot;
 
             try {
-                vReportGot = ValidationProc.simpleValidatation(shapesGraph, dataGraph, verbose);
+                vReportGot = ValidationProc.simpleValidation(shapesGraph, dataGraph, verbose);
             } catch (Throwable th) {
                 System.out.println("** Test : "+test.origin());
                 throw th;