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

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

commit 7434bcde4e57f55425035a93e58334498ae85c49
Author: Andy Seaborne <[email protected]>
AuthorDate: Sat Apr 25 16:36:27 2026 +0100

    Provide validation of a combined shapes and data file
---
 jena-cmds/src/main/java/shacl/shacl_validate.java | 73 +++++++++++++----------
 1 file changed, 41 insertions(+), 32 deletions(-)

diff --git a/jena-cmds/src/main/java/shacl/shacl_validate.java 
b/jena-cmds/src/main/java/shacl/shacl_validate.java
index 96df4d54e5..bdd2d5728e 100644
--- a/jena-cmds/src/main/java/shacl/shacl_validate.java
+++ b/jena-cmds/src/main/java/shacl/shacl_validate.java
@@ -21,6 +21,8 @@
 
 package shacl;
 
+import java.util.List;
+
 import org.apache.jena.atlas.logging.LogCtl;
 import org.apache.jena.cmd.ArgDecl;
 import org.apache.jena.cmd.CmdException;
@@ -36,11 +38,14 @@ import org.apache.jena.shacl.ShaclValidator;
 import org.apache.jena.shacl.ValidationReport;
 import org.apache.jena.shacl.engine.ValidationContext;
 import org.apache.jena.shacl.lib.ShLib;
+import org.apache.jena.sparql.graph.GraphFactory;
 import org.apache.jena.sys.JenaSystem;
 
 /** SHACL validation.
- * <p>
- * Usage: <code>shacl validate [--text] --shapes SHAPES --data DATA</code>
+ * <pre>
+ * Usage: <code>shacl validate [--text] [-v|--verbose] [--target=] --shapes 
SHAPES --data DATA</code>
+ * Usage: <code>shacl validate [--text] [-v|--verbose] [--target=] FILE</code>
+ * </pre>
  */
 public class shacl_validate extends CmdMain {
 
@@ -55,8 +60,10 @@ public class shacl_validate extends CmdMain {
     private ArgDecl argShapes      = new ArgDecl(true, "--shapes", 
"--shapesfile", "--shapefile", "-s");
     private ArgDecl argTargetNode  = new ArgDecl(true, "--target", "--node", 
"-n", "-t");
 
-    private String  datafile = null;
-    private String  shapesfile = null;
+    // Allow multiple files for each - combine into one graph each for data 
and for shapes.
+    private List<String> datafiles = null;
+    private List<String> shapesfiles = null;
+    private String shapesURL = null;
     private String  targetNode = null;  // Parse later.
     private boolean textOutput = false;
 
@@ -75,44 +82,43 @@ public class shacl_validate extends CmdMain {
 
     @Override
     protected String getSummary() {
-        return getCommandName()+" [--target URI] --shapes shapesFile --data 
dataFile";
+        return getCommandName()+" [--target URI] [--shapes shapesFile --data 
dataFile] [FILE ...]";
     }
 
     @Override
     protected void processModulesAndArgs() {
          super.processModulesAndArgs();
 
-         datafile = super.getValue(argData);
-         shapesfile = super.getValue(argShapes);
+         // --data can be empty in which case shapes and data are in the 
shapes files.
+         datafiles = super.getValues(argData);
+         shapesfiles = super.getValues(argShapes);
 
-         // No -- arguments, use act on single file of shapes and data.
-         if ( datafile == null && shapesfile == null ) {
-             if ( positionals.size() == 1 ) {
-                 datafile = positionals.get(0);
-                 shapesfile = positionals.get(0);
-             }
+         // If there are no arguments, act the commandline positional 
arguments as shapes and data.
+         if ( datafiles.isEmpty() && shapesfiles.isEmpty() ) {
+             if ( positionals.isEmpty() )
+                 throw new CmdException("No input");
+             shapesfiles = positionals;
          }
-
-         if ( datafile == null )
-             throw new CmdException("Usage: "+getSummary());
-         if ( shapesfile == null )
-             shapesfile = datafile;
+         if ( shapesfiles == null || shapesfiles.isEmpty() )
+             throw new CmdException("No shapes files");
 
          textOutput = super.hasArg(argOutputText);
 
-         if ( contains(argTargetNode) ) {
+         if ( contains(argTargetNode) )
              targetNode = getValue(argTargetNode);
-         }
+
+         // For imports.
+         shapesURL = shapesfiles.getFirst();
     }
 
     @Override
     protected void exec() {
-        Graph shapesGraph = load(shapesfile, "shapes file");
+        Graph shapesGraph = load(shapesfiles);
         Graph dataGraph;
-        if ( datafile.equals(shapesfile) )
+        if ( datafiles.isEmpty() )
             dataGraph = shapesGraph;
         else
-            dataGraph = load(datafile, "data file");
+            dataGraph = load(datafiles);
 
         Node node = null;
         if ( targetNode != null ) {
@@ -120,7 +126,7 @@ public class shacl_validate extends CmdMain {
             node = NodeFactory.createURI(x);
         }
 
-        shapesGraph = Imports.withImports(shapesfile, shapesGraph);
+        shapesGraph = Imports.withImports(shapesURL, shapesGraph);
 
         if ( isVerbose() )
             ValidationContext.VERBOSE = true;
@@ -138,14 +144,17 @@ public class shacl_validate extends CmdMain {
             RDFDataMgr.write(System.out, report.getGraph(), Lang.TTL);
     }
 
-    private Graph load(String filename, String scope) {
-        try {
-            Graph graph = RDFDataMgr.loadGraph(filename);
-            return graph;
-        } catch (RiotException ex) {
-            System.err.println("Loading "+scope);
-            throw ex;
-        }
+    private Graph load(List<String> files) {
+        Graph graph = GraphFactory.createDefaultGraph();
+        files.forEach(fn-> {
+            try {
+                RDFDataMgr.read(graph, fn);
+            } catch (RiotException ex) {
+                System.err.println("Error loading "+fn);
+                throw ex;
+            }
+        });
+        return graph;
     }
 
     @Override

Reply via email to