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 f836f33b9 All InfosetOutputter functions now return Unit
f836f33b9 is described below

commit f836f33b9a76ef4c18a25f30b8844ea99b19f11e
Author: Steve Lawrence <[email protected]>
AuthorDate: Fri Aug 19 09:14:37 2022 -0400

    All InfosetOutputter functions now return Unit
    
    Commit 3b213ce30b deprecated InfosetOutputter functions that returned
    false, and instead expected them to throw an Exception. If an
    implementation returned false from one of these functions, then Daffodil
    threw a usageError and stopped processing, with the assumption that no
    one actually used this.
    
    Unfortunately, the SAXInfosetOutputter actually does return false to
    signify errors, which could lead to usageErrors when outputting SAX (or
    EXI which uses SAX behind the scenes).
    
    This changes the InfosetOutputter API to remove the Boolean return
    value, and changes all concrete implementations to use this new API and
    throw an Exception when an error is encountered. This breaks backwards
    compatibility, but ensures consistence and a cleaner API.
    
    Note that this does not completely address DAFFODIL-2721, but is a quick
    change to fix the SAX and EXI regression. Additional work is needed to
    fully resolve the issue.
    
    DAFFODIL-2721
---
 .../daffodil/general/TestRuntimeProperties.scala   |  3 +-
 .../org/apache/daffodil/japi/infoset/Infoset.scala | 64 +++++++--------
 .../daffodil/example/TestInfosetOutputter.java     | 24 ++----
 .../apache/daffodil/infoset/InfosetOutputter.scala | 71 ++++++++++-------
 .../apache/daffodil/infoset/InfosetWalker.scala    | 16 ++--
 .../daffodil/infoset/JDOMInfosetOutputter.scala    | 25 ++----
 .../daffodil/infoset/JsonInfosetOutputter.scala    | 24 ++----
 .../daffodil/infoset/NullInfosetOutputter.scala    | 20 +++--
 .../daffodil/infoset/SAXInfosetOutputter.scala     | 91 ++++++----------------
 .../infoset/ScalaXMLInfosetOutputter.scala         | 24 ++----
 .../daffodil/infoset/TeeInfosetOutputter.scala     | 56 +++++--------
 .../daffodil/infoset/W3CDOMInfosetOutputter.scala  | 25 ++----
 .../daffodil/infoset/XMLTextInfosetOutputter.scala | 27 ++-----
 .../org/apache/daffodil/sapi/infoset/Infoset.scala | 71 +++++++++--------
 .../example/TestInfosetInputterOutputter.scala     | 24 ++----
 .../daffodil/tdml/TDMLInfosetOutputter.scala       | 79 +++----------------
 16 files changed, 240 insertions(+), 404 deletions(-)

diff --git 
a/daffodil-core/src/test/scala/org/apache/daffodil/general/TestRuntimeProperties.scala
 
b/daffodil-core/src/test/scala/org/apache/daffodil/general/TestRuntimeProperties.scala
index 77eb8bf74..40fdaf1a5 100644
--- 
a/daffodil-core/src/test/scala/org/apache/daffodil/general/TestRuntimeProperties.scala
+++ 
b/daffodil-core/src/test/scala/org/apache/daffodil/general/TestRuntimeProperties.scala
@@ -38,7 +38,7 @@ import org.apache.daffodil.util.TestUtils
 class RedactingScalaXMLInfosetOutputter
   extends ScalaXMLInfosetOutputter {
 
-  override def startSimple(diSimple: DISimple): Boolean = {
+  override def startSimple(diSimple: DISimple): Unit = {
     super.startSimple(diSimple)
 
     val runtimeProperties = diSimple.erd.runtimeProperties
@@ -55,7 +55,6 @@ class RedactingScalaXMLInfosetOutputter
       val newElem = thisElem.copy(child = newChild)
       stack.top(stack.top.size - 1) = newElem
     }
-    true
   }
 }
 
diff --git 
a/daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala 
b/daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala
index 514f6fb67..47eebe1d7 100644
--- 
a/daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala
+++ 
b/daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala
@@ -123,18 +123,18 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
   /**
    * Called by Daffodil internals to signify the beginning of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def startDocument(): Boolean
+  @throws[Exception]
+  def startDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the end of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def endDocument(): Boolean
+  @throws[Exception]
+  def endDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a simple element.
@@ -142,11 +142,11 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diSimple the simple element that is started. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
 
-  def startSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def startSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a simple element.
@@ -154,10 +154,10 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diSimple the simple element that is ended. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def endSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def endSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a complex 
element.
@@ -165,10 +165,10 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diComplex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def startComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def startComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a complex element.
@@ -176,10 +176,10 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diComplex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def endComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def endComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of an array of 
elements.
@@ -187,10 +187,10 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diArray the array that is started. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def startArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def startArray(diArray: DIArray): Unit
 
   /**
    * Called by Daffodil internals to signify the end of an array of elements.
@@ -198,10 +198,10 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
    * @param diArray the array that is ended. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * @throws Exception if there was an error and Daffodil should stop parsing
    */
-  def endArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def endArray(diArray: DIArray): Unit
 }
 
 /**
@@ -475,12 +475,12 @@ abstract class InfosetOutputterProxy extends 
InfosetOutputter {
   protected val infosetOutputter: SInfosetOutputter
 
   override def reset(): Unit = infosetOutputter.reset()
-  override def startDocument(): Boolean = infosetOutputter.startDocument()
-  override def endDocument(): Boolean = infosetOutputter.endDocument()
-  override def startSimple(diSimple: DISimple): Boolean = 
infosetOutputter.startSimple(diSimple)
-  override def endSimple(diSimple: DISimple): Boolean = 
infosetOutputter.endSimple(diSimple)
-  override def startComplex(diComplex: DIComplex): Boolean = 
infosetOutputter.startComplex(diComplex)
-  override def endComplex(diComplex: DIComplex): Boolean = 
infosetOutputter.endComplex(diComplex)
-  override def startArray(diArray: DIArray): Boolean = 
infosetOutputter.startArray(diArray)
-  override def endArray(diArray: DIArray): Boolean = 
infosetOutputter.endArray(diArray)
+  override def startDocument(): Unit = infosetOutputter.startDocument()
+  override def endDocument(): Unit = infosetOutputter.endDocument()
+  override def startSimple(diSimple: DISimple): Unit = 
infosetOutputter.startSimple(diSimple)
+  override def endSimple(diSimple: DISimple): Unit = 
infosetOutputter.endSimple(diSimple)
+  override def startComplex(diComplex: DIComplex): Unit = 
infosetOutputter.startComplex(diComplex)
+  override def endComplex(diComplex: DIComplex): Unit = 
infosetOutputter.endComplex(diComplex)
+  override def startArray(diArray: DIArray): Unit = 
infosetOutputter.startArray(diArray)
+  override def endArray(diArray: DIArray): Unit = 
infosetOutputter.endArray(diArray)
 }
diff --git 
a/daffodil-japi/src/test/java/org/apache/daffodil/example/TestInfosetOutputter.java
 
b/daffodil-japi/src/test/java/org/apache/daffodil/example/TestInfosetOutputter.java
index ed1658e4b..4fc482514 100644
--- 
a/daffodil-japi/src/test/java/org/apache/daffodil/example/TestInfosetOutputter.java
+++ 
b/daffodil-japi/src/test/java/org/apache/daffodil/example/TestInfosetOutputter.java
@@ -41,63 +41,55 @@ public class TestInfosetOutputter extends InfosetOutputter {
     }
 
     @Override
-    public boolean startDocument() {
+    public void startDocument() {
         events.add(TestInfosetEvent.startDocument());
-        return true;
     }
 
     @Override
-    public boolean endDocument() {
+    public void endDocument() {
         events.add(TestInfosetEvent.endDocument());
-        return true;
     }
 
     @Override
-    public boolean startSimple(DISimple diSimple) {
+    public void startSimple(DISimple diSimple) {
         events.add(
             TestInfosetEvent.startSimple(
                 diSimple.erd().name(),
                 diSimple.erd().namedQName().namespace().toString(),
                 diSimple.dataValueAsString(),
                 diSimple.erd().isNillable() ? diSimple.isNilled() : null));
-        return true;
     }
 
     @Override
-    public boolean endSimple(DISimple diSimple) {
+    public void endSimple(DISimple diSimple) {
         events.add(
             TestInfosetEvent.endSimple(
                 diSimple.erd().name(),
                 diSimple.erd().namedQName().namespace().toString()));
-        return true;
     }
 
     @Override
-    public boolean startComplex(DIComplex diComplex) {
+    public void startComplex(DIComplex diComplex) {
         events.add(
             TestInfosetEvent.startComplex(
                 diComplex.erd().name(),
                 diComplex.erd().namedQName().namespace().toString(),
                 diComplex.erd().isNillable() ? diComplex.isNilled() : null));
-        return true;
     }
 
     @Override
-    public boolean endComplex(DIComplex diComplex) {
+    public void endComplex(DIComplex diComplex) {
         events.add(
             TestInfosetEvent.endComplex(
                 diComplex.erd().name(),
                 diComplex.erd().namedQName().namespace().toString()));
-        return true;
     }
 
     @Override
-    public boolean startArray(DIArray diArray) {
-        return true;
+    public void startArray(DIArray diArray) {
     }
 
     @Override
-    public boolean endArray(DIArray diArray) {
-        return true;
+    public void endArray(DIArray diArray) {
     }
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetOutputter.scala
index 8f1291312..1b17e5757 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetOutputter.scala
@@ -20,6 +20,20 @@ package org.apache.daffodil.infoset
 import java.nio.file.Path
 import java.nio.file.Paths
 
+/**
+ * Defines the interface for InfosetOutputters.
+ *
+ * Note that these functions all throw the generic java.lang.Exception to
+ * indicate error. Part of the reason to do this instead of a custom exception
+ * (e.g. InfosetOutputterException) is to simplify implementations. If an
+ * implementation already throws an exception when there is an error, there is
+ * no need to catch it and wrap it in a Daffodil specific exception. This is
+ * especially true considering Daffodil will just unwrap the exception and
+ * convert it to a SDE. Additionally, because Scala does not have checked
+ * exceptions, it can be difficult to ensure all expected exceptions are caught
+ * by implementations. This does mean some exceptions that you might normally
+ * expect to bubble up and will not, and will instead be turned into an SDE.
+ */
 trait InfosetOutputter {
 
   import Status._
@@ -30,90 +44,95 @@ trait InfosetOutputter {
    * Reset the internal state of this InfosetOutputter. This should be called
    * inbetween calls to the parse method.
    */
-  def reset(): Unit // call to reuse these. When first constructed no reset 
call is necessary.
+  def reset(): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
    */
-  def startDocument(): Boolean
+  @throws[Exception]
+  def startDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the end of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
    */
-  def endDocument(): Boolean
+  @throws[Exception]
+  def endDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a simple element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diSimple the simple element that is started. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-
-  def startSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def startSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a simple element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diSimple the simple element that is ended. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def endSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a complex 
element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def startComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def startComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a complex element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def endComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of an array of 
elements.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the array that is started. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def startArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def startArray(diArray: DIArray): Unit
 
   /**
    * Called by Daffodil internals to signify the end of an array of elements.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the array that is ended. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def endArray(diArray: DIArray): Unit
 
   def getStatus(): Status = {
     // Done, Ready (Not started), Visiting (part way done - can retry to visit 
more)...
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetWalker.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetWalker.scala
index d99b809c5..16f85526c 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetWalker.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetWalker.scala
@@ -17,10 +17,6 @@
 
 package org.apache.daffodil.infoset
 
-import scala.util.Failure
-import scala.util.Success
-import scala.util.Try
-
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.util.MStackOfInt
@@ -413,13 +409,11 @@ class InfosetWalker private (
     containerIndexStack.setTop(top + 1)
   }
 
-  private def doOutputter(outputterFunc: => Boolean, desc: String, context: 
ThrowsSDE): Unit = {
-    Try(outputterFunc) match {
-      case Success(true) => // success
-      // $COVERAGE-OFF$
-      case Success(false) => Assert.usageError("InfosetOutputter false return 
value is deprecated. Throw an Exception instead.")
-      // $COVERAGE-ON$
-      case Failure(e) => {
+  private def doOutputter(outputterFunc: => Unit, desc: String, context: 
ThrowsSDE): Unit = {
+    try {
+      outputterFunc
+    } catch {
+      case e: Exception => {
         val cause = e.getCause
         val msg = if (cause == null) e.toString else cause.toString
         context.SDE("Failed to %s: %s", desc, msg)
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JDOMInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JDOMInfosetOutputter.scala
index f0f1ba16b..a7aef3baa 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JDOMInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JDOMInfosetOutputter.scala
@@ -35,20 +35,18 @@ class JDOMInfosetOutputter extends InfosetOutputter
     stack.clear
   }
 
-  def startDocument(): Boolean = {
+  def startDocument(): Unit = {
     stack.push(new org.jdom2.Document)
-    true
   }
 
-  def endDocument(): Boolean = {
+  def endDocument(): Unit = {
     val root = stack.pop
     assert(stack.isEmpty)
     assert(root.isInstanceOf[org.jdom2.Document])
     result = Maybe(root.asInstanceOf[org.jdom2.Document])
-    true
   }
 
-  def startSimple(diSimple: DISimple): Boolean = {
+  def startSimple(diSimple: DISimple): Unit = {
 
     val elem = createElement(diSimple)
 
@@ -63,33 +61,26 @@ class JDOMInfosetOutputter extends InfosetOutputter
     }
 
     stack.top.addContent(elem)
-
-    true
   }
 
-  def endSimple(diSimple: DISimple): Boolean = {
-    true
+  def endSimple(diSimple: DISimple): Unit = {
   }
 
-  def startComplex(diComplex: DIComplex): Boolean = {
+  def startComplex(diComplex: DIComplex): Unit = {
 
     val elem = createElement(diComplex)
 
     stack.top.addContent(elem)
     stack.push(elem)
-    true
   }
 
-  def endComplex(diComplex: DIComplex): Boolean = {
+  def endComplex(diComplex: DIComplex): Unit = {
     stack.pop
-    true
   }
 
-  def startArray(diArray: DIArray): Boolean = {
-    true
+  def startArray(diArray: DIArray): Unit = {
   }
-  def endArray(diArray: DIArray): Boolean = {
-    true
+  def endArray(diArray: DIArray): Unit = {
   }
 
   def getResult(): org.jdom2.Document = {
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JsonInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JsonInfosetOutputter.scala
index 306e54fae..6658ae2c5 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JsonInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/JsonInfosetOutputter.scala
@@ -97,7 +97,7 @@ class JsonInfosetOutputter private (writer: java.io.Writer, 
pretty: Boolean, dum
   }
 
 
-  override def startSimple(simple: DISimple): Boolean = {
+  override def startSimple(simple: DISimple): Unit = {
     startNode()
     startElement(simple)
     if (!isNilled(simple) && simple.hasValue) {
@@ -113,15 +113,13 @@ class JsonInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean, dum
     } else {
       writer.write("null")
     }
-    true
   }
 
-  override def endSimple(simple: DISimple): Boolean = {
+  override def endSimple(simple: DISimple): Unit = {
     // nothing to do
-    true
   }
 
-  override def startComplex(complex: DIComplex): Boolean = {
+  override def startComplex(complex: DIComplex): Unit = {
     startNode()
     startElement(complex)
     if (!isNilled(complex)) {
@@ -130,47 +128,41 @@ class JsonInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean, dum
     } else {
       writer.write("null")
     }
-    true
   }
 
-  override def endComplex(complex: DIComplex): Boolean = {
+  override def endComplex(complex: DIComplex): Unit = {
     if (!isNilled(complex)) {
       endNodeWithChildren()
       writer.write('}')
     } else {
       // do nothing
     }
-    true
   }
 
-  override def startArray(array: DIArray): Boolean = {
+  override def startArray(array: DIArray): Unit = {
     startNode()
     writer.write('"')
     writer.write(array.erd.name)
     writer.write("\": [")
     prepareForChildren()
-    true
   }
 
-  override def endArray(array: DIArray): Boolean = {
+  override def endArray(array: DIArray): Unit = {
     endNodeWithChildren()
     writer.write(']')
-    true
   }
 
-  override def startDocument(): Boolean = {
+  override def startDocument(): Unit = {
     // does not use startNode() because the stack is empty and we also do
     // not want to output the newline that it outputs or do any indentation
     writer.write('{')
     prepareForChildren()
-    true
   }
 
-  override def endDocument(): Boolean = {
+  override def endDocument(): Unit = {
     endNodeWithChildren()
     writer.write('}')
     if (pretty) writer.write(System.lineSeparator())
     writer.flush()
-    true
   }
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/NullInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/NullInfosetOutputter.scala
index 266b6f0e1..ceaf45a7c 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/NullInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/NullInfosetOutputter.scala
@@ -23,19 +23,17 @@ package org.apache.daffodil.infoset
  */
 class NullInfosetOutputter() extends InfosetOutputter {
 
-  override def reset(): Unit = {
-    //do nothing
-  }
+  override def reset(): Unit = {}
 
-  override def startSimple(simple: DISimple): Boolean = true
-  override def endSimple(simple: DISimple): Boolean = true
+  override def startSimple(simple: DISimple): Unit = {}
+  override def endSimple(simple: DISimple): Unit = {}
 
-  override def startComplex(complex: DIComplex): Boolean = true
-  override def endComplex(complex: DIComplex): Boolean = true
+  override def startComplex(complex: DIComplex): Unit = {}
+  override def endComplex(complex: DIComplex): Unit = {}
 
-  override def startArray(array: DIArray): Boolean = true
-  override def endArray(array: DIArray): Boolean = true
+  override def startArray(array: DIArray): Unit = {}
+  override def endArray(array: DIArray): Unit = {}
 
-  override def startDocument(): Boolean = true
-  override def endDocument(): Boolean = true
+  override def startDocument(): Unit = {}
+  override def endDocument(): Unit = {}
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetOutputter.scala
index 1ca3c5db4..808f339e1 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetOutputter.scala
@@ -23,7 +23,6 @@ import org.apache.daffodil.api.DFDL
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.xml.XMLUtils
 import org.xml.sax.ContentHandler
-import org.xml.sax.SAXException
 import org.xml.sax.helpers.AttributesImpl
 
 class SAXInfosetOutputter(xmlReader: DFDL.DaffodilParseXMLReader,
@@ -43,104 +42,62 @@ class SAXInfosetOutputter(xmlReader: 
DFDL.DaffodilParseXMLReader,
     // their contentHandler's reset if applicable and if necessary
   }
 
-  override def startDocument(): Boolean = {
+  override def startDocument(): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        contentHandler.startDocument()
-        true
-      } catch {
-        case _: SAXException => false
-      }
-    } else {
-      true
+      contentHandler.startDocument()
     }
   }
 
-  override def endDocument(): Boolean = {
+  override def endDocument(): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        contentHandler.endDocument()
-        true
-      } catch {
-        case _: SAXException => false
-      }
-    } else {
-      true
+       contentHandler.endDocument()
     }
   }
 
-  override def startSimple(diSimple: DISimple): Boolean = {
+  override def startSimple(diSimple: DISimple): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        doStartElement(diSimple, contentHandler)
-        if (diSimple.hasValue) {
-          val text =
-            if 
(diSimple.erd.optPrimType.get.isInstanceOf[NodeInfo.String.Kind]) {
-              val s = remapped(diSimple.dataValueAsString)
-              scala.xml.Utility.escape(s)
-            } else {
-              diSimple.dataValueAsString
-            }
-          val arr = text.toCharArray
-          contentHandler.characters(arr, 0, arr.length)
-        }
-        true
-      } catch {
-        case _: SAXException => false
+      doStartElement(diSimple, contentHandler)
+      if (diSimple.hasValue) {
+        val text =
+          if (diSimple.erd.optPrimType.get.isInstanceOf[NodeInfo.String.Kind]) 
{
+            val s = remapped(diSimple.dataValueAsString)
+            scala.xml.Utility.escape(s)
+          } else {
+            diSimple.dataValueAsString
+          }
+        val arr = text.toCharArray
+        contentHandler.characters(arr, 0, arr.length)
       }
-    } else {
-      true
     }
   }
 
-  override def endSimple(diSimple: DISimple): Boolean = {
+  override def endSimple(diSimple: DISimple): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        doEndElement(diSimple, contentHandler)
-        true
-      } catch {
-        case _: SAXException => false
-      }
-    } else {
-      true
+      doEndElement(diSimple, contentHandler)
     }
   }
 
-  override def startComplex(diComplex: DIComplex): Boolean = {
+  override def startComplex(diComplex: DIComplex): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        doStartElement(diComplex, contentHandler)
-        true
-      } catch {
-        case _: SAXException => false
-      }
-    } else {
-      true
+      doStartElement(diComplex, contentHandler)
     }
   }
 
-  override def endComplex(diComplex: DIComplex): Boolean = {
+  override def endComplex(diComplex: DIComplex): Unit = {
     val contentHandler = xmlReader.getContentHandler
     if (contentHandler != null) {
-      try {
-        doEndElement(diComplex, contentHandler)
-        true
-      } catch {
-        case _: SAXException => false
-      }
-    } else {
-      true
+      doEndElement(diComplex, contentHandler)
     }
   }
 
-  override def startArray(diArray: DIArray): Boolean = true // not applicable
+  override def startArray(diArray: DIArray): Unit = {} // not applicable
 
-  override def endArray(diArray: DIArray): Boolean = true // not applicable
+  override def endArray(diArray: DIArray): Unit = {} // not applicable
 
   private def doStartPrefixMapping(diElem: DIElement, contentHandler: 
ContentHandler): Unit = {
     val (nsbStart: NamespaceBinding, nsbEnd: NamespaceBinding) = 
getNsbStartAndEnd(diElem)
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/ScalaXMLInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/ScalaXMLInfosetOutputter.scala
index 2e037f539..c45daa38d 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/ScalaXMLInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/ScalaXMLInfosetOutputter.scala
@@ -40,16 +40,14 @@ class ScalaXMLInfosetOutputter(showFormatInfo: Boolean = 
false, showFreedInfo: B
     stack.clear
   }
 
-  def startDocument(): Boolean = {
+  def startDocument(): Unit = {
     stack.push(new ListBuffer())
-    true
   }
 
-  def endDocument(): Boolean = {
+  def endDocument(): Unit = {
     val root = stack.pop
     assert(root.length == 1)
     resultNode = Maybe(root(0))
-    true
   }
 
   private def getAttributes(diElem: DIElement): MetaData = {
@@ -75,7 +73,7 @@ class ScalaXMLInfosetOutputter(showFormatInfo: Boolean = 
false, showFreedInfo: B
     freedAttr
   }
 
-  def startSimple(diSimple: DISimple): Boolean = {
+  def startSimple(diSimple: DISimple): Unit = {
 
     val attributes = getAttributes(diSimple)
 
@@ -103,19 +101,16 @@ class ScalaXMLInfosetOutputter(showFormatInfo: Boolean = 
false, showFreedInfo: B
 
     val elemWithFmt = addFmtInfo(diSimple, elem, showFormatInfo)
     stack.top.append(elemWithFmt)
-    true
   }
 
-  def endSimple(diSimple: DISimple): Boolean = {
-    true
+  def endSimple(diSimple: DISimple): Unit = {
   }
 
-  def startComplex(diComplex: DIComplex): Boolean = {
+  def startComplex(diComplex: DIComplex): Unit = {
     stack.push(new ListBuffer())
-    true
   }
 
-  def endComplex(diComplex: DIComplex): Boolean = {
+  def endComplex(diComplex: DIComplex): Unit = {
 
     val attributes = getAttributes(diComplex)
     val children = stack.pop
@@ -131,15 +126,12 @@ class ScalaXMLInfosetOutputter(showFormatInfo: Boolean = 
false, showFreedInfo: B
 
     val elemWithFmt = addFmtInfo(diComplex, elem, showFormatInfo)
     stack.top.append(elemWithFmt)
-    true
   }
 
-  def startArray(diArray: DIArray): Boolean = {
+  def startArray(diArray: DIArray): Unit = {
     // Array elements are started individually
-    true
   }
-  def endArray(diArray: DIArray): Boolean = {
-    true
+  def endArray(diArray: DIArray): Unit = {
   }
 
   def getResult(): scala.xml.Node = {
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/TeeInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/TeeInfosetOutputter.scala
index c2ed4f04f..feeabe0e2 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/TeeInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/TeeInfosetOutputter.scala
@@ -19,11 +19,9 @@ package org.apache.daffodil.infoset
 
 
 /**
- * Receive infoset events and forward them to one or more InfosetOutputters.
- * For infoset events that return a boolean, this returns true only if all
- * outputters return true, otherwise false is returned. Additionally, all
- * events are called on all the outputters regardless of the return of any
- * previous outputters.
+ * Receive infoset events and forward them to one or more InfosetOutputters. A
+ * thrown exception from any outputter is not caught and bubbles up resulting
+ * in an SDE. No other outputters are called when an exception occurs.
  *
  * @param outputters
  *
@@ -36,51 +34,35 @@ class TeeInfosetOutputter(outputters: InfosetOutputter*)
     outputters.foreach { _.reset() }
   }
 
-  override def startSimple(simple: DISimple): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.startSimple(simple)
-    }
+  override def startSimple(simple: DISimple): Unit = {
+    outputters.foreach { _.startSimple(simple) }
   }
   
-  override def endSimple(simple: DISimple): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.endSimple(simple)
-    }
+  override def endSimple(simple: DISimple): Unit = {
+    outputters.foreach { _.endSimple(simple) }
   }
 
-  override def startComplex(complex: DIComplex): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.startComplex(complex)
-    }
+  override def startComplex(complex: DIComplex): Unit = {
+    outputters.foreach { _.startComplex(complex) }
   }
 
-  override def endComplex(complex: DIComplex): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.endComplex(complex)
-    }
+  override def endComplex(complex: DIComplex): Unit = {
+    outputters.foreach { _.endComplex(complex) }
   }
 
-  override def startArray(array: DIArray): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.startArray(array)
-    }
+  override def startArray(array: DIArray): Unit = {
+    outputters.foreach { _.startArray(array) }
   }
 
-  override def endArray(array: DIArray): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.endArray(array)
-    }
+  override def endArray(array: DIArray): Unit = {
+    outputters.foreach { _.endArray(array) }
   }
 
-  override def startDocument(): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.startDocument()
-    }
+  override def startDocument(): Unit = {
+    outputters.foreach { _.startDocument() }
   }
 
-  override def endDocument(): Boolean = {
-    outputters.foldLeft(true) { case (res, outputter) =>
-      res & outputter.endDocument()
-    }
+  override def endDocument(): Unit = {
+    outputters.foreach { _.endDocument() }
   }
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/W3CDOMInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/W3CDOMInfosetOutputter.scala
index 2bb809ed3..71b509956 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/W3CDOMInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/W3CDOMInfosetOutputter.scala
@@ -40,23 +40,21 @@ class W3CDOMInfosetOutputter extends InfosetOutputter
     stack.clear
   }
 
-  def startDocument(): Boolean = {
+  def startDocument(): Unit = {
     val factory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance();
     factory.setNamespaceAware(true)
     document = factory.newDocumentBuilder().newDocument()
     stack.push(document)
-    true
   }
 
-  def endDocument(): Boolean = {
+  def endDocument(): Unit = {
     val root = stack.pop
     assert(stack.isEmpty)
     assert(root.isInstanceOf[Document])
     result = Maybe(root.asInstanceOf[Document])
-    true
   }
 
-  def startSimple(diSimple: DISimple): Boolean = {
+  def startSimple(diSimple: DISimple): Unit = {
 
     val elem = createElement(diSimple)
 
@@ -71,32 +69,25 @@ class W3CDOMInfosetOutputter extends InfosetOutputter
     }
 
     stack.top.appendChild(elem)
-
-    true
   }
 
-  def endSimple(diSimple: DISimple): Boolean = {
-    true
+  def endSimple(diSimple: DISimple): Unit = {
   }
 
-  def startComplex(diComplex: DIComplex): Boolean = {
+  def startComplex(diComplex: DIComplex): Unit = {
 
     val elem = createElement(diComplex)
     stack.top.appendChild(elem)
     stack.push(elem)
-    true
   }
 
-  def endComplex(diComplex: DIComplex): Boolean = {
+  def endComplex(diComplex: DIComplex): Unit = {
     stack.pop
-    true
   }
 
-  def startArray(diArray: DIArray): Boolean = {
-    true
+  def startArray(diArray: DIArray): Unit = {
   }
-  def endArray(diArray: DIArray): Boolean = {
-    true
+  def endArray(diArray: DIArray): Unit = {
   }
 
   def getResult(): Document = {
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/XMLTextInfosetOutputter.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/XMLTextInfosetOutputter.scala
index 62154196f..5ad73e261 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/XMLTextInfosetOutputter.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/XMLTextInfosetOutputter.scala
@@ -152,7 +152,7 @@ class XMLTextInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean,
     }
   }
 
-  override def startSimple(simple: DISimple): Boolean = {
+  override def startSimple(simple: DISimple): Unit = {
     if (pretty) {
       writer.write(System.lineSeparator())
       outputIndentation(writer)
@@ -174,16 +174,13 @@ class XMLTextInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean,
 
     outputEndTag(simple)
     inScopeComplexElementHasChildren = true
-
-    true
   }
   
-  override def endSimple(simple: DISimple): Boolean = {
+  override def endSimple(simple: DISimple): Unit = {
     // do nothing, everything is done in startSimple
-    true
   }
 
-  override def startComplex(complex: DIComplex): Boolean = {
+  override def startComplex(complex: DIComplex): Unit = {
     if (pretty) {
       writer.write(System.lineSeparator())
       outputIndentation(writer)
@@ -191,11 +188,9 @@ class XMLTextInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean,
     outputStartTag(complex)
     incrementIndentation()
     inScopeComplexElementHasChildren = false
-
-    true
   }
 
-  override def endComplex(complex: DIComplex): Boolean = {
+  override def endComplex(complex: DIComplex): Unit = {
     decrementIndentation()
     if (pretty && inScopeComplexElementHasChildren) {
       // only output newline and indentation for non-empty complex types
@@ -204,28 +199,22 @@ class XMLTextInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean,
     }
     outputEndTag(complex)
     inScopeComplexElementHasChildren = true
-
-    true
   }
 
-  override def startArray(array: DIArray): Boolean = {
+  override def startArray(array: DIArray): Unit = {
     // do nothing
-    true
   }
 
-  override def endArray(array: DIArray): Boolean = {
+  override def endArray(array: DIArray): Unit = {
     // do nothing
-    true
   }
 
-  override def startDocument(): Boolean = {
+  override def startDocument(): Unit = {
     writer.write("""<?xml version="1.0" encoding="UTF-8"?>""")
-    true
   }
 
-  override def endDocument(): Boolean = {
+  override def endDocument(): Unit = {
     writer.write(System.lineSeparator())
     writer.flush()
-    true
   }
 }
diff --git 
a/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/infoset/Infoset.scala 
b/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/infoset/Infoset.scala
index 565785b44..4a6e8fef3 100644
--- 
a/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/infoset/Infoset.scala
+++ 
b/daffodil-sapi/src/main/scala/org/apache/daffodil/sapi/infoset/Infoset.scala
@@ -123,85 +123,90 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
   /**
    * Called by Daffodil internals to signify the beginning of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
    */
-  def startDocument(): Boolean
+  @throws[Exception]
+  def startDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the end of the infoset.
    *
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
    */
-  def endDocument(): Boolean
+  @throws[Exception]
+  def endDocument(): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a simple element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diSimple the simple element that is started. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-
-  def startSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def startSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a simple element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diSimple the simple element that is ended. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endSimple(diSimple: DISimple): Boolean
+  @throws[Exception]
+  def endSimple(diSimple: DISimple): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a complex 
element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def startComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def startComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a complex element.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diComplex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endComplex(diComplex: DIComplex): Boolean
+  @throws[Exception]
+  def endComplex(diComplex: DIComplex): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of an array of 
elements.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diArray the array that is started. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def startArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def startArray(diArray: DIArray): Unit
 
   /**
    * Called by Daffodil internals to signify the end of an array of elements.
    *
+   * Throws java.lang.Exception if there was an error and Daffodil should stop 
parsing
+   *
    * @param diArray the array that is ended. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
-   * @return true on sucess, false if there was an error and Daffodil should 
stop all
-   *         future calls to the InfosetOutputter
    */
-  def endArray(diArray: DIArray): Boolean
+  @throws[Exception]
+  def endArray(diArray: DIArray): Unit
 }
 
 /**
@@ -475,12 +480,12 @@ abstract class InfosetOutputterProxy extends 
InfosetOutputter {
   protected val infosetOutputter: SInfosetOutputter
 
   override def reset(): Unit = infosetOutputter.reset()
-  override def startDocument(): Boolean = infosetOutputter.startDocument()
-  override def endDocument(): Boolean = infosetOutputter.endDocument()
-  override def startSimple(diSimple: DISimple): Boolean = 
infosetOutputter.startSimple(diSimple)
-  override def endSimple(diSimple: DISimple): Boolean = 
infosetOutputter.endSimple(diSimple)
-  override def startComplex(diComplex: DIComplex): Boolean = 
infosetOutputter.startComplex(diComplex)
-  override def endComplex(diComplex: DIComplex): Boolean = 
infosetOutputter.endComplex(diComplex)
-  override def startArray(diArray: DIArray): Boolean = 
infosetOutputter.startArray(diArray)
-  override def endArray(diArray: DIArray): Boolean = 
infosetOutputter.endArray(diArray)
+  override def startDocument(): Unit = infosetOutputter.startDocument()
+  override def endDocument(): Unit = infosetOutputter.endDocument()
+  override def startSimple(diSimple: DISimple): Unit = 
infosetOutputter.startSimple(diSimple)
+  override def endSimple(diSimple: DISimple): Unit = 
infosetOutputter.endSimple(diSimple)
+  override def startComplex(diComplex: DIComplex): Unit = 
infosetOutputter.startComplex(diComplex)
+  override def endComplex(diComplex: DIComplex): Unit = 
infosetOutputter.endComplex(diComplex)
+  override def startArray(diArray: DIArray): Unit = 
infosetOutputter.startArray(diArray)
+  override def endArray(diArray: DIArray): Unit = 
infosetOutputter.endArray(diArray)
 }
diff --git 
a/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestInfosetInputterOutputter.scala
 
b/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestInfosetInputterOutputter.scala
index 249ed9dcb..81bdd3226 100644
--- 
a/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestInfosetInputterOutputter.scala
+++ 
b/daffodil-sapi/src/test/scala/org/apache/daffodil/example/TestInfosetInputterOutputter.scala
@@ -90,56 +90,48 @@ case class TestInfosetOutputter() extends InfosetOutputter {
     events.clear()
   }
 
-  override def startDocument(): Boolean = {
+  override def startDocument(): Unit = {
     events.append(TestInfosetEvent.startDocument())
-    true
   }
 
-  override def endDocument(): Boolean = {
+  override def endDocument(): Unit = {
     events.append(TestInfosetEvent.endDocument())
-    true
   }
 
-  override def startSimple(diSimple: DISimple): Boolean = {
+  override def startSimple(diSimple: DISimple): Unit = {
     events.append(
       TestInfosetEvent.startSimple(
         diSimple.erd.name,
         diSimple.erd.namedQName.namespace,
         diSimple.dataValueAsString,
         if (diSimple.erd.isNillable) MaybeBoolean(diSimple.isNilled) else 
MaybeBoolean.Nope))
-    true
   }
 
-  override def endSimple(diSimple: DISimple): Boolean = {
+  override def endSimple(diSimple: DISimple): Unit = {
     events.append(
       TestInfosetEvent.endSimple(
         diSimple.erd.name,
         diSimple.erd.namedQName.namespace))
-    true
   }
 
-  override def startComplex(diComplex: DIComplex): Boolean = {
+  override def startComplex(diComplex: DIComplex): Unit = {
     events.append(
       TestInfosetEvent.startComplex(
         diComplex.erd.name,
         diComplex.erd.namedQName.namespace,
         if (diComplex.erd.isNillable) MaybeBoolean(diComplex.isNilled) else 
MaybeBoolean.Nope))
-    true
   }
 
-  override def endComplex(diComplex: DIComplex): Boolean = {
+  override def endComplex(diComplex: DIComplex): Unit = {
     events.append(
       TestInfosetEvent.endComplex(
         diComplex.erd.name,
         diComplex.erd.namedQName.namespace))
-    true
   }
 
-  override def startArray(diArray: DIArray): Boolean = {
-    true
+  override def startArray(diArray: DIArray): Unit = {
   }
 
-  override def endArray(diArray: DIArray): Boolean = {
-    true
+  override def endArray(diArray: DIArray): Unit = {
   }
 }
diff --git 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/TDMLInfosetOutputter.scala
 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/TDMLInfosetOutputter.scala
index 93e7dcbbd..32ef0e790 100644
--- 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/TDMLInfosetOutputter.scala
+++ 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/TDMLInfosetOutputter.scala
@@ -20,10 +20,6 @@ package org.apache.daffodil.tdml
 import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
 
-import org.apache.daffodil.infoset.DIArray
-import org.apache.daffodil.infoset.DIComplex
-import org.apache.daffodil.infoset.DISimple
-import org.apache.daffodil.infoset.InfosetOutputter
 import org.apache.daffodil.infoset.JDOMInfosetInputter
 import org.apache.daffodil.infoset.JDOMInfosetOutputter
 import org.apache.daffodil.infoset.JsonInfosetInputter
@@ -35,73 +31,20 @@ import org.apache.daffodil.infoset.W3CDOMInfosetInputter
 import org.apache.daffodil.infoset.W3CDOMInfosetOutputter
 import org.apache.daffodil.infoset.XMLTextInfosetInputter
 import org.apache.daffodil.infoset.XMLTextInfosetOutputter
+import org.apache.daffodil.infoset.TeeInfosetOutputter
 
-class TDMLInfosetOutputter() extends InfosetOutputter {
+class TDMLInfosetOutputter extends {
+    private val jsonStream = new ByteArrayOutputStream()
+    val xmlStream = new ByteArrayOutputStream()
 
-  private def implString: String = "daffodil"
+    private val scalaOut = new ScalaXMLInfosetOutputter()
+    private val jdomOut = new JDOMInfosetOutputter()
+    private val w3cdomOut = new W3CDOMInfosetOutputter()
+    private val jsonOut = new JsonInfosetOutputter(jsonStream, false)
+    private val xmlOut = new XMLTextInfosetOutputter(xmlStream, false)
 
-  private val jsonStream = new ByteArrayOutputStream()
-  val xmlStream = new ByteArrayOutputStream()
-
-  private val scalaOut = new ScalaXMLInfosetOutputter()
-  private val jdomOut = new JDOMInfosetOutputter()
-  private val w3cdomOut = new W3CDOMInfosetOutputter()
-  private val jsonOut = new JsonInfosetOutputter(jsonStream, false)
-  private val xmlOut = new XMLTextInfosetOutputter(xmlStream, false)
-
-  private val outputters = Seq(xmlOut, scalaOut, jdomOut, w3cdomOut, jsonOut)
-
-  override def reset(): Unit = {
-    outputters.foreach(_.reset())
-  }
-
-  override def startSimple(simple: DISimple): Boolean = {
-    if (!outputters.forall(_.startSimple(simple)))
-      throw TDMLException("startSimple failed", Some(implString))
-    true
-  }
-
-  override def endSimple(simple: DISimple): Boolean = {
-    if (!outputters.forall(_.endSimple(simple)))
-      throw TDMLException("endSimple failed", Some(implString))
-    true
-  }
-
-  override def startComplex(complex: DIComplex): Boolean = {
-    if (!outputters.forall(_.startComplex(complex)))
-      throw TDMLException("startComplex failed", Some(implString))
-    true
-  }
-
-  override def endComplex(complex: DIComplex): Boolean = {
-    if (!outputters.forall(_.endComplex(complex)))
-      throw TDMLException("endComplex failed", Some(implString))
-    true
-  }
-
-  override def startArray(array: DIArray): Boolean = {
-    if (!outputters.forall(_.startArray(array)))
-      throw TDMLException("startArray failed", Some(implString))
-    true
-  }
-
-  override def endArray(array: DIArray): Boolean = {
-    if (!outputters.forall(_.endArray(array)))
-      throw TDMLException("endArray failed", Some(implString))
-    true
-  }
-
-  override def startDocument(): Boolean = {
-    if (!outputters.forall(_.startDocument()))
-      throw TDMLException("startDocument failed", Some(implString))
-    true
-  }
-
-  override def endDocument(): Boolean = {
-    if (!outputters.forall(_.endDocument()))
-      throw TDMLException("endDocument failed", Some(implString))
-    true
-  }
+    private val outputters = Seq(xmlOut, scalaOut, jdomOut, w3cdomOut, jsonOut)
+  } with TeeInfosetOutputter(outputters: _*) {
 
   def getResult() = scalaOut.getResult
 

Reply via email to