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
+ *
+ * - compile a DFDL schema
+ *
- parse non-XML data into EXI using Agile Delta and
+ *
- unparse the data back to non-XML form.
+ *
+ */
+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");
+ }
+ }
+}