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

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


The following commit(s) were added to refs/heads/main by this push:
     new dd5d908aa Add compileResource API method
dd5d908aa is described below

commit dd5d908aa7dbd7fd08a7c89ceb2f42b414bcd7e7
Author: Steve Lawrence <[email protected]>
AuthorDate: Tue Aug 27 12:16:05 2024 -0400

    Add compileResource API method
    
    Some API users want to find a DFDL schema resource on the classpath
    (e.g. by using Class.getResource). However, this results in an absolute
    URI which when passed to compileSource cannot be depersonalized in some
    cases and leads to verbose diagnostic paths. This is also one issue that
    prevents reproducible saved parsers since these absolute paths are
    included in the saved parser and are specific to the build environment.
    
    To fix this, this adds a new compileResource API function that accepts a
    resource path. This new API calls getResource instead of the user having
    to call it, and it creates a URISchemaSource with the resulting URI and
    diagnostic path context set to the resource path. This allows the
    diagnostic paths to be depersonalized and is one step towards
    reproducible saved parsers.
    
    DAFFODIL-2919
---
 .../scala/org/apache/daffodil/japi/Daffodil.scala  | 34 ++++++++++++++++++++++
 .../org/apache/daffodil/example/TestJavaAPI.java   | 21 +++++++++++++
 .../scala/org/apache/daffodil/sapi/Daffodil.scala  | 24 +++++++++++++++
 .../org/apache/daffodil/example/TestScalaAPI.scala | 20 +++++++++++++
 4 files changed, 99 insertions(+)

diff --git 
a/daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala 
b/daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala
index 4e46287b9..9e590c860 100644
--- a/daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala
+++ b/daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala
@@ -171,6 +171,40 @@ class Compiler private[japi] (private var sCompiler: 
SCompiler) {
     new ProcessorFactory(pf)
   }
 
+  /**
+   * Compile DFDL resource name into a [[ProcessorFactory]]
+   *
+   * @param name Resource name of a DFDL schema used to create a 
[[ProcessorFactory]].
+   * @return [[ProcessorFactory]] used to create [[DataProcessor]](s). Must 
check [[ProcessorFactory#isError]] before using it.
+   * @throws java.io.IOException if an I/O error occurs while reading the uri
+   * @throws java.io.FileNotFoundException if the resource could not be found
+   */
+  @throws(classOf[java.io.IOException])
+  def compileResource(name: String): ProcessorFactory = compileResource(name, 
null, null)
+
+  /**
+   * Compile DFDL resource name into a [[ProcessorFactory]]
+   *
+   * @param name Resource name of a DFDL schema used to create a 
[[ProcessorFactory]].
+   * @param rootName name of root element, or null to choose automatically 
from first element of schema.
+   * @param rootNamespace String of namespace of the root element, or null to 
infer automatically when unambiguous. Pass "" (empty string) for No Namespace.
+   * @return [[ProcessorFactory]] used to create [[DataProcessor]](s). Must 
check [[ProcessorFactory#isError]] before using it.
+   * @throws java.io.IOException if an I/O error occurs while reading the uri
+   * @throws java.io.FileNotFoundException if the resource could not be found
+   */
+  @throws(classOf[java.io.IOException])
+  @throws(classOf[java.io.FileNotFoundException])
+  def compileResource(
+    name: String,
+    rootName: String,
+    rootNamespace: String
+  ): ProcessorFactory = {
+    val uri = Misc.getRequiredResource(name)
+    val source = URISchemaSource(new File(name), uri)
+    val pf = sCompiler.compileSource(source, Option(rootName), 
Option(rootNamespace))
+    new ProcessorFactory(pf)
+  }
+
   /**
    * Reload a saved parser from a file
    *
diff --git 
a/daffodil-japi/src/test/java/org/apache/daffodil/example/TestJavaAPI.java 
b/daffodil-japi/src/test/java/org/apache/daffodil/example/TestJavaAPI.java
index 70439586f..4414e0d59 100644
--- a/daffodil-japi/src/test/java/org/apache/daffodil/example/TestJavaAPI.java
+++ b/daffodil-japi/src/test/java/org/apache/daffodil/example/TestJavaAPI.java
@@ -1429,4 +1429,25 @@ public class TestJavaAPI {
         assertTrue(pf.isError());
     }
 
+    @Test
+    public void testJavaAPICompileResource() throws IOException, 
ClassNotFoundException {
+        org.apache.daffodil.japi.Compiler c = Daffodil.compiler();
+        String name = "/test/japi/mySchema1.dfdl.xsd";
+        ProcessorFactory pf = c.compileResource(name);
+        DataProcessor dp = pf.onPath("/");
+
+        java.io.File file = getResource("/test/japi/myDataBroken.dat");
+        java.io.FileInputStream fis = new java.io.FileInputStream(file);
+        try (InputSourceDataInputStream dis = new 
InputSourceDataInputStream(fis)) {
+            JDOMInfosetOutputter outputter = new JDOMInfosetOutputter();
+            ParseResult res = dp.parse(dis, outputter);
+            assertTrue(res.isError());
+
+            Diagnostic d = res.getDiagnostics().get(0);
+            LocationInSchemaFile loc = d.getLocationsInSchemaFiles().get(0);
+            assertTrue(loc.toString().replace("\\", "/").contains("in " + 
name));
+        }
+    }
+
+
 }
diff --git 
a/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/Daffodil.scala 
b/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/Daffodil.scala
index 93a3c5bf9..47e241931 100644
--- a/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/Daffodil.scala
+++ b/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/Daffodil.scala
@@ -162,6 +162,30 @@ class Compiler private[sapi] (private var sCompiler: 
SCompiler) {
     new ProcessorFactory(pf.asInstanceOf[SProcessorFactory])
   }
 
+  /**
+   * Compile DFDL resource name into a [[ProcessorFactory]]
+   *
+   * @param name Resource name of a DFDL schema used to create a 
[[ProcessorFactory]].
+   * @param optRootName Option for name of root element, or None to choose 
automatically from first
+   *        element of schema. Defaults to None.
+   * @param optRootNamespace Option for string of namespace of the root 
element, or None to infer
+   *        automatically when unambiguous. Pass Some("") (empty string) for 
No Namespace.
+   *        Defaults to None.
+   * @return [[ProcessorFactory]] used to create [[DataProcessor]](s). Must 
check [[ProcessorFactory.isError]] before using it.
+   */
+  @throws(classOf[java.io.IOException])
+  @throws(classOf[java.io.FileNotFoundException])
+  def compileResource(
+    name: String,
+    optRootName: Option[String] = None,
+    optRootNamespace: Option[String] = None
+  ): ProcessorFactory = {
+    val uri = Misc.getRequiredResource(name)
+    val source = URISchemaSource(new File(name), uri)
+    val pf = sCompiler.compileSource(source, optRootName, optRootNamespace)
+    new ProcessorFactory(pf.asInstanceOf[SProcessorFactory])
+  }
+
   /**
    * Reload a saved parser from a file
    *
diff --git 
a/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestScalaAPI.scala 
b/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestScalaAPI.scala
index c82409c0e..371dd9edc 100644
--- 
a/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestScalaAPI.scala
+++ 
b/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestScalaAPI.scala
@@ -1391,4 +1391,24 @@ class TestScalaAPI {
     assertTrue(pf.isError())
   }
 
+  @Test
+  def testScalaAPICompileResource(): Unit = {
+    val c = Daffodil.compiler()
+    val name = "/test/sapi/mySchema1.dfdl.xsd"
+    val pf = c.compileResource(name)
+    val dp = pf.onPath("/")
+
+    val file = getResource("/test/sapi/myDataBroken.dat")
+    val fis = new java.io.FileInputStream(file)
+    using(new InputSourceDataInputStream(fis)) { input =>
+      val outputter = new ScalaXMLInfosetOutputter()
+      val res = dp.parse(input, outputter)
+      assertTrue(res.isError())
+
+      val d = res.getDiagnostics(0)
+      val loc = d.getLocationsInSchemaFiles(0)
+      assertTrue(loc.toString().replace("\\", "/").contains("in " + name))
+    }
+  }
+
 }

Reply via email to