You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by GitBox <gi...@apache.org> on 2022/11/18 20:35:05 UTC

[GitHub] [daffodil] stevedlawrence commented on a diff in pull request #878: Implement a encode/decodeEXI command to the CLI

stevedlawrence commented on code in PR #878:
URL: https://github.com/apache/daffodil/pull/878#discussion_r1026843932


##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -514,12 +516,46 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments) {
     requireSubcommand()
   }
 
+  // Encode EXI Subcommand Options
+  object encodeEXI extends scallop.Subcommand("encodeEXI") {
+    banner("""|Usage: daffodil encodeEXI [-s <schema>] [-o <output>] [infile]

Review Comment:
   Thoughts on having a single subcommand `exi` that can both encode and decode? For example, the `base64` command encodes by default and decodes with the `-d` option. Maybe something similar?
   
   I almost wonder if this wants to be a separate utility, e.g. `dfdlexi`? Might not be worth the effort.
   



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)

Review Comment:
   Do we even need to parse? Can we just use one of the infosets in daffod-cli? These tests are much faster than they used to be but there's still some overhead in these integration tests. The less we can do the better.



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)

Review Comment:
   This should happen outside of runCLI. The encodeEXI command isn't guaranteed to be done by the time md5sum is called.



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)
+      } (ExitCode.Success)
+
+      // Decode EXI to XML and compare against original XML infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)

Review Comment:
   I'm not sure how reliable getBefore is. I'm prety sure it's not guaranteed to return the full output. Instead, I'd recommend creating another tempFile that you decode to and them read that file and compare.
   
   I htink this expectEOF + getBefore is a bit of a hack and probably should be avoided. I've removed most uses of it.



##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -1482,6 +1518,74 @@ object Main {
         }
       }
 
+      case Some(conf.encodeEXI) => {
+        val encodeOpts = conf.encodeEXI
+        val channel = encodeOpts.output.toOption match {
+          case Some("-") | None => Channels.newChannel(STDOUT)
+          case Some(file) => new FileOutputStream(file).getChannel()
+        }
+        val output = Channels.newOutputStream(channel)
+
+        val inputStream = encodeOpts.infile.toOption match {
+          case Some("-") | None => STDIN
+          case Some(file) => {
+            val f = new File(file)
+            new FileInputStream(f)
+          }
+        }
+        val input = new InputSource(inputStream)
+
+        val exiFactory = {
+          if (encodeOpts.schema.isDefined)
+            getExiFactoryOpt(InfosetType.EXISA, encodeOpts.schema.toOption)
+          else
+            getExiFactoryOpt(InfosetType.EXI, encodeOpts.schema.toOption)
+        }
+        val exiResult = new EXIResult(exiFactory.get)
+        exiResult.setOutputStream(output)
+
+        val reader = XMLReaderFactory.createXMLReader()
+        reader.setContentHandler(exiResult.getHandler)
+        reader.parse(input)
+        output.close

Review Comment:
   Do we need to catch any exceptions and return a exit code? Otherwise any exceptions will probably be reported as a bug, when really it should be reported as "invalid EXI/XML" or something.



##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -1482,6 +1518,74 @@ object Main {
         }
       }
 
+      case Some(conf.encodeEXI) => {
+        val encodeOpts = conf.encodeEXI
+        val channel = encodeOpts.output.toOption match {
+          case Some("-") | None => Channels.newChannel(STDOUT)
+          case Some(file) => new FileOutputStream(file).getChannel()
+        }
+        val output = Channels.newOutputStream(channel)
+
+        val inputStream = encodeOpts.infile.toOption match {
+          case Some("-") | None => STDIN
+          case Some(file) => {
+            val f = new File(file)
+            new FileInputStream(f)
+          }
+        }
+        val input = new InputSource(inputStream)
+
+        val exiFactory = {
+          if (encodeOpts.schema.isDefined)
+            getExiFactoryOpt(InfosetType.EXISA, encodeOpts.schema.toOption)
+          else
+            getExiFactoryOpt(InfosetType.EXI, encodeOpts.schema.toOption)
+        }

Review Comment:
   Note that this has all been refactored in PR #873. We'll have to fix some merge conflicts depending on which is merged first. I think it should be fairly easy to update this to use the new stuff either way since it's just a matter of making the EXIFactory publicly available.



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)
+      } (ExitCode.Success)
+
+      // Decode EXI to XML and compare against original XML infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(infosetXML, resultNode)

Review Comment:
   Like before, this should happen outside of runCLI when we are guaranteed the CLI is done with its work.



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)
+      } (ExitCode.Success)
+
+      // Decode EXI to XML and compare against original XML infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(infosetXML, resultNode)
+      } (ExitCode.Success)
+
+      // Generate the infoset in schema aware EXI directly
+      runCLI(args"parse -s $schema -I exisa -o $tempEXI") { cli =>
+        cli.send("test", inputDone = true)
+      } (ExitCode.Success)

Review Comment:
   Like before, can we reuse an existing EXI file in the repo and avoid he overhead with more parsing?



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)
+      } (ExitCode.Success)
+
+      // Decode EXI to XML and compare against original XML infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(infosetXML, resultNode)
+      } (ExitCode.Success)
+
+      // Generate the infoset in schema aware EXI directly
+      runCLI(args"parse -s $schema -I exisa -o $tempEXI") { cli =>
+        cli.send("test", inputDone = true)
+      } (ExitCode.Success)
+
+      // Decode the parsed EXI infoset to XML and compare against original XML
+      // infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(infosetXML, resultNode)
+      } (ExitCode.Success)
+    }
+  }
+
+  @Test def test_3017_CLI_Encode_Decode_EXI(): Unit = {
+    val inputXML = <person><name>Edward</name><age>42</age></person>
+
+    withTempFile { tempEXI =>
+      runCLI(args"encodeEXI -o $tempEXI") { cli =>
+        cli.sendLine(inputXML.toString, inputDone = true)
+      } (ExitCode.Success)
+
+      runCLI(args"decodeEXI $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(inputXML, resultNode)

Review Comment:
   Move these lines outside of runCLI.



##########
daffodil-cli/src/it/scala/org/apache/daffodil/exi/TestEXIEncodeDecode.scala:
##########
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.saving
+
+import org.junit.Test
+import scala.xml.{Node, XML}
+
+import org.apache.daffodil.CLI.Util._
+import org.apache.daffodil.Main.ExitCode
+import org.apache.daffodil.xml.XMLUtils
+
+class TestCLIEncodeDecodeEXI {
+
+  @Test def test_3017_CLI_Encode_Decode_EXI_SA(): Unit = {
+    val schema = path("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_15.dfdl.xsd")
+
+    withTempFile { tempEXI =>
+
+      // Create initial XML infoset
+      var infosetXML: Node = null
+      var encodedMD5: String = null
+      runCLI(args"parse -s $schema") { cli =>
+        cli.send("test", inputDone = true)
+        val res = cli.expectEOF
+        infosetXML = XML.loadString(res.getBefore)
+      } (ExitCode.Success)
+
+      // Encode infoset to schema aware EXI
+      runCLI(args"encodeEXI -s $schema -o $tempEXI") { cli =>
+        cli.sendLine(infosetXML.toString, inputDone = true)
+        encodedMD5 = md5sum(tempEXI)
+      } (ExitCode.Success)
+
+      // Decode EXI to XML and compare against original XML infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)
+        XMLUtils.compareAndReport(infosetXML, resultNode)
+      } (ExitCode.Success)
+
+      // Generate the infoset in schema aware EXI directly
+      runCLI(args"parse -s $schema -I exisa -o $tempEXI") { cli =>
+        cli.send("test", inputDone = true)
+      } (ExitCode.Success)
+
+      // Decode the parsed EXI infoset to XML and compare against original XML
+      // infoset
+      runCLI(args"decodeEXI -s $schema $tempEXI") { cli =>
+        val res = cli.expectEOF
+        val resultNode = XML.loadString(res.getBefore)

Review Comment:
   Same before. I suggest using withTempFile and outputting to that and then compare the file instead of trying to capture all of stdout.



##########
daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala:
##########
@@ -1482,6 +1518,74 @@ object Main {
         }
       }
 
+      case Some(conf.encodeEXI) => {
+        val encodeOpts = conf.encodeEXI
+        val channel = encodeOpts.output.toOption match {
+          case Some("-") | None => Channels.newChannel(STDOUT)
+          case Some(file) => new FileOutputStream(file).getChannel()
+        }
+        val output = Channels.newOutputStream(channel)
+
+        val inputStream = encodeOpts.infile.toOption match {
+          case Some("-") | None => STDIN
+          case Some(file) => {
+            val f = new File(file)
+            new FileInputStream(f)
+          }
+        }
+        val input = new InputSource(inputStream)
+
+        val exiFactory = {
+          if (encodeOpts.schema.isDefined)
+            getExiFactoryOpt(InfosetType.EXISA, encodeOpts.schema.toOption)
+          else
+            getExiFactoryOpt(InfosetType.EXI, encodeOpts.schema.toOption)
+        }
+        val exiResult = new EXIResult(exiFactory.get)
+        exiResult.setOutputStream(output)
+
+        val reader = XMLReaderFactory.createXMLReader()
+        reader.setContentHandler(exiResult.getHandler)
+        reader.parse(input)
+        output.close
+
+        ExitCode.Success
+      }
+
+      case Some(conf.decodeEXI) => {
+        val decodeOpts = conf.decodeEXI
+        val channel = decodeOpts.output.toOption match {
+          case Some("-") | None => Channels.newChannel(STDOUT)
+          case Some(file) => new FileOutputStream(file).getChannel()
+        }
+        val output = Channels.newOutputStream(channel)
+
+        val inputStream = decodeOpts.infile.toOption match {
+          case Some("-") | None => STDIN
+          case Some(file) => {
+            val f = new File(file)
+            new FileInputStream(f)
+          }
+        }
+        val input = new InputSource(inputStream)
+
+        val exiFactory = {
+          if (decodeOpts.schema.isDefined)
+            getExiFactoryOpt(InfosetType.EXISA, decodeOpts.schema.toOption)
+          else
+            getExiFactoryOpt(InfosetType.EXI, decodeOpts.schema.toOption)
+        }
+        val exiSource = new EXISource(exiFactory.get)
+        exiSource.setInputSource(input)
+
+        val result = new StreamResult(output)
+        val tf = TransformerFactory.newInstance()
+        val transformer = tf.newTransformer
+        transformer.transform(exiSource, result)
+
+        ExitCode.Success

Review Comment:
   Same comments above about potential merge conflicts and exit code.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@daffodil.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org