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); + } }
