From 471e6a8440e2f86e83ef931fb58b5e0708658bbd Mon Sep 17 00:00:00 2001 From: Josh Adams Date: Wed, 28 Sep 2022 09:59:33 -0400 Subject: [PATCH] Added sample EXI program using Agile Delta --- .gitignore | 2 + helloExi/.project | 17 ++ helloExi/README.txt | 18 ++ helloExi/build.sbt | 23 +++ helloExi/project/build.properties | 1 + helloExi/src/main/java/HelloEXI.java | 167 ++++++++++++++++++ helloExi/src/main/resources/helloWorld.dat | 1 + .../src/main/resources/helloWorld.dfdl.xsd | 32 ++++ helloExi/src/test/java/TestHelloWorld.java | 15 ++ 9 files changed, 276 insertions(+) create mode 100644 helloExi/.project create mode 100644 helloExi/README.txt create mode 100644 helloExi/build.sbt create mode 100644 helloExi/project/build.properties create mode 100644 helloExi/src/main/java/HelloEXI.java create mode 100644 helloExi/src/main/resources/helloWorld.dat create mode 100644 helloExi/src/main/resources/helloWorld.dfdl.xsd create mode 100644 helloExi/src/test/java/TestHelloWorld.java diff --git a/.gitignore b/.gitignore index b09589b..3442c85 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ target target/ lib_managed +lib/ src_managed resource_managed .history @@ -12,6 +13,7 @@ resource_managed .bsp/ errors project/errors +.metals .~*# out .scala_dependencies diff --git a/helloExi/.project b/helloExi/.project new file mode 100644 index 0000000..98c7b7b --- /dev/null +++ b/helloExi/.project @@ -0,0 +1,17 @@ + + + helloExi + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/helloExi/README.txt b/helloExi/README.txt new file mode 100644 index 0000000..ccf5280 --- /dev/null +++ b/helloExi/README.txt @@ -0,0 +1,18 @@ +This is a Daffodil/DFDL example program using Agile Delta's EXI implementation. + +The build.sbt file is a build script for the sbt - simple build tool. + +You will need version 0.13.x or higher. + +You will also need Java 1.8 (aka Java 8) or higher JDK. + +You will need an internet connection to pull down the dependent libraries, including daffodil itself. + +With those installed you can type 'sbt run' and it will download all dependencies as jar files, and then compile and run the HelloWorld.java program. + +You will need either an evaluation or full version of the Agile Delta Efficient XML SDK, with all of it's jar files placed in the "lib/" directory. +NOTE: The standard evaluation package from Agile Delta only includes command line tools and does not include access to the SDK. You must ask for the SDK. + +If you would like the source and javadoc jars for the dependencies downloaded also, then type 'sbt updateClassifiers'. + +The jar files are cached in the lib_managed/ directory (which is removed by 'sbt clean') diff --git a/helloExi/build.sbt b/helloExi/build.sbt new file mode 100644 index 0000000..0db4955 --- /dev/null +++ b/helloExi/build.sbt @@ -0,0 +1,23 @@ +name := "dfdl-helloexi" + +organization := "com.tresys" + +version := "0.1.0" + +scalaVersion := "2.12.15" + +// People use this project to study what the dependencies actually are needed +// so having them put into lib_managed is helpful. +retrieveManaged := true +useCoursier := false // Workaround becauuse retrieveManaged doesn't work in some sbt versions. + +Compile / run / mainClass := Some("HelloEXI") + +libraryDependencies ++= Seq( + "org.apache.daffodil" %% "daffodil-japi" % "3.2.1", + "jaxen" % "jaxen" % "1.2.0", + "junit" % "junit" % "4.13.2" % "test", + "com.github.sbt" % "junit-interface" % "0.13.2" % "test" +) + +testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") diff --git a/helloExi/project/build.properties b/helloExi/project/build.properties new file mode 100644 index 0000000..3161d21 --- /dev/null +++ b/helloExi/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.6.1 diff --git a/helloExi/src/main/java/HelloEXI.java b/helloExi/src/main/java/HelloEXI.java new file mode 100644 index 0000000..b84b408 --- /dev/null +++ b/helloExi/src/main/java/HelloEXI.java @@ -0,0 +1,167 @@ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.xml.sax.ContentHandler; +import org.xml.sax.XMLReader; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import org.apache.daffodil.japi.Compiler; +import org.apache.daffodil.japi.Daffodil; +import org.apache.daffodil.japi.DataProcessor; +import org.apache.daffodil.japi.Diagnostic; +import org.apache.daffodil.japi.ParseResult; +import org.apache.daffodil.japi.ProcessorFactory; +import org.apache.daffodil.japi.UnparseResult; +import org.apache.daffodil.japi.DaffodilParseXMLReader; +import org.apache.daffodil.japi.DaffodilUnparseContentHandler; +import org.apache.daffodil.japi.io.InputSourceDataInputStream; +import org.apache.daffodil.japi.DaffodilUnparseErrorSAXException; + +import com.agiledelta.efx.EFXProperty; +import com.agiledelta.efx.EFXFactory; +import com.agiledelta.efx.EFXException; +import com.agiledelta.efx.sax.EFXSAXSerializer; + +/** + * Demonstrates using the Daffodil DFDL processor to + * + */ +public class HelloEXI { + + public static void main(String[] args) throws IOException, URISyntaxException, EFXException { + + URL schemaFileURL = HelloEXI.class.getResource("/helloWorld.dfdl.xsd"); + URL dataFileURL = HelloEXI.class.getResource("/helloWorld.dat"); + String exiFilePath = "src/main/resources/helloWorld.exi"; + String unpFilePath = "src/main/resources/helloWorld.exi.dat"; + + // + // First compile the DFDL Schema + // + Compiler c = Daffodil.compiler(); + ProcessorFactory pf = c.compileSource(schemaFileURL.toURI()); + if (pf.isError()) { + // didn't compile schema. Must be diagnostic of some sort. + List diags = pf.getDiagnostics(); + for (Diagnostic d : diags) { + System.err.println(d.getSomeMessage()); + } + System.exit(1); + } + DataProcessor dp = pf.onPath("/"); + if (dp.isError()) { + // didn't compile schema. Must be diagnostic of some sort. + List diags = dp.getDiagnostics(); + for (Diagnostic d : diags) { + System.err.println(d.getSomeMessage()); + } + System.exit(1); + } + + // + // Parse - parse data to EXI + // + System.out.println("**** Parsing data into EXI *****"); + InputStream is = dataFileURL.openStream(); + OutputStream os = new FileOutputStream(exiFilePath); + InputSourceDataInputStream dis = new InputSourceDataInputStream(is); + + // + // Setup Agile Delta EXI content handler + // + EFXFactory factory = EFXFactory.newInstance(); + //SchemaResolver resolver = new SchemaResolver() { + // public SchemaSource getSchema(String schemaID, String schemaPath, String namespaceURI) throws java.io.IOException { + // } + //}; + ////factory.setProperty(EFXProperty.SCHEMA_RESOLVER, resolver); + //factory.setSchema(schemaId); + factory.setProperty(EFXProperty.HEADER, true); + EFXSAXSerializer exiContentHandler = new EFXSAXSerializer(factory, os); + DaffodilParseXMLReader reader = dp.newXMLReaderInstance(); + reader.setContentHandler(exiContentHandler); + reader.parse(dis); + os.close(); + + // + // Check for errors + // + ParseResult pr = (ParseResult) reader.getProperty("urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:sax:ParseResult"); + boolean err = pr.isError(); + if (err) { + // didn't parse the data. Must be diagnostic of some sort. + List diags = pr.getDiagnostics(); + for (Diagnostic d : diags) { + System.err.println(d.getSomeMessage()); + } + System.exit(2); + } + + is.close(); + os.close(); + + // + // Unparse back to native format + // + + // If you need to also convert XML back into the native data format + // you need to "unparse" the infoset back to data. + // + // Not all DFDL schemas are setup for unparsing. There are some things + // you need for unparsing that just don't need to be present in the + // schema if you only intend to do parsing. + // + // But let's assume your DFDL schema is one that is able to be used both + // for parsing and unparsing data. + // + // So let's try unparsing + // + // We'll just store the result of unparsing into this + // ByteArrayOutputStream. + // + System.out.println("**** Unparsing XML infoset back into data *****"); + + is = new FileInputStream(exiFilePath); + FileOutputStream fos = new FileOutputStream(unpFilePath); + java.nio.channels.WritableByteChannel wbc = java.nio.channels.Channels.newChannel(fos); + XMLReader xmlReader = factory.createXMLReader(); + DaffodilUnparseContentHandler handler = dp.newContentHandlerInstance(wbc); + xmlReader.setContentHandler(handler); + try { + xmlReader.parse(new InputSource(is)); + } catch (SAXException ex) { + // Do nothing, error is detailed in unparse result + } finally { + is.close(); + wbc.close(); + fos.close(); + } + + UnparseResult ur = handler.getUnparseResult(); + err = ur.isError(); + + if (err) { + // didn't unparse. Must be diagnostic of some sort. + List diags = ur.getDiagnostics(); + for (Diagnostic d : diags) { + System.err.println(d.getSomeMessage()); + } + System.exit(3); + } + } +} diff --git a/helloExi/src/main/resources/helloWorld.dat b/helloExi/src/main/resources/helloWorld.dat new file mode 100644 index 0000000..736fba8 --- /dev/null +++ b/helloExi/src/main/resources/helloWorld.dat @@ -0,0 +1 @@ +Hello world! \ No newline at end of file diff --git a/helloExi/src/main/resources/helloWorld.dfdl.xsd b/helloExi/src/main/resources/helloWorld.dfdl.xsd new file mode 100644 index 0000000..0de0f04 --- /dev/null +++ b/helloExi/src/main/resources/helloWorld.dfdl.xsd @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/helloExi/src/test/java/TestHelloWorld.java b/helloExi/src/test/java/TestHelloWorld.java new file mode 100644 index 0000000..c21f362 --- /dev/null +++ b/helloExi/src/test/java/TestHelloWorld.java @@ -0,0 +1,15 @@ +import org.junit.Test; +import org.junit.Assert; + +public class TestHelloEXI { + + @Test + public void testMain() { + try{ + HelloEXI.main(new String[0]); + } + catch(Exception e){ + Assert.fail("Should not have thrown any exception"); + } + } +}