This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit f5a13ce4ed4b11bca10ee4441bb8f0b00414c41e
Author: Andy Seaborne <[email protected]>
AuthorDate: Sun Dec 31 15:42:53 2023 +0000

    Output via ValidationContext
---
 .../main/java/org/apache/jena/shacl/Imports.java   | 103 +++++++++++++++------
 .../main/java/org/apache/jena/shacl/Shapes.java    |   2 +-
 .../jena/shacl/engine/ValidationContext.java       |  13 ++-
 .../shacl/engine/constraint/JLogConstraint.java    |   2 +-
 .../org/apache/jena/shacl/parser/Constraints.java  |  22 +++--
 .../org/apache/jena/shacl/parser/ShapesParser.java |   2 +-
 .../org/apache/jena/shacl/sys/ShaclSystem.java     |  10 +-
 .../org/apache/jena/shacl/validation/VLib.java     |  21 +++--
 .../jena/shacl/validation/ValidationProc.java      |  31 +++----
 .../org/apache/jena/shacl/vocabulary/SHACL.java    |  24 +++++
 10 files changed, 154 insertions(+), 76 deletions(-)

diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/Imports.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/Imports.java
index 135ac4b1ac..04416df3ea 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/Imports.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/Imports.java
@@ -29,25 +29,36 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.apache.jena.atlas.lib.Pair;
+import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.atlas.web.HttpException;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.GraphUtil;
 import org.apache.jena.graph.Node;
 import org.apache.jena.irix.IRIs;
 import org.apache.jena.riot.RDFDataMgr;
+import org.apache.jena.riot.RDFParser;
 import org.apache.jena.riot.RiotParseException;
+import org.apache.jena.riot.system.stream.LocationMapper;
+import org.apache.jena.riot.system.stream.StreamManager;
+import org.apache.jena.shacl.sys.ShaclSystem;
 import org.apache.jena.sparql.graph.GraphFactory;
 import org.apache.jena.system.G;
 import org.apache.jena.system.RDFDataException;
+import org.apache.jena.web.HttpSC;
+import org.slf4j.Logger;
 
 /**
  * Import processing.
  * <p>
- * Imports are triggered by a base (a single triple "? rdf:type owl:Ontology")
- * and imports (triples "base owl:Imports URI").
+ * Imports are triggered by a base (a single triple "? rdf:type owl:Ontology") 
and
+ * imports (triples "base owl:Imports URI").
  * <p>
  * If there are other "? owl:imports ?" triples, they are ignored.
  */
 public class Imports {
+
+    public static Logger importsLogger = ShaclSystem.shaclSystemLogger;
+
     private Imports() {}
 
     /**
@@ -69,8 +80,8 @@ public class Imports {
     }
 
     /**
-     * Process and return the owl:imports closure of a graph.
-     * The graph is included in the results.
+     * Process and return the owl:imports closure of a graph. The graph is 
included
+     * in the results.
      */
     public static Graph withImports(String url, Graph graph) {
         url = IRIs.resolve(url);
@@ -80,8 +91,11 @@ public class Imports {
     private static Graph withImportsWorker(String url, Graph graph) {
         // Partial check for any imports. Are there any imports triples?
         boolean hasImports = G.contains(graph, null, nodeOwlImports, null);
-        if ( ! hasImports )
+        if ( !hasImports )
             return graph;
+        if ( importsLogger.isDebugEnabled() ) {
+            importsLogger.debug("Imports");
+        }
         // Probably some work to do.
         // This is "import self", and start the "visited".
         Graph acc = GraphFactory.createDefaultGraph();
@@ -97,38 +111,72 @@ public class Imports {
     private static void processImports(Set<String> visited, Graph graph, Graph 
acc) {
         List<Node> imports = imports(graph);
         for ( Node imported : imports ) {
-            if ( ! imported.isURI() )
+            if ( !imported.isURI() )
                 // Ignore non-URIs.
                 continue;
             String uri = imported.getURI();
-            if ( visited.contains(uri) )
+            if ( importsLogger.isDebugEnabled() )
+                importsLogger.debug("Import: " + uri);
+
+            // FmtLog.info(Imports.class, "Import: %s", uri);
+            if ( visited.contains(uri) ) {
+                if ( importsLogger.isDebugEnabled() )
+                    importsLogger.debug("Skipped: " + uri);
                 continue;
+            }
             visited.add(uri);
             // Read into a temporary graph to isolate errors.
-            try {
-                Graph g2 = RDFDataMgr.loadGraph(uri);
-                GraphUtil.addInto(acc, g2);
-                processImports(visited, g2, acc);
-            } catch (RiotParseException ex) {
-                //FmtLog.error(Imports.class, "Parse error reading '%s': %s", 
uri, ex.getMessage());
-                throw ex;
-            }
+            Graph g2 = loadOneGraph(uri);
+            GraphUtil.addInto(acc, g2);
+            processImports(visited, g2, acc);
+        }
+    }
+
+    private static final LocationMapper mapSHACL = new LocationMapper();
+    static {
+        // Inclusion in this list does not imply the shapes file is parseable 
or actually works!
+        mapSHACL.addAltEntry("http://topbraid.org/tosh";,    
"http://topbraid.org/tosh.ttl";);
+        mapSHACL.addAltEntry("http://datashapes.org/dash";,  
"http://datashapes.org/dash.ttl";);
+        mapSHACL.addAltEntry("https://topbraid.org/tosh";,   
"https://topbraid.org/tosh.ttl";);
+        mapSHACL.addAltEntry("https://datashapes.org/dash";, 
"https://datashapes.org/dash.ttl";);
+        //mapSHACL.addAltEntry("http://www.w3.org/ns/shacl";,  
"https://www.w3.org/ns/shacl";);
+    }
+
+    public static StreamManager shaclImportsStreamManager = 
StreamManager.get().clone();
+    static {
+        if ( ! mapSHACL.isEmpty() )
+            shaclImportsStreamManager.locationMapper(mapSHACL.clone());
+    }
+
+    private static Graph loadOneGraph(String uriOrFile) {
+        try {
+            return RDFParser.source(uriOrFile)
+                    .streamManager(shaclImportsStreamManager)
+                    .toGraph();
+        } catch (HttpException ex) {
+            if ( ex.getStatusCode() == HttpSC.NOT_FOUND_404 )
+                FmtLog.error(importsLogger, "Not found: %s", uriOrFile);
+            else
+                FmtLog.error(importsLogger, "HTTP exception: " + 
ex.getMessage());
+            throw ex;
+        } catch (RiotParseException ex) {
+            FmtLog.error(importsLogger, "Parse error reading '%s': %s", 
uriOrFile, ex.getMessage());
+            throw ex;
         }
     }
 
     /** Return the imports for a graph */
     public static List<Node> imports(Graph graph) {
-        Pair<Node,List<Node>> pair = baseAndImports(graph);
+        Pair<Node, List<Node>> pair = baseAndImports(graph);
         return pair.getRight();
     }
 
     /**
-     * Locate the base (a single triple ? rdf:type owl:Ontology)
-     * and imports (triples "base owl:Imports URI").
-     * May return null for the base in which case all imports are returned.
-     *
+     * Locate the base (a single triple ? rdf:type owl:Ontology) and imports 
(triples
+     * "base owl:Imports URI"). May return null for the base in which case all
+     * imports are returned.
      */
-    public static Pair<Node,List<Node>> baseAndImports(Graph graph) {
+    public static Pair<Node, List<Node>> baseAndImports(Graph graph) {
         Node base = null;
         if ( G.containsOne(graph, null, nodeRDFType, nodeOwlOntology) ) {
             base = G.getOnePO(graph, nodeRDFType, nodeOwlOntology);
@@ -138,23 +186,24 @@ public class Imports {
     }
 
     /**
-     * Locate the base (a single triple ? rdf:type owl:Ontology).
-     * If none or more than one matching triple, then return null.
+     * Locate the base (a single triple ? rdf:type owl:Ontology). If none or 
more
+     * than one matching triple, then return null.
      */
     public static Node base(Graph graph) {
         // Filter for URI?
         try {
             return G.getZeroOrOnePO(graph, nodeRDFType, nodeOwlOntology);
-        } catch (RDFDataException ex) { return null; }
+        } catch (RDFDataException ex) {
+            return null;
+        }
     }
 
     /**
-     * Locate any imports (triples "base owl:Imports URI").
-     * Base may be a wildcard indicating "any owl:imports".
+     * Locate any imports (triples "base owl:Imports URI"). Base may be a 
wildcard
+     * indicating "any owl:imports".
      */
     public static List<Node> allImports(Node base, Graph graph) {
         List<Node> imports = iter(G.listSP(graph, base, 
nodeOwlImports)).filter(Node::isURI).collect(Collectors.toList());
         return imports;
     }
 }
-
diff --git a/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java
index 667450cf71..a116f1415f 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/Shapes.java
@@ -57,7 +57,7 @@ public class Shapes implements Iterable<Shape> {
     private final Collection<Shape> rootShapes;
     // Declared shapes, not in targetShapes.
     private final Collection<Shape> declShapes;
-    // Shapes that are not declared shapes (by type), and not accessible from 
in targets.
+    // Shapes that are not declared shapes (by type), and not accessible from 
targets.
     // This is placeholder.
     // It should be disjoint with rootShapes and declShapes.
     private final Collection<Shape> otherShapes;
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
index c9ffa4f2d5..359d234ac6 100644
--- 
a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
+++ 
b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/ValidationContext.java
@@ -18,6 +18,7 @@
 
 package org.apache.jena.shacl.engine;
 
+import org.apache.jena.atlas.io.IndentedWriter;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.riot.system.ErrorHandler;
@@ -44,8 +45,8 @@ public class ValidationContext {
     private final Graph dataGraph;
     private boolean strict = false;
     private final ValidationListener validationListener;
-
     private final ErrorHandler errorHandler;
+    private final IndentedWriter out;
 
     public static ValidationContext create(Shapes shapes, Graph data) {
         return create(shapes, data, ShaclSystem.systemShaclErrorHandler, null);
@@ -74,17 +75,19 @@ public class ValidationContext {
         this.dataGraph = vCxt.dataGraph;
         this.verbose = vCxt.verbose;
         this.strict = vCxt.strict;
-        this.errorHandler = vCxt.errorHandler;
         this.validationListener = vCxt.validationListener;
+        this.errorHandler = vCxt.errorHandler;
+        this.out = vCxt.out;
     }
 
     private ValidationContext(Shapes shapes, Graph data, ErrorHandler 
errorHandler, ValidationListener validationListener) {
         this.shapes = shapes;
         this.dataGraph = data;
+        this.validationListener = validationListener;
         if ( errorHandler == null )
             errorHandler = ShaclSystem.systemShaclErrorHandler;
         this.errorHandler = errorHandler;
-        this.validationListener = validationListener;
+        this.out = IndentedWriter.stdout.clone();
         validationReportBuilder.addPrefixes(data.getPrefixMapping());
         
validationReportBuilder.addPrefixes(shapes.getGraph().getPrefixMapping());
     }
@@ -106,6 +109,8 @@ public class ValidationContext {
         return validationReportBuilder.build();
     }
 
+    public IndentedWriter out() { return out; }
+
     public boolean hasViolation() { return seenValidationReportEntry; }
 
     public void setVerbose(boolean value) {
@@ -134,7 +139,7 @@ public class ValidationContext {
     public Graph getDataGraph() {
         return dataGraph;
     }
-    
+
     public ErrorHandler getErrorHandler() {
         return errorHandler;
     }
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
 
b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
index a10e28ff91..ba2534d7f4 100644
--- 
a/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
+++ 
b/jena-shacl/src/main/java/org/apache/jena/shacl/engine/constraint/JLogConstraint.java
@@ -49,7 +49,7 @@ public class JLogConstraint extends ConstraintTerm {
     @Override
     public ReportItem validate(ValidationContext vCxt, Node n) {
         String msg = String.format("%s[%s]", message, ShLib.displayStr(n));
-        ShaclSystem.systemShaclLogger.warn(msg);
+        ShaclSystem.shaclSystemLogger.warn(msg);
         return null;
     }
 
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
index eeec95d1c8..6f8100874f 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/Constraints.java
@@ -82,6 +82,7 @@ public class Constraints {
         dispatch.put( SHACL.class_,            (g, s, p, o) -> new 
ClassConstraint(o)    );
         dispatch.put( SHACL.datatype,          (g, s, p, o) -> new 
DatatypeConstraint(o) );
         dispatch.put( SHACL.nodeKind,          (g, s, p, o) -> new 
NodeKindConstraint(o) );
+
         dispatch.put( SHACL.minCount,          (g, s, p, o) -> new 
MinCount(intValue(o)) );
         dispatch.put( SHACL.maxCount,          (g, s, p, o) -> new 
MaxCount(intValue(o)) );
 
@@ -97,15 +98,15 @@ public class Constraints {
         dispatch.put( SHACL.languageIn,        (g, s, p, o) -> new 
StrLanguageIn(listString(g, o)) );
         dispatch.put( SHACL.uniqueLang,        (g, s, p, o) -> new 
UniqueLangConstraint(booleanValueStrict(o)) );
 
-        dispatch.put( SHACL.hasValue,          (g, s, p, o) -> new 
HasValueConstraint(o) );
-        dispatch.put( SHACL.in,                (g, s, p, o) -> new 
InConstraint(list(g,o)) );
-        dispatch.put( SHACL.closed,            (g, s, p, o) -> new 
ClosedConstraint(g,s,booleanValue(o)) );
-
         dispatch.put( SHACL.equals,            (g, s, p, o) -> new 
EqualsConstraint( checkObjectIRI(g, s, p, o)) );
         dispatch.put( SHACL.disjoint,          (g, s, p, o) -> new 
DisjointConstraint( checkObjectIRI(g, s, p, o)) );
         dispatch.put( SHACL.lessThan,          (g, s, p, o) -> new 
LessThanConstraint( checkObjectIRI(g, s, p, o)) );
         dispatch.put( SHACL.lessThanOrEquals,  (g, s, p, o) -> new 
LessThanOrEqualsConstraint( checkObjectIRI(g, s, p, o)) );
 
+        dispatch.put( SHACL.hasValue,          (g, s, p, o) -> new 
HasValueConstraint(o) );
+        dispatch.put( SHACL.in,                (g, s, p, o) -> new 
InConstraint(list(g,o)) );
+        dispatch.put( SHACL.closed,            (g, s, p, o) -> new 
ClosedConstraint(g,s,booleanValue(o)) );
+
         // Below
         //dispatch.put( SHACL.not,                (g, s, p, o) -> 
notImplemented(p) );
         //dispatch.put( SHACL.and,                (g, s, p, o) -> 
notImplemented(p) );
@@ -168,7 +169,6 @@ public class Constraints {
      * Constraints require more that just the triple being inspected.
      */
     private static Constraint parseConstraint(Graph g, Node s, Node p, Node o, 
Map<Node, Shape> parsed, Set<Node> traversed) {
-
         // Test for single triple constraints.
         ConstraintMaker maker = dispatch.get(p);
         if ( maker != null )
@@ -182,18 +182,18 @@ public class Constraints {
 
         if ( p.equals(SHACL.or) ) {
             List<Node> elts = list(g, o);
-            List<Shape> shapes = 
elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, 
x)).collect(Collectors.toList());
+            List<Shape> shapes = shapes(g, parsed, traversed, elts);
             return new ShOr(shapes);
         }
         if ( p.equals(SHACL.and) ) {
             List<Node> elts = list(g, o);
-            List<Shape> shapes = 
elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, 
x)).collect(Collectors.toList());
+            List<Shape> shapes = shapes(g, parsed, traversed, elts);
             return new ShAnd(shapes);
         }
 
         if ( p.equals(SHACL.xone) ) {
             List<Node> elts = list(g, o);
-            List<Shape> shapes = 
elts.stream().map(x->ShapesParser.parseShapeStep(traversed, parsed, g, 
x)).collect(Collectors.toList());
+            List<Shape> shapes = shapes(g, parsed, traversed, elts);
             return new ShXone(shapes);
         }
 
@@ -243,6 +243,10 @@ public class Constraints {
         return null;
     }
 
+    private static List<Shape> shapes(Graph g, Map<Node, Shape> parsed, 
Set<Node> traversed, List<Node> elts) {
+        return elts.stream().map(x->ShapesParser.parseShapeStep(traversed, 
parsed, g, x)).collect(Collectors.toList());
+    }
+
     private static Constraint parseQualifiedValueShape(Graph g, Node s, Node 
p, Node o, Map<Node, Shape> parsed, Set<Node> traversed) {
         Shape sub = ShapesParser.parseShapeStep(traversed, parsed, g, o);
         // [PARSE] Syntax check needed
@@ -253,7 +257,7 @@ public class Constraints {
         Node qDisjoint = G.getZeroOrOneSP(g, s, 
SHACL.qualifiedValueShapesDisjoint);
         if ( vMin < 0 && vMax < 0 )
             throw new ShaclParseException("At least one of 
sh:qualifiedMinCount and sh:qualifiedMaxCount required");
-        return new QualifiedValueShape(sub, intValue(qMin, -1), intValue(qMax, 
-1), booleanValueStrict(qDisjoint)) ;
+        return new QualifiedValueShape(sub, vMin, vMax, 
booleanValueStrict(qDisjoint)) ;
     }
 
     interface ConstraintMaker {
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
index 1e0a52c604..35f3119e2c 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/parser/ShapesParser.java
@@ -303,7 +303,7 @@ public class ShapesParser {
                 return parsed.get(shapeNode);
             // Loop detection. Do before parsing.
             if ( traversed.contains(shapeNode) ) {
-                ShaclSystem.systemShaclLogger.warn("Cycle detected : node 
"+ShLib.displayStr(shapeNode));
+                ShaclSystem.shaclSystemLogger.warn("Cycle detected : node 
"+ShLib.displayStr(shapeNode));
                 // Put in a substitute shape.
                 return unshape(shapesGraph, shapeNode);
             }
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
index 73c32a8f1a..507586a96f 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/sys/ShaclSystem.java
@@ -26,14 +26,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ShaclSystem {
-    public static Logger systemShaclLogger = LoggerFactory.getLogger("SHACL"); 
-    public static ErrorHandler systemShaclErrorHandler = 
ErrorHandlerFactory.errorHandlerStd(systemShaclLogger);
-    
+    public static Logger shaclSystemLogger = 
LoggerFactory.getLogger("org.apache.jena.shacl.SHACL");
+    public static ErrorHandler systemShaclErrorHandler = 
ErrorHandlerFactory.errorHandlerStd(shaclSystemLogger);
+
     private static ShaclValidator globalDefault = new ShaclPlainValidator();
-    
+
     /** Set the current system-wide {@link ShaclValidator}. */
     public static void set(ShaclValidator validator) { globalDefault = 
validator; }
 
-    /** The current system-wide {@link ShaclValidator}. */ 
+    /** The current system-wide {@link ShaclValidator}. */
     public static ShaclValidator get() { return globalDefault; }
 }
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
index ed57b9fb1f..54dcbb017e 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/validation/VLib.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.jena.atlas.io.IndentedWriter;
 import org.apache.jena.atlas.lib.InternalErrorException;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
@@ -85,13 +84,12 @@ public class VLib {
     * graphs that were used to construct the shapes graph or the data graph. 
SHACL
     * processing is thus idempotent.
     */
-    private static IndentedWriter out  = 
IndentedWriter.clone(IndentedWriter.stdout);
-
     public static void validateShape(ValidationContext vCxt, Graph data, Shape 
shape, Node focusNode) {
         if ( shape.deactivated() )
             return;
+        vCxt.out().incIndent();
         if ( vCxt.isVerbose() )
-            out.println("S: "+shape);
+            vCxt.out().println("S: "+shape);
         vCxt.notifyValidationListener(() -> new 
FocusNodeValidationStartedEvent(vCxt, shape, focusNode));
         Path path;
         Set<Node> vNodes;
@@ -104,22 +102,23 @@ public class VLib {
             vCxt.notifyValidationListener(() -> new 
ValueNodesDeterminedForPropertyShapeEvent(vCxt, shape, focusNode, path, 
vNodes));
         } else {
             if ( vCxt.isVerbose() )
-                out.println("Z: "+shape);
+                vCxt.out().println("Z: "+shape);
             return;
         }
 
         // Constraints of this shape.
         for ( Constraint c : shape.getConstraints() ) {
+            vCxt.out().incIndent();
             if ( vCxt.isVerbose() )
-                out.println("C: "+c);
+                vCxt.out().println("C: "+c);
             evalConstraint(vCxt, data, shape, focusNode, path, vNodes, c);
+            vCxt.out().decIndent();
         }
 
         // Reachable shapes.
         // Follow sh:property (sh:node behaves as a constraint).
         validationPropertyShapes(vCxt, data, shape.getPropertyShapes(), 
focusNode);
-        if ( vCxt.isVerbose() )
-            out.println();
+        vCxt.out().decIndent();
         vCxt.notifyValidationListener(() -> new 
FocusNodeValidationFinishedEvent(vCxt, shape, focusNode));
     }
 
@@ -138,16 +137,18 @@ public class VLib {
         if ( propertyShape.deactivated() )
             return;
         if ( vCxt.isVerbose() )
-            out.println("P: "+propertyShape);
+            vCxt.out().println("P: "+propertyShape);
         vCxt.notifyValidationListener(() -> new 
FocusNodeValidationStartedEvent(vCxt, propertyShape, focusNode));
         Path path = propertyShape.getPath();
         Set<Node> vNodes = ShaclPaths.valueNodes(data, focusNode, path);
         vCxt.notifyValidationListener(() -> new 
ValueNodesDeterminedForPropertyShapeEvent(vCxt, propertyShape, focusNode, path, 
vNodes));
         for ( Constraint c : propertyShape.getConstraints() ) {
+            vCxt.out().incIndent();
             if ( vCxt.isVerbose() )
-                out.println("C: "+focusNode+" :: "+c);
+                vCxt.out().println("C: "+focusNode+" :: "+c);
             // Pass vNodes here.
             evalConstraint(vCxt, data, propertyShape, focusNode, path, vNodes, 
c);
+            vCxt.out().decIndent();
         }
         vNodes.forEach(vNode->{
             validationPropertyShapes(vCxt, data, 
propertyShape.getPropertyShapes(), vNode);
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 ea78fa96a7..34d20b2353 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
@@ -21,7 +21,6 @@ package org.apache.jena.shacl.validation;
 import java.util.Collection;
 import java.util.Collections;
 
-import org.apache.jena.atlas.io.IndentedWriter;
 import org.apache.jena.graph.Graph;
 import org.apache.jena.graph.Node;
 import org.apache.jena.shacl.Shapes;
@@ -74,14 +73,12 @@ public class ValidationProc {
      * processing is thus idempotent.
      */
 
-    private static IndentedWriter out  = IndentedWriter.stdout;
-
     public static ValidationReport plainValidation(Shapes shapes, Graph data) {
-        int x = out.getAbsoluteIndent();
+        ValidationContext vCxt = ValidationContext.create(shapes, data);
+        int x = vCxt.out().getAbsoluteIndent();
         try {
-            ValidationContext vCxt = ValidationContext.create(shapes, data);
             return plainValidation(vCxt, shapes, data);
-        } finally { out.setAbsoluteIndent(x); }
+        } finally { vCxt.out().setAbsoluteIndent(x); }
     }
 
     private static ValidationReport plainValidation(ValidationContext vCxt, 
Shapes shapes, Graph data) {
@@ -90,7 +87,7 @@ public class ValidationProc {
         try {
             targetShapes.forEach(shape->plainValidation(vCxt, shape, data));
             if (vCxt.isVerbose())
-                out.ensureStartOfLine();
+                vCxt.out().ensureStartOfLine();
             return vCxt.generateReport();
         } finally {
             vCxt.notifyValidationListener(() -> new 
TargetShapesValidationFinishedEvent(vCxt, targetShapes));
@@ -104,11 +101,11 @@ public class ValidationProc {
     // ---- Single node.
 
     public static ValidationReport plainValidationNode(Shapes shapes, Graph 
data, Node node) {
-        int x = out.getAbsoluteIndent();
+        ValidationContext vCxt = ValidationContext.create(shapes, data);
+        int x = vCxt.out().getAbsoluteIndent();
         try {
-            ValidationContext vCxt = ValidationContext.create(shapes, data);
             return plainValidationNode(vCxt, shapes, node, data);
-        } finally { out.setAbsoluteIndent(x); }
+        } finally { vCxt.out().setAbsoluteIndent(x); }
     }
 
     private static ValidationReport plainValidationNode(ValidationContext 
vCxt, Shapes shapes, Node node, Graph data) {
@@ -119,7 +116,7 @@ public class ValidationProc {
                             plainValidationNode(vCxt, data, node, shape)
             );
             if (vCxt.isVerbose())
-                out.ensureStartOfLine();
+                vCxt.out().ensureStartOfLine();
             return vCxt.generateReport();
         } finally {
             vCxt.notifyValidationListener(() -> new 
TargetShapesValidationFinishedEvent(vCxt, targetShapes));
@@ -150,19 +147,17 @@ public class ValidationProc {
         vCxt.notifyValidationListener(() -> new 
FocusNodesDeterminedEvent(vCxt, shape, focusNodes));
 
         if ( vCxt.isVerbose() ) {
-            out.println(shape.toString());
-            out.printf("N: FocusNodes(%d): %s\n", focusNodes.size(), 
focusNodes);
-            out.incIndent();
+            vCxt.out().println(shape.toString());
+            vCxt.out().printf("N: FocusNodes(%d): %s\n", focusNodes.size(), 
focusNodes);
         }
+        vCxt.out().incIndent();
 
         for ( Node focusNode : focusNodes ) {
             if ( vCxt.isVerbose() )
-                out.println("F: "+focusNode);
+                vCxt.out().println("F: "+focusNode);
             VLib.validateShape(vCxt, data, shape, focusNode);
         }
-        if ( vCxt.isVerbose() ) {
-            out.decIndent();
-        }
+        vCxt.out().decIndent();
         vCxt.notifyValidationListener(() -> new 
ShapeValidationFinishedEvent(vCxt, shape));
     }
 
diff --git 
a/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHACL.java 
b/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHACL.java
index dda7ed234f..803f8a3ba6 100644
--- a/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHACL.java
+++ b/jena-shacl/src/main/java/org/apache/jena/shacl/vocabulary/SHACL.java
@@ -18,6 +18,8 @@
 
 package org.apache.jena.shacl.vocabulary;
 
+import java.util.Set;
+
 import org.apache.jena.graph.Node;
 import org.apache.jena.graph.NodeFactory;
 
@@ -831,4 +833,26 @@ public class SHACL {
     public static final Node XoneConstraintComponent = createResource( 
"http://www.w3.org/ns/shacl#XoneConstraintComponent"; );
 
     public static final Node XoneConstraintComponent_xone = createResource( 
"http://www.w3.org/ns/shacl#XoneConstraintComponent-xone"; );
+
+    /** Set of all the constraint components in SHACL 1.0 Core and SPARQL : 32 
items */
+    public static final Set<Node> allStdConstraintComponents;
+
+    static {
+        // Not including ConstraintComponent which is the class of constraint 
components
+        Node arrayAllConstraintComponents[] = {
+            AndConstraintComponent, ClassConstraintComponent, 
ClosedConstraintComponent, DatatypeConstraintComponent,
+            DisjointConstraintComponent, EqualsConstraintComponent, 
ExpressionConstraintComponent, HasValueConstraintComponent,
+            InConstraintComponent, JSConstraintComponent, 
LanguageInConstraintComponent,
+            LessThanConstraintComponent, LessThanOrEqualsConstraintComponent,
+            MaxCountConstraintComponent, MaxExclusiveConstraintComponent,
+            MaxInclusiveConstraintComponent, MaxLengthConstraintComponent,
+            MinCountConstraintComponent, MinExclusiveConstraintComponent,
+            MinInclusiveConstraintComponent, MinLengthConstraintComponent,
+            NodeConstraintComponent, NodeKindConstraintComponent,
+            NotConstraintComponent, OrConstraintComponent, 
PatternConstraintComponent, PropertyConstraintComponent,
+            QualifiedMaxCountConstraintComponent, 
QualifiedMinCountConstraintComponent, SPARQLConstraintComponent,
+            UniqueLangConstraintComponent, XoneConstraintComponent
+        };
+        allStdConstraintComponents = Set.of(arrayAllConstraintComponents);
+    }
 }

Reply via email to