mbeckerle commented on code in PR #908:
URL: https://github.com/apache/daffodil/pull/908#discussion_r1067103209
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetInputter.scala:
##########
@@ -21,79 +21,70 @@ import java.net.URI
import java.net.URISyntaxException
import org.apache.daffodil.api.DFDL
-import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
-import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.dpath.NodeInfo
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.processors.DaffodilUnparseContentHandler
+import org.apache.daffodil.util.Coroutine
+import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.MaybeBoolean
import org.apache.daffodil.util.Misc
import org.apache.daffodil.xml.XMLUtils
/**
- * The SAXInfosetInputter consumes SAXInfosetEvent objects from the
DaffodilUnparseContentHandler
- * class and converts them to events that the DataProcessor unparse can use.
This class contains an
- * array of batched SAXInfosetEvent objects that it receives from the
contentHandler and the index
- * of the current element being processed.
+ * The SAXInfosetInputter consumes SAXInfosetEvent objects from the
+ * DaffodilUnparseContentHandler class and converts them to events that the
+ * DataProcessor unparse can use.
+ *
+ * See the DaffodilUnparseContentHandler for a detailed description of how
these two
+ * classes interact.
*
- * This class, together with the SAXInfosetInputter, uses coroutines to ensure
that a batch of events
- * (based on the tunable saxUnparseEventBatchSize) can be passed from the
former to the latter.
- * The following is the general process:
- *
- * - the run method is called, with the first batch of events, starting with
the StartDocument event,
- * already loaded on the inputter's queue.
- * This is collected and stored in the batchedInfosetEvents member, and the
currentIndex is set to 0
- * - The dp.unparse method is called, and it calls hasNext to make sure an
event exists to be
- * processed and then queries the event at currentIndex. The hasNext call also
checks that there is
- * a next event to be processed (currentIndex+1), and if not, queues the next
batch of events by
- * transferring control to the contentHandler so it can load them.
- * - After it is done with the current event, it calls inputter.next to get
the next event, and that
- * increments the currentIndex and cleans out the event at the previous index
- * - This process continues until the event at currentIndex either contains an
EndDocument event or
- * the currentIndex is the last in the batch. If it is the former, the
endDocumentReceived flag is
- * set to true and hasNext will return false. If it is the latter, the next
batch of events will be
- * queued by transferring control to the contentHandler so it can load them.
- * - This ends the unparse process, and the unparseResult and/or any Errors
are set on a single element
- * array containing response events. We call resumeFinal passing along that
array, terminating this
- * thread and resuming the contentHandler for the last time.
- *
- * @param unparseContentHandler producer coroutine that sends the
SAXInfosetEvent to this class
- * @param dp dataprocessor that we use to kickstart the unparse process and
that consumes the
- * currentEvent
- * @param output outputChannel of choice where the unparsed data is stored
+ * @param unparseContentHandler producer coroutine that sends the
SAXInfosetEvents to this class
+ * @param dp DataProcessor that we use to kickstart the unparse process to
consumes the events
+ * @param output OutputChannel where the unparsed data is written
+ * @param resolveRelaiveInfosetBlobURIs if true, elements with type xs:anyURI
type and a
+ * relativeURI are resolved relative to the classpath. This should only be
true when used
+ * via a TDMLRunner or similar testing infrastructure
*/
class SAXInfosetInputter(
- unparseContentHandler: DFDL.DaffodilUnparseContentHandler,
+ unparseContentHandler: DaffodilUnparseContentHandler,
dp: DFDL.DataProcessor,
- output: DFDL.Output)
- extends InfosetInputter with DFDL.ConsumerCoroutine {
+ output: DFDL.Output,
+ resolveRelativeInfosetBlobURIs: Boolean)
+ extends InfosetInputter with Coroutine[Array[SAXInfosetEvent]] {
/**
- * allows support for converting relative URIs in Blobs to absolute URIs,
this is necessary
- * for running TDML tests as they allow relative URIs. Because Daffodil
proper only uses
- * absolute URIs, we hide this functionality behind this flag. It can be set
to true by calling
- * the
unparseContentHandler.enableInputterResolutionOfRelativeInfosetBlobURIs(),
which calls the
- * inputter's enableResolutionOfRelativeInfosetBlobURIs() function to set
the below variable to true
+ * The index into batchedInfosetEvents that the InfosetInputter is currently
returning
+ * information about to the unparse()
*/
- private var resolveRelativeInfosetBlobURIs: Boolean = false
-
- private var endDocumentReceived = false
private var currentIndex: Int = 0
+
+ /**
+ * The array of batched infoset events received from the ContentHandler.
+ */
Review Comment:
So if we make this batch size large enough, would this consume the entire
unparser input infoset events, create one batch object, and hand it off to the
coroutine exactly once? That would minimize the overhead, and be sensible for
almost all "small message" situations.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/SAXInfosetInputter.scala:
##########
@@ -21,79 +21,70 @@ import java.net.URI
import java.net.URISyntaxException
import org.apache.daffodil.api.DFDL
-import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
-import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.dpath.NodeInfo
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.processors.DaffodilUnparseContentHandler
+import org.apache.daffodil.util.Coroutine
+import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.One
+import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.MaybeBoolean
import org.apache.daffodil.util.Misc
import org.apache.daffodil.xml.XMLUtils
/**
- * The SAXInfosetInputter consumes SAXInfosetEvent objects from the
DaffodilUnparseContentHandler
- * class and converts them to events that the DataProcessor unparse can use.
This class contains an
- * array of batched SAXInfosetEvent objects that it receives from the
contentHandler and the index
- * of the current element being processed.
+ * The SAXInfosetInputter consumes SAXInfosetEvent objects from the
+ * DaffodilUnparseContentHandler class and converts them to events that the
+ * DataProcessor unparse can use.
Review Comment:
typo: unparser
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -28,156 +28,223 @@ import org.xml.sax.Locator
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.infoset.SAXInfosetEvent
import org.apache.daffodil.infoset.SAXInfosetInputter
import org.apache.daffodil.util.MStackOf
+import org.apache.daffodil.util.MainCoroutine
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the
SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The
SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an
XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the
XMLReader must have
- * support for XML Namespaces
+ * Unparse SAX events received from an XMLReader using a provided
DataProcessor and
+ * Output channel
*
- * This class, together with the SAXInfosetInputter, uses coroutines to ensure
that a batch of events
- * (based on the tunable saxUnparseEventBatchSize) can be passed from the
former to the latter.
- * The following is the general process:
+ * Note: XMLReaders using this as their ContentHandler must have support for
XML
+ * namespaces so that we receive namespace URI and prefix information that
Daffodil
+ * requires to unparse.
*
- * - an external call is made to parse an XML Document
- * - this class receives a StartDocument call, which is the first
SAXInfosetEvent that should be
- * sent to the SAXInfosetInputter. That event is put onto an array of
SAXInfosetEvents of size the
- * saxUnparseEventBatchSize tunable. Once the array is full, it is put on the
inputter's queue,
- * this thread is paused, and that inputter's thread is run
- * - when the SAXInfosetInputter is done processing that batch and is ready
for a new batch, it
- * sends a 1 element array with the last completed event via the coroutine
system, which loads it on
- * the contentHandler's queue, which restarts this thread and pauses that one.
In the expected case,
- * the single element array will contain no new information until the unparse
complete. In the case of
- * an unexpected error though, it will contain error information
- * - this process continues until the EndDocument SAXInfosetEvent is loaded
into the batch.
- * Once that SAXInfosetEvent is processed by the SAXInfosetInputter, it
signals the end of batched
- * events coming from the contentHandler. This ends the unparseProcess and
returns the event with
- * the unparseResult and/or any error
- * information
+ * The SAX ContentHandler API is push-based, but the Daffodil InfosetInputter
unparse
+ * API is pull-based, so these two API's are at odds with one another. To link
the
+ * two, we create two classes that implement a coroutine-like API to
communicate and
+ * ensure that the push and pull sides of the two APIs never run at the same
time
+ * (see Coroutine.scala for implementation details). The "producer" coroutine
is this
+ * DaffodilUnparseContentHandler and runs on the same thread as an XMLReader to
+ * receive and batch SAX events. The "consumer" coroutine is an instance of the
Review Comment:
The detail that one of these coroutines is actually the main co-routine,
and the other is the "peer" coroutine object, and which one is producer and
which one consumer, would help here also.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -28,156 +28,223 @@ import org.xml.sax.Locator
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.infoset.SAXInfosetEvent
import org.apache.daffodil.infoset.SAXInfosetInputter
import org.apache.daffodil.util.MStackOf
+import org.apache.daffodil.util.MainCoroutine
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the
SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The
SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an
XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the
XMLReader must have
- * support for XML Namespaces
+ * Unparse SAX events received from an XMLReader using a provided
DataProcessor and
+ * Output channel
*
- * This class, together with the SAXInfosetInputter, uses coroutines to ensure
that a batch of events
- * (based on the tunable saxUnparseEventBatchSize) can be passed from the
former to the latter.
- * The following is the general process:
+ * Note: XMLReaders using this as their ContentHandler must have support for
XML
+ * namespaces so that we receive namespace URI and prefix information that
Daffodil
+ * requires to unparse.
*
- * - an external call is made to parse an XML Document
- * - this class receives a StartDocument call, which is the first
SAXInfosetEvent that should be
- * sent to the SAXInfosetInputter. That event is put onto an array of
SAXInfosetEvents of size the
- * saxUnparseEventBatchSize tunable. Once the array is full, it is put on the
inputter's queue,
- * this thread is paused, and that inputter's thread is run
- * - when the SAXInfosetInputter is done processing that batch and is ready
for a new batch, it
- * sends a 1 element array with the last completed event via the coroutine
system, which loads it on
- * the contentHandler's queue, which restarts this thread and pauses that one.
In the expected case,
- * the single element array will contain no new information until the unparse
complete. In the case of
- * an unexpected error though, it will contain error information
- * - this process continues until the EndDocument SAXInfosetEvent is loaded
into the batch.
- * Once that SAXInfosetEvent is processed by the SAXInfosetInputter, it
signals the end of batched
- * events coming from the contentHandler. This ends the unparseProcess and
returns the event with
- * the unparseResult and/or any error
- * information
+ * The SAX ContentHandler API is push-based, but the Daffodil InfosetInputter
unparse
+ * API is pull-based, so these two API's are at odds with one another. To link
the
+ * two, we create two classes that implement a coroutine-like API to
communicate and
+ * ensure that the push and pull sides of the two APIs never run at the same
time
+ * (see Coroutine.scala for implementation details). The "producer" coroutine
is this
+ * DaffodilUnparseContentHandler and runs on the same thread as an XMLReader to
+ * receive and batch SAX events. The "consumer" coroutine is an instance of the
+ * SAXInfosetInputter which calls the actual unparse() function to consume
these
+ * batched SAX events and unparse data.
+ *
+ * Below is a description of how this class is used and the interaction
between these
+ * two classes to unparse using the SAX API:
+ *
+ * 1. A DaffodilUnparseContentHandler instance is created, which initializes a
+ * SAXInfosetInputter coroutine instance.
+ *
+ * 2. An XMLReader instance is created and configured to send events to the
+ * DaffodilUnparseContentHandler.
+ *
+ * 3. The DaffodilUnparseContentHandler receives events from the XMLReader,
gathers
+ * the necessary information from those events, and fills out an array of
+ * SAXInfosetEvent objects, called a "batch".
+ *
+ * 4. When a full batch has been gathered, or an endDocument() event is
received, the
+ * DaffodilUnparseContentHandler calls resume() to pause execution and
resume the
+ * SAXInfosetInputter coroutine, passing it the batch of events.
+ *
+ * 5. Since this is the first time the SAXInfosetInputter has been given
control, its
+ * coroutine Thread is started and its run() function called. This calls
+ * waitResume() to get the first batch of events which it immediately
receives. It
+ * then calls the DataProcessor unparse() function to begin the unparse.
+ *
+ * 6. The SAXInfosetInputter functions are called by unparse, which read the
batched
+ * events and provide the necessary information to unparse the infoset.
Once the
+ * SAXInfosetInputter has consumed and used the full batch of events and
needs a
+ * new event in the next() function, it calls resume() to pause execution
and
+ * resume the DaffodilUnparseContentHandler coroutine,
+ * passing it Nope signifying it needs more events.
+ *
+ * 7. The DaffodilUnparseContentHandler resumes and again continues to receive
SAX
+ * events and fill out the batched events array until it is full or
endDocument()
+ * is received, at which point it calls resume() to pause and return
control back
+ * to the SAXInfosetInputter where it can read the new batch of events.
+ *
+ * 8. Steps 6 and 7 repeat until the SAXInfosetInputter signals back to the
+ * DaffodilUnparseContentHandler that it is complete by returning a One
object
+ * containing either an UnparseResult or an Exception. At this point, the
+ * SAXInfosetInputter is complete and calls resumeFinal() to provide
control back
+ * to the DaffodilUnparseContentHandler--the SAXInfosetInputter
+ * coroutine is done.
+ *
+ * 9. The DaffodilUnparseContentHandler resumes, examines the result from the
+ * SAXInfosetInputter, and either makes the UnparseResult available to the
+ * XMLReader or throws a SAXException if there was an error.
*
* @param dp dataprocessor object that will be used to call the parse
* @param output outputChannel of choice where the unparsed data is stored
*/
class DaffodilUnparseContentHandler(
dp: DFDL.DataProcessor,
output: DFDL.Output)
- extends DFDL.DaffodilUnparseContentHandler {
- private lazy val inputter = new SAXInfosetInputter(this, dp, output)
- private var unparseResult: DFDL.UnparseResult = _
+ extends MainCoroutine[Maybe[Either[Exception, DFDL.UnparseResult]]]
+ with DFDL.DaffodilUnparseContentHandler {
+
+ /**
+ * The SAXInfosetInputter coroutine that consumes the batches of
SAXInfosetEvents.
+ * The coroutine thread will not be created until the
+ * DaffodilUnparseContentHandler calls resume with the first batch of events
+ */
+ private lazy val inputter: SAXInfosetInputter = new SAXInfosetInputter(this,
dp, output, resolveRelativeInfosetBlobURIs)
Review Comment:
Line too long.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -28,156 +28,223 @@ import org.xml.sax.Locator
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.infoset.SAXInfosetEvent
import org.apache.daffodil.infoset.SAXInfosetInputter
import org.apache.daffodil.util.MStackOf
+import org.apache.daffodil.util.MainCoroutine
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the
SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The
SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an
XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the
XMLReader must have
- * support for XML Namespaces
+ * Unparse SAX events received from an XMLReader using a provided
DataProcessor and
+ * Output channel
*
- * This class, together with the SAXInfosetInputter, uses coroutines to ensure
that a batch of events
- * (based on the tunable saxUnparseEventBatchSize) can be passed from the
former to the latter.
- * The following is the general process:
+ * Note: XMLReaders using this as their ContentHandler must have support for
XML
+ * namespaces so that we receive namespace URI and prefix information that
Daffodil
+ * requires to unparse.
*
- * - an external call is made to parse an XML Document
- * - this class receives a StartDocument call, which is the first
SAXInfosetEvent that should be
- * sent to the SAXInfosetInputter. That event is put onto an array of
SAXInfosetEvents of size the
- * saxUnparseEventBatchSize tunable. Once the array is full, it is put on the
inputter's queue,
- * this thread is paused, and that inputter's thread is run
- * - when the SAXInfosetInputter is done processing that batch and is ready
for a new batch, it
- * sends a 1 element array with the last completed event via the coroutine
system, which loads it on
- * the contentHandler's queue, which restarts this thread and pauses that one.
In the expected case,
- * the single element array will contain no new information until the unparse
complete. In the case of
- * an unexpected error though, it will contain error information
- * - this process continues until the EndDocument SAXInfosetEvent is loaded
into the batch.
- * Once that SAXInfosetEvent is processed by the SAXInfosetInputter, it
signals the end of batched
- * events coming from the contentHandler. This ends the unparseProcess and
returns the event with
- * the unparseResult and/or any error
- * information
+ * The SAX ContentHandler API is push-based, but the Daffodil InfosetInputter
unparse
+ * API is pull-based, so these two API's are at odds with one another. To link
the
+ * two, we create two classes that implement a coroutine-like API to
communicate and
+ * ensure that the push and pull sides of the two APIs never run at the same
time
+ * (see Coroutine.scala for implementation details). The "producer" coroutine
is this
+ * DaffodilUnparseContentHandler and runs on the same thread as an XMLReader to
+ * receive and batch SAX events. The "consumer" coroutine is an instance of the
+ * SAXInfosetInputter which calls the actual unparse() function to consume
these
+ * batched SAX events and unparse data.
+ *
+ * Below is a description of how this class is used and the interaction
between these
+ * two classes to unparse using the SAX API:
+ *
+ * 1. A DaffodilUnparseContentHandler instance is created, which initializes a
+ * SAXInfosetInputter coroutine instance.
+ *
+ * 2. An XMLReader instance is created and configured to send events to the
+ * DaffodilUnparseContentHandler.
+ *
+ * 3. The DaffodilUnparseContentHandler receives events from the XMLReader,
gathers
Review Comment:
receives = "is passed" or "is called with these"
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilUnparseContentHandler.scala:
##########
@@ -28,156 +28,223 @@ import org.xml.sax.Locator
import org.apache.daffodil.api.DFDL
import org.apache.daffodil.api.DFDL.DaffodilUnhandledSAXException
import org.apache.daffodil.api.DFDL.DaffodilUnparseErrorSAXException
-import org.apache.daffodil.api.DFDL.SAXInfosetEvent
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.InfosetInputterEventType.EndDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.EndElement
import org.apache.daffodil.infoset.InfosetInputterEventType.StartDocument
import org.apache.daffodil.infoset.InfosetInputterEventType.StartElement
+import org.apache.daffodil.infoset.SAXInfosetEvent
import org.apache.daffodil.infoset.SAXInfosetInputter
import org.apache.daffodil.util.MStackOf
+import org.apache.daffodil.util.MainCoroutine
import org.apache.daffodil.util.Maybe
import org.apache.daffodil.util.Maybe.Nope
import org.apache.daffodil.util.Maybe.One
import org.apache.daffodil.util.Misc
/**
- * DaffodilUnparseContentHandler produces SAXInfosetEvent objects for the
SAXInfosetInputter to
- * consume and convert to events that the Dataprocessor unparse can use. The
SAXInfosetEvent object
- * is built from information that is passed to the ContentHandler from an
XMLReader parser. In
- * order to receive the uri and prefix information from the XMLReader, the
XMLReader must have
- * support for XML Namespaces
+ * Unparse SAX events received from an XMLReader using a provided
DataProcessor and
+ * Output channel
*
- * This class, together with the SAXInfosetInputter, uses coroutines to ensure
that a batch of events
- * (based on the tunable saxUnparseEventBatchSize) can be passed from the
former to the latter.
- * The following is the general process:
+ * Note: XMLReaders using this as their ContentHandler must have support for
XML
+ * namespaces so that we receive namespace URI and prefix information that
Daffodil
+ * requires to unparse.
*
- * - an external call is made to parse an XML Document
- * - this class receives a StartDocument call, which is the first
SAXInfosetEvent that should be
- * sent to the SAXInfosetInputter. That event is put onto an array of
SAXInfosetEvents of size the
- * saxUnparseEventBatchSize tunable. Once the array is full, it is put on the
inputter's queue,
- * this thread is paused, and that inputter's thread is run
- * - when the SAXInfosetInputter is done processing that batch and is ready
for a new batch, it
- * sends a 1 element array with the last completed event via the coroutine
system, which loads it on
- * the contentHandler's queue, which restarts this thread and pauses that one.
In the expected case,
- * the single element array will contain no new information until the unparse
complete. In the case of
- * an unexpected error though, it will contain error information
- * - this process continues until the EndDocument SAXInfosetEvent is loaded
into the batch.
- * Once that SAXInfosetEvent is processed by the SAXInfosetInputter, it
signals the end of batched
- * events coming from the contentHandler. This ends the unparseProcess and
returns the event with
- * the unparseResult and/or any error
- * information
+ * The SAX ContentHandler API is push-based, but the Daffodil InfosetInputter
unparse
+ * API is pull-based, so these two API's are at odds with one another. To link
the
+ * two, we create two classes that implement a coroutine-like API to
communicate and
+ * ensure that the push and pull sides of the two APIs never run at the same
time
+ * (see Coroutine.scala for implementation details). The "producer" coroutine
is this
+ * DaffodilUnparseContentHandler and runs on the same thread as an XMLReader to
+ * receive and batch SAX events. The "consumer" coroutine is an instance of the
+ * SAXInfosetInputter which calls the actual unparse() function to consume
these
+ * batched SAX events and unparse data.
+ *
+ * Below is a description of how this class is used and the interaction
between these
+ * two classes to unparse using the SAX API:
+ *
+ * 1. A DaffodilUnparseContentHandler instance is created, which initializes a
+ * SAXInfosetInputter coroutine instance.
+ *
+ * 2. An XMLReader instance is created and configured to send events to the
Review Comment:
I want to make sure we're using the word "send" vs. "pass" consistently here
if possible.
I think best usage is to keep the term "send" to mean passed over to the
peer coroutine as part of resuming it. The word "pass" here is technically
correct, one passes things to a coroutine, but distinguishing that from regular
calling, such as to a callback handler, is useful here if we can be consistent.
The term "pass" should mean passed as an argument to a method call.
I think an XMLReader passes things to a content handler. Not send.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]