mbeckerle commented on code in PR #1112:
URL: https://github.com/apache/daffodil/pull/1112#discussion_r1391376419


##########
daffodil-core/src/test/scala/org/apache/daffodil/core/api/TestMetadataWalking.scala:
##########
@@ -0,0 +1,228 @@
+/*
+ * 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.core.api
+
+import scala.collection.mutable.ArrayBuffer
+import scala.xml.Elem
+
+import org.apache.daffodil.core.util.TestUtils
+import org.apache.daffodil.io.InputSourceDataInputStream
+import org.apache.daffodil.lib.util._
+import org.apache.daffodil.runtime1.api.ChoiceMetadata
+import org.apache.daffodil.runtime1.api.ComplexElementMetadata
+import org.apache.daffodil.runtime1.api.DFDL.ParseResult
+import org.apache.daffodil.runtime1.api.ElementMetadata
+import org.apache.daffodil.runtime1.api.InfosetArray
+import org.apache.daffodil.runtime1.api.InfosetComplexElement
+import org.apache.daffodil.runtime1.api.InfosetElement
+import org.apache.daffodil.runtime1.api.InfosetItem
+import org.apache.daffodil.runtime1.api.InfosetSimpleElement
+import org.apache.daffodil.runtime1.api.Metadata
+import org.apache.daffodil.runtime1.api.MetadataHandler
+import org.apache.daffodil.runtime1.api.SequenceMetadata
+import org.apache.daffodil.runtime1.api.SimpleElementMetadata
+import org.apache.daffodil.runtime1.infoset.ExceptionOccurredMixin
+import org.apache.daffodil.runtime1.infoset.InfosetOutputter
+import org.apache.daffodil.runtime1.infoset.InfosetOutputterImpl
+import org.apache.daffodil.runtime1.processors.DataProcessor
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class TestMetadataWalking {
+
+  def compileAndWalkMetadata(schema: Elem, mh: MetadataHandler): DataProcessor 
= {
+    val dp = TestUtils.compileSchema(schema)
+    assertTrue(!dp.isError)
+    dp.walkMetadata(mh)
+    dp
+  }
+
+  def parseAndWalkData(dp: DataProcessor, infosetOutputter: InfosetOutputter)(
+    data: Array[Byte],
+  ): ParseResult = {
+    val isdis = InputSourceDataInputStream(data)
+    val res = dp.parse(isdis, infosetOutputter)
+    res
+  }
+
+  class GatherMetadata extends MetadataHandler {
+
+    private val buf = new ArrayBuffer[Metadata]();
+
+    def getResult: Seq[Metadata] = {
+      val res: Seq[Metadata] = buf.toVector // makes a copy
+      buf.clear()
+      res
+    }
+
+    override def simpleElementMetadata(m: SimpleElementMetadata): Unit = buf 
+= m
+
+    override def startComplexElementMetadata(m: ComplexElementMetadata): Unit 
= buf += m
+
+    override def endComplexElementMetadata(m: ComplexElementMetadata): Unit = 
buf += m
+
+    override def startSequenceMetadata(m: SequenceMetadata): Unit = buf += m
+
+    override def endSequenceMetadata(m: SequenceMetadata): Unit = buf += m
+
+    override def startChoiceMetadata(m: ChoiceMetadata): Unit = buf += m
+
+    override def endChoiceMetadata(m: ChoiceMetadata): Unit = buf += m

Review Comment:
   Actually, we do need the redundant name. Often I got confused between 
infoset event handlers and metadata event handlers when doing Drill work which 
uses both those APIs. That's why I added that suffix to all the names. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala:
##########
@@ -70,6 +70,11 @@ abstract class SequenceTermBase(
 
   def isOrdered: Boolean
 
+  /**
+   * Overridden in sequence group ref
+   */
+  def isHidden: Boolean = false

Review Comment:
   There are such tests already: parseSeqOfHiddenAndRegularRef  is one. 



##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala:
##########
@@ -154,69 +153,69 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
   /**
    * Called by Daffodil internals to signify the beginning of a simple element.
    *
-   * @param diSimple the simple element that is started. Various fields of
+   * @param simple the simple element that is started. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
 
   @throws[Exception]
-  def startSimple(diSimple: DISimple): Unit
+  def startSimple(simple: InfosetSimpleElement): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a simple element.
    *
-   * @param diSimple the simple element that is ended. Various fields of
+   * @param simple the simple element that is ended. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
   @throws[Exception]
-  def endSimple(diSimple: DISimple): Unit
+  def endSimple(simple: InfosetSimpleElement): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of a complex 
element.
    *
-   * @param diComplex the complex element that is started. Various fields of
+   * @param complex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
   @throws[Exception]
-  def startComplex(diComplex: DIComplex): Unit
+  def startComplex(complex: InfosetComplexElement): Unit
 
   /**
    * Called by Daffodil internals to signify the end of a complex element.
    *
-   * @param diComplex the complex element that is ended. Various fields of
+   * @param complex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
   @throws[Exception]
-  def endComplex(diComplex: DIComplex): Unit
+  def endComplex(complex: InfosetComplexElement): Unit
 
   /**
    * Called by Daffodil internals to signify the beginning of an array of 
elements.
    *
-   * @param diArray the array that is started. Various fields of
+   * @param array the array that is started. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
   @throws[Exception]
-  def startArray(diArray: DIArray): Unit
+  def startArray(array: InfosetArray): Unit
 
   /**
    * Called by Daffodil internals to signify the end of an array of elements.
    *
-   * @param diArray the array that is ended. Various fields of
+   * @param array the array that is ended. Various fields of
    *                DIArray can be accessed to determine things like the
    *                name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
   @throws[Exception]
-  def endArray(diArray: DIArray): Unit
+  def endArray(array: InfosetArray): Unit

Review Comment:
   Deprecation/Compat section added.
   We can put these added variants back in, but deprecated, at a later time if 
we think we need them. I don't want to clutter the API with them at this time. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.runtime1.api
+
+import scala.xml.NamespaceBinding
+
+/**
+ * This is the supportable API for access to the RuntimeData structures
+ * which provide access to static information about a given .
+ *
+ * This is used to interface other data processing fabrics to Daffodil
+ * data and metadata, by mapping to/from these metadata objects.
+ */
+trait Metadata {
+
+  /**
+   * Provides the file context of a metadata component. This refers to the 
specific
+   * DFDL schema file where the corresponding DFDL schema text resides 
corresponding
+   * to this metadata object.
+   * <p/>
+   * This is for use in diagnostic messaging. It is not the actual file URI, 
because
+   * those may contain personal-identifying information about the 
person/acccount and
+   * system that compiled the schema. It will provide enough content about the 
file URI that
+   * a user will be able to identify which file, but some prefix of the path
+   * components trimmed to make it of a manageable length.
+   * <p/>
+   * Used along with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]]
+   * and 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineColumnNumber]],
+   * this can give a precise location in the DFDL schema file.
+   * @return a string containing the file information, or null if unknown.
+   */
+  def schemaFileInfo: String
+
+  /**
+   * Provides the line number to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileInfo]].
+   * @return the line number as a string, or null if unknown.
+   */
+  def schemaFileLineNumber: String
+
+  /**
+   * Provides the column number within the text line, to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]].
+   * @return the column number within the text line, as a string, or null if 
unknown.
+   */
+  def schemaFileLineColumnNumber: String
+
+  /**
+   * The name of the schema component, in a form suitable for diagnostic 
messages.
+   * Unnamed components like sequence or choice groups have a 
diagnosticDebugName, despite not having
+   * any actual name.
+   * @return the name of the component, suitable for use in diagnostic 
messages.
+   */
+  def diagnosticDebugName: String
+
+  /**
+   * The standard conversion of the metadata component to a string.
+   * Unless overridden this uses the 
[[org.apache.daffodil.runtime1.api.Metadata.diagnosticDebugName]].
+   * @return string representation of this metadata component.
+   */
+  override def toString = diagnosticDebugName
+}
+
+/*
+ * Provides metadata access that is common to all Terms, which include
+ * Elements of simple or complex type, as well as the Sequence and Choice 
groups.
+ */
+trait TermMetadata extends Metadata {
+  // nothing here
+}
+
+/**
+ * Common metadata access for all elements, of simple or complex type.
+ */
+trait ElementMetadata extends TermMetadata {
+
+  /**
+   * @return the name of this element. In the case of a global/qualified name, 
this is only the local
+   *         part of the QName.
+   */
+  def name: String
+
+  /**
+   * @return the namespace URI as a string, or null if no namespace.
+   */
+  def namespace: String
+
+  /**
+   * @return the namespace bindings needed to construct an XML element from a 
Daffodil infoset
+   *         element of simple or complex type.
+   */
+  def minimizedScope: NamespaceBinding
+
+  /**
+   * @return the namespace prefix part of the XML QName of this component, or 
null if there
+   *         is no prefix defined or no namespace.
+   */
+  def prefix: String
+
+  /**
+   *  @return true if two or more occurrences are possible.
+   *          Note that having only 0 or 1 occurrence is not considered an 
array,
+   *          but rather an optional element.
+   */
+  def isArray: Boolean
+
+  /**
+   * @return true if only 0 or 1 occurrence are possible.
+   */
+  def isOptional: Boolean
+
+  /**
+   * @return the QName string for this element.
+   */
+  def toQName: String
+
+  /**
+   * @return true if the element is declared to be nillable.
+   */
+  def isNillable: Boolean
+
+  /**
+   * Provides access to the runtime properties. This is an extended collection 
of
+   * name-value pairs which are associated with a schema component.
+   * <p/>
+   * Runtime properties are intended to use for new ad-hoc property extensions 
to
+   * DFDL. These name-value pairs are visible to infoset outputters as well.
+   *
+   * @return a java-compatible map of name-value pairs.
+   */
+  def runtimeProperties: java.util.Map[String, String]
+
+}
+
+/**
+ * Access to metadata values exclusive to elements of complex type.
+ */
+trait ComplexElementMetadata extends ElementMetadata {
+
+  /**
+   * @return an ordered sequence of the child elements within this complex 
type regardless
+   *         of their nesting within sequence and choice groups.
+   */
+  def childMetadata: Seq[ElementMetadata]
+}
+
+/**
+ * Access to metadata values exclusive to elements of simple type.
+ */
+trait SimpleElementMetadata extends ElementMetadata {
+
+  /**
+   * The primitive type of this element as a string.
+   *
+   * @return one of boolean, double, float, date, time, dateTime, string, 
anyURI, hexBinary, decimal,
+   *         integer, nonNegativeInteger, byte, short, int, long, 
unsignedByte, unsignedShort,
+   *         unsignedInt, unsignedLong as a string. Note the initial 
lower-case letter in all these
+   *         type names.
+   */
+  def primTypeName: String
+}
+
+/**
+ * Access to metadata values shared by both sequences and choices
+ * which are known collectively as Model Groups.
+ */
+trait ModelGroupMetadata extends TermMetadata {}

Review Comment:
   Not necessary now. Can be added in the future if needed. 
   



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.runtime1.api
+
+import scala.xml.NamespaceBinding
+
+/**
+ * This is the supportable API for access to the RuntimeData structures
+ * which provide access to static information about a given .
+ *
+ * This is used to interface other data processing fabrics to Daffodil
+ * data and metadata, by mapping to/from these metadata objects.
+ */
+trait Metadata {
+
+  /**
+   * Provides the file context of a metadata component. This refers to the 
specific
+   * DFDL schema file where the corresponding DFDL schema text resides 
corresponding
+   * to this metadata object.
+   * <p/>
+   * This is for use in diagnostic messaging. It is not the actual file URI, 
because
+   * those may contain personal-identifying information about the 
person/acccount and
+   * system that compiled the schema. It will provide enough content about the 
file URI that
+   * a user will be able to identify which file, but some prefix of the path
+   * components trimmed to make it of a manageable length.
+   * <p/>
+   * Used along with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]]
+   * and 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineColumnNumber]],
+   * this can give a precise location in the DFDL schema file.
+   * @return a string containing the file information, or null if unknown.
+   */
+  def schemaFileInfo: String
+
+  /**
+   * Provides the line number to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileInfo]].
+   * @return the line number as a string, or null if unknown.
+   */
+  def schemaFileLineNumber: String
+
+  /**
+   * Provides the column number within the text line, to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]].
+   * @return the column number within the text line, as a string, or null if 
unknown.
+   */
+  def schemaFileLineColumnNumber: String
+
+  /**
+   * The name of the schema component, in a form suitable for diagnostic 
messages.
+   * Unnamed components like sequence or choice groups have a 
diagnosticDebugName, despite not having
+   * any actual name.
+   * @return the name of the component, suitable for use in diagnostic 
messages.
+   */
+  def diagnosticDebugName: String
+
+  /**
+   * The standard conversion of the metadata component to a string.
+   * Unless overridden this uses the 
[[org.apache.daffodil.runtime1.api.Metadata.diagnosticDebugName]].
+   * @return string representation of this metadata component.
+   */
+  override def toString = diagnosticDebugName
+}
+
+/*
+ * Provides metadata access that is common to all Terms, which include
+ * Elements of simple or complex type, as well as the Sequence and Choice 
groups.
+ */
+trait TermMetadata extends Metadata {
+  // nothing here
+}
+
+/**
+ * Common metadata access for all elements, of simple or complex type.
+ */
+trait ElementMetadata extends TermMetadata {
+
+  /**
+   * @return the name of this element. In the case of a global/qualified name, 
this is only the local
+   *         part of the QName.
+   */
+  def name: String
+
+  /**
+   * @return the namespace URI as a string, or null if no namespace.
+   */
+  def namespace: String
+
+  /**
+   * @return the namespace bindings needed to construct an XML element from a 
Daffodil infoset
+   *         element of simple or complex type.
+   */
+  def minimizedScope: NamespaceBinding
+
+  /**
+   * @return the namespace prefix part of the XML QName of this component, or 
null if there
+   *         is no prefix defined or no namespace.
+   */
+  def prefix: String
+
+  /**
+   *  @return true if two or more occurrences are possible.
+   *          Note that having only 0 or 1 occurrence is not considered an 
array,
+   *          but rather an optional element.
+   */
+  def isArray: Boolean
+
+  /**
+   * @return true if only 0 or 1 occurrence are possible.
+   */
+  def isOptional: Boolean
+
+  /**
+   * @return the QName string for this element.
+   */
+  def toQName: String
+
+  /**
+   * @return true if the element is declared to be nillable.
+   */
+  def isNillable: Boolean
+
+  /**
+   * Provides access to the runtime properties. This is an extended collection 
of
+   * name-value pairs which are associated with a schema component.
+   * <p/>
+   * Runtime properties are intended to use for new ad-hoc property extensions 
to
+   * DFDL. These name-value pairs are visible to infoset outputters as well.
+   *
+   * @return a java-compatible map of name-value pairs.
+   */
+  def runtimeProperties: java.util.Map[String, String]
+
+}
+
+/**
+ * Access to metadata values exclusive to elements of complex type.
+ */
+trait ComplexElementMetadata extends ElementMetadata {
+
+  /**
+   * @return an ordered sequence of the child elements within this complex 
type regardless
+   *         of their nesting within sequence and choice groups.
+   */
+  def childMetadata: Seq[ElementMetadata]

Review Comment:
   removed. 
   



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetOutputter.scala:
##########
@@ -190,3 +213,10 @@ object Status extends Enumeration {
   type Status = Value
   val DONE, READY, VISITING = Value
 }
+
+trait ExceptionOccurredMixin {
+  def exceptionOccurred(e: Exception): Unit = {
+    val ex = e // because sometimes the debugger won't show the exception

Review Comment:
   Removed



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/unparsers/UState.scala:
##########
@@ -168,7 +168,7 @@ abstract class UState(
     Assert.invariant(Maybe.WithNulls.isDefined(currentInfosetNode))
     currentInfosetNode match {
       case a: DIArray => {
-        a.getOccurrence(arrayIterationPos)
+        a(arrayIterationPos)

Review Comment:
   All related data structures take DINode, not DIElement, so I'm disinclined 
to change this in a major way at this time.



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala:
##########
@@ -871,10 +901,11 @@ sealed abstract class ModelGroupRuntimeData(
     fillByteEvArg,
     maybeCheckByteAndBitOrderEvArg,
     maybeCheckBitOrderAndCharsetEvArg,
-  ) {
+  )
+  with ModelGroupMetadata {
 
   final override def isRequiredScalar = true
-  final override def isArray = false
+  final def isArray = false

Review Comment:
   This is essential. Metadata walk doesn't have an array event. You get an 
element event for the element declaration and you call isArray for that 
information. 
   
   I will fix the coverage. 



##########
daffodil-japi/src/test/java/org/apache/daffodil/example/TestInfosetOutputter.java:
##########
@@ -51,45 +50,50 @@ public void endDocument() {
     }
 
     @Override
-    public void startSimple(DISimple diSimple) {
+    public void startSimple(InfosetSimpleElement diSimple) {
         events.add(
             TestInfosetEvent.startSimple(
-                diSimple.erd().name(),
-                diSimple.erd().namedQName().namespace().toString(),
+                diSimple.metadata().name(),
+                diSimple.metadata().namespace(),
                 diSimple.dataValueAsString(),
-                diSimple.erd().isNillable() ? diSimple.isNilled() : null));
+                diSimple.metadata().isNillable() ? diSimple.isNilled() : 
null));
     }
 
     @Override
-    public void endSimple(DISimple diSimple) {
+    public void endSimple(InfosetSimpleElement diSimple) {
         events.add(
             TestInfosetEvent.endSimple(
-                diSimple.erd().name(),
-                diSimple.erd().namedQName().namespace().toString()));
+                diSimple.metadata().name(),
+                diSimple.metadata().namespace()));
     }
 
     @Override
-    public void startComplex(DIComplex diComplex) {
+    public void startComplex(InfosetComplexElement complex) {
         events.add(
             TestInfosetEvent.startComplex(
-                diComplex.erd().name(),
-                diComplex.erd().namedQName().namespace().toString(),
-                diComplex.erd().isNillable() ? diComplex.isNilled() : null));
+                complex.metadata().name(),
+                complex.metadata().namespace(),
+                complex.metadata().isNillable() ? complex.isNilled() : null));

Review Comment:
   You do not have to call it before. isNilled will just return false if the 
item is non-nillable. 
   But this test is also insisting that the item is declared nillable, or at 
least is exercising that method for coverage reasons. 



##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala:
##########
@@ -154,69 +153,69 @@ abstract class InfosetOutputter extends SInfosetOutputter 
{
   /**
    * Called by Daffodil internals to signify the beginning of a simple element.
    *
-   * @param diSimple the simple element that is started. Various fields of
+   * @param simple the simple element that is started. Various fields of
    *                 DISimple can be accessed to determine things like the
    *                 value, nil, name, namespace, etc.
    * @throws Exception if there was an error and Daffodil should stop parsing
    */
 
   @throws[Exception]
-  def startSimple(diSimple: DISimple): Unit
+  def startSimple(simple: InfosetSimpleElement): Unit

Review Comment:
   I would like to resolve this in a subsequent PR. 
   One thought: maybe we should provide these base traits instead as Java 
interfaces. They could still be used from Scala without a problem since there 
are no problematic data types on the calls I believe. 



##########
daffodil-core/src/test/scala/org/apache/daffodil/core/api/TestMetadataWalking.scala:
##########
@@ -0,0 +1,228 @@
+/*
+ * 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.core.api
+
+import scala.collection.mutable.ArrayBuffer
+import scala.xml.Elem
+
+import org.apache.daffodil.core.util.TestUtils
+import org.apache.daffodil.io.InputSourceDataInputStream
+import org.apache.daffodil.lib.util._
+import org.apache.daffodil.runtime1.api.ChoiceMetadata
+import org.apache.daffodil.runtime1.api.ComplexElementMetadata
+import org.apache.daffodil.runtime1.api.DFDL.ParseResult
+import org.apache.daffodil.runtime1.api.ElementMetadata
+import org.apache.daffodil.runtime1.api.InfosetArray
+import org.apache.daffodil.runtime1.api.InfosetComplexElement
+import org.apache.daffodil.runtime1.api.InfosetElement
+import org.apache.daffodil.runtime1.api.InfosetItem
+import org.apache.daffodil.runtime1.api.InfosetSimpleElement
+import org.apache.daffodil.runtime1.api.Metadata
+import org.apache.daffodil.runtime1.api.MetadataHandler
+import org.apache.daffodil.runtime1.api.SequenceMetadata
+import org.apache.daffodil.runtime1.api.SimpleElementMetadata
+import org.apache.daffodil.runtime1.infoset.ExceptionOccurredMixin
+import org.apache.daffodil.runtime1.infoset.InfosetOutputter
+import org.apache.daffodil.runtime1.infoset.InfosetOutputterImpl
+import org.apache.daffodil.runtime1.processors.DataProcessor
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class TestMetadataWalking {
+
+  def compileAndWalkMetadata(schema: Elem, mh: MetadataHandler): DataProcessor 
= {
+    val dp = TestUtils.compileSchema(schema)
+    assertTrue(!dp.isError)
+    dp.walkMetadata(mh)
+    dp
+  }
+
+  def parseAndWalkData(dp: DataProcessor, infosetOutputter: InfosetOutputter)(
+    data: Array[Byte],
+  ): ParseResult = {
+    val isdis = InputSourceDataInputStream(data)
+    val res = dp.parse(isdis, infosetOutputter)
+    res
+  }
+
+  class GatherMetadata extends MetadataHandler {
+
+    private val buf = new ArrayBuffer[Metadata]();
+
+    def getResult: Seq[Metadata] = {
+      val res: Seq[Metadata] = buf.toVector // makes a copy
+      buf.clear()
+      res
+    }
+
+    override def simpleElementMetadata(m: SimpleElementMetadata): Unit = buf 
+= m
+
+    override def startComplexElementMetadata(m: ComplexElementMetadata): Unit 
= buf += m
+
+    override def endComplexElementMetadata(m: ComplexElementMetadata): Unit = 
buf += m
+
+    override def startSequenceMetadata(m: SequenceMetadata): Unit = buf += m
+
+    override def endSequenceMetadata(m: SequenceMetadata): Unit = buf += m
+
+    override def startChoiceMetadata(m: ChoiceMetadata): Unit = buf += m
+
+    override def endChoiceMetadata(m: ChoiceMetadata): Unit = buf += m
+  }
+
+  class GatherData
+    extends InfosetOutputterImpl
+    with InfosetOutputter
+    with ExceptionOccurredMixin {
+
+    private val buf = new ArrayBuffer[InfosetItem]
+
+    def getResult: Seq[InfosetItem] = {
+      val res = buf.toVector
+      reset()
+      res
+    }
+
+    override def reset(): Unit = { buf.clear() }
+
+    override def startDocument(): Unit = {}
+
+    override def endDocument(): Unit = {}

Review Comment:
   I have not needed it. I believe the concept isn't needed at all. 
   
   That is, it isn't needed in InfosetOutputter/inputter for DFDL either. Or 
even in the DFDL Infoset.
   
   it's a holdover from XML legacy and SAX/STAX, and the only reason it is 
needed there is theoretically because one could start an XML document with 
comments, processing-instructions, DTDs, etc. and those need a surrounding 
context.  For structured data where the only events are going to be associated 
with elements, there's no need for this extra document thing. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,266 @@
+/*
+ * 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.runtime1.api
+
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.lang.{ String => JString }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.net.URI
+
+import com.ibm.icu.util.Calendar
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+
+  /**
+   * @return the metadata of the element that is an array
+   */
+  override def metadata: ElementMetadata
+
+  /**
+   * @return the number of items in the array.
+   */
+  def length: Long
+
+  /**
+   * Access to an infoset element of the array.
+   * @param occursIndex1b the one-based index of the element to be accessed
+   * @return the infoset element located at the given index
+   */
+  def apply(occursIndex1b: Long): InfosetElement

Review Comment:
   Unused. Removed. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,266 @@
+/*
+ * 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.runtime1.api
+
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.lang.{ String => JString }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.net.URI
+
+import com.ibm.icu.util.Calendar
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+
+  /**
+   * @return the metadata of the element that is an array
+   */
+  override def metadata: ElementMetadata
+
+  /**
+   * @return the number of items in the array.
+   */
+  def length: Long
+
+  /**
+   * Access to an infoset element of the array.
+   * @param occursIndex1b the one-based index of the element to be accessed
+   * @return the infoset element located at the given index
+   */
+  def apply(occursIndex1b: Long): InfosetElement
+}
+
+/**
+ * API access to elements of the DFDL Infoset of both
+ * complex and simple type.
+ */
+trait InfosetElement extends InfosetItem {
+
+  /**
+   * In DFDL both simple and complex type elements can be
+   * nilled.
+   *
+   * @return true if the element is nilled, false otherwise.
+   */
+  def isNilled: Boolean
+
+  /**
+   * @return true if the element is a string or hexBinary of length 0, false 
otherwise.
+   */
+  def isEmpty: Boolean
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ElementMetadata]]
+   */
+  def metadata: ElementMetadata
+
+}
+
+/**
+ * Methods specific complex elements in the infoset
+ */
+trait InfosetComplexElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ComplexElementMetadata]]
+   */
+  override def metadata: ComplexElementMetadata
+}
+
+/**
+ * Methods specific to simple elements in the infoset
+ */
+trait InfosetSimpleElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[SimpleElementMetadata]]
+   */
+  override def metadata: SimpleElementMetadata
+
+  /**
+   * @return true if the element has a value, false for a nilled element.
+   */
+  def hasValue: Boolean
+
+  /**
+   * Obtains the value, then converts it to a string.
+   * Caches the string so we're not allocating strings repeatedly
+   */
+  def dataValueAsString: String

Review Comment:
   Good change. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.runtime1.api
+
+import scala.xml.NamespaceBinding
+
+/**
+ * This is the supportable API for access to the RuntimeData structures
+ * which provide access to static information about a given .
+ *
+ * This is used to interface other data processing fabrics to Daffodil
+ * data and metadata, by mapping to/from these metadata objects.
+ */
+trait Metadata {
+
+  /**
+   * Provides the file context of a metadata component. This refers to the 
specific
+   * DFDL schema file where the corresponding DFDL schema text resides 
corresponding
+   * to this metadata object.
+   * <p/>
+   * This is for use in diagnostic messaging. It is not the actual file URI, 
because
+   * those may contain personal-identifying information about the 
person/acccount and
+   * system that compiled the schema. It will provide enough content about the 
file URI that
+   * a user will be able to identify which file, but some prefix of the path
+   * components trimmed to make it of a manageable length.
+   * <p/>
+   * Used along with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]]
+   * and 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineColumnNumber]],
+   * this can give a precise location in the DFDL schema file.
+   * @return a string containing the file information, or null if unknown.
+   */
+  def schemaFileInfo: String
+
+  /**
+   * Provides the line number to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileInfo]].
+   * @return the line number as a string, or null if unknown.
+   */
+  def schemaFileLineNumber: String
+
+  /**
+   * Provides the column number within the text line, to go with 
[[org.apache.daffodil.runtime1.api.Metadata.schemaFileLineNumber]].
+   * @return the column number within the text line, as a string, or null if 
unknown.
+   */
+  def schemaFileLineColumnNumber: String
+
+  /**
+   * The name of the schema component, in a form suitable for diagnostic 
messages.
+   * Unnamed components like sequence or choice groups have a 
diagnosticDebugName, despite not having
+   * any actual name.
+   * @return the name of the component, suitable for use in diagnostic 
messages.
+   */
+  def diagnosticDebugName: String

Review Comment:
   The debug hooks have proven to be essential. This is for users of the API to 
debug their stuff. 
   I had to add a InfosetOutputter.exceptionOccurred(e) method so that a user 
can override it to access exceptions thrown by their code, as otherwise the 
exceptions are all being caught deep inside Daffodil, and what you get is 
unrelated to the cause or you have to wrap try/catch around everything in order 
to debug it.  



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,266 @@
+/*
+ * 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.runtime1.api
+
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.lang.{ String => JString }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.net.URI
+
+import com.ibm.icu.util.Calendar
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+
+  /**
+   * @return the metadata of the element that is an array
+   */
+  override def metadata: ElementMetadata
+
+  /**
+   * @return the number of items in the array.
+   */
+  def length: Long
+
+  /**
+   * Access to an infoset element of the array.
+   * @param occursIndex1b the one-based index of the element to be accessed
+   * @return the infoset element located at the given index
+   */
+  def apply(occursIndex1b: Long): InfosetElement
+}
+
+/**
+ * API access to elements of the DFDL Infoset of both
+ * complex and simple type.
+ */
+trait InfosetElement extends InfosetItem {
+
+  /**
+   * In DFDL both simple and complex type elements can be
+   * nilled.
+   *
+   * @return true if the element is nilled, false otherwise.
+   */
+  def isNilled: Boolean
+
+  /**
+   * @return true if the element is a string or hexBinary of length 0, false 
otherwise.
+   */
+  def isEmpty: Boolean
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ElementMetadata]]
+   */
+  def metadata: ElementMetadata
+
+}
+
+/**
+ * Methods specific complex elements in the infoset
+ */
+trait InfosetComplexElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ComplexElementMetadata]]
+   */
+  override def metadata: ComplexElementMetadata
+}
+
+/**
+ * Methods specific to simple elements in the infoset
+ */
+trait InfosetSimpleElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[SimpleElementMetadata]]
+   */
+  override def metadata: SimpleElementMetadata
+
+  /**
+   * @return true if the element has a value, false for a nilled element.
+   */
+  def hasValue: Boolean
+
+  /**
+   * Obtains the value, then converts it to a string.
+   * Caches the string so we're not allocating strings repeatedly
+   */
+  def dataValueAsString: String
+
+  /*
+   * These are so that API users don't have to know about our
+   * very Scala-oriented DataValue type system.
+   */
+
+  /**
+   * @return the value of this simple element as a Scala AnyRef, which is
+   *         equivalent to a Java Object.
+   */
+  def getAnyRef: AnyRef
+
+  /**
+   * @return the value of this simple element as an Object (java.lang.Object),
+   *         which is equivalent to Scala AnyRef.
+   */
+  final def getObject: java.lang.Object = getAnyRef
+
+  // Note: I could not get @throws in scaladoc to work right.
+  // Complains "Could not find any member to link for ... and I tried various 
formulations of
+  // ClassCastException, with package, with and without [[..]].
+  // So I've just converted it to plain text.
+
+  /**
+   * @return Casts the value of this simple element as a java.math.BigDecimal.
+   * <p/>throws `ClassCastException` if the element value is not of type 
Decimal.
+   */
+  def getBigDecimal: JBigDecimal

Review Comment:
   We should change these to match the DFDL type names. The return types are 
not *necessarily* the exact representation types.
   ```
   def getUnsignedInt: Long 
   ```
   Requires only that you know the primTypeName to know what to call, and the 
return type can be kept the same regardless of the implementation.
   
   People always expect getInt will work for smaller integer types also, so 
I've changed it to also convert from
   
   getAnyRef and getObject should return the same types that the other getTYPE 
functions do. So for example if the data is a date type, getDate returns a 
Calendar, getAnyRef should return a Calendar also for that same element. 
   
   I will make this change. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,266 @@
+/*
+ * 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.runtime1.api
+
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.lang.{ String => JString }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.net.URI
+
+import com.ibm.icu.util.Calendar
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+
+  /**
+   * @return the metadata of the element that is an array
+   */
+  override def metadata: ElementMetadata
+
+  /**
+   * @return the number of items in the array.
+   */
+  def length: Long
+
+  /**
+   * Access to an infoset element of the array.
+   * @param occursIndex1b the one-based index of the element to be accessed
+   * @return the infoset element located at the given index
+   */
+  def apply(occursIndex1b: Long): InfosetElement
+}
+
+/**
+ * API access to elements of the DFDL Infoset of both
+ * complex and simple type.
+ */
+trait InfosetElement extends InfosetItem {
+
+  /**
+   * In DFDL both simple and complex type elements can be
+   * nilled.
+   *
+   * @return true if the element is nilled, false otherwise.
+   */
+  def isNilled: Boolean
+
+  /**
+   * @return true if the element is a string or hexBinary of length 0, false 
otherwise.
+   */
+  def isEmpty: Boolean
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ElementMetadata]]
+   */
+  def metadata: ElementMetadata
+
+}
+
+/**
+ * Methods specific complex elements in the infoset
+ */
+trait InfosetComplexElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[ComplexElementMetadata]]
+   */
+  override def metadata: ComplexElementMetadata
+}
+
+/**
+ * Methods specific to simple elements in the infoset
+ */
+trait InfosetSimpleElement extends InfosetElement {
+
+  /*
+   * Access to the metadata information about this element.
+   * See [[SimpleElementMetadata]]
+   */
+  override def metadata: SimpleElementMetadata
+
+  /**
+   * @return true if the element has a value, false for a nilled element.
+   */
+  def hasValue: Boolean

Review Comment:
   Within daffodil internals these are different because there are states like 
where we don't know if the element will be setNilled or not and we want to know 
if it has a value. 
   
   But at this API, the distinction is not needed, as simple elements are 
finalized before they're walked. 
   
   So this can be removed. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetOutputter.scala:
##########
@@ -84,75 +85,98 @@ trait InfosetOutputter {
    *                 value, nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endSimple(diSimple: DISimple): Unit
+  def endSimple(diSimple: InfosetSimpleElement): 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
+   * @param complex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def startComplex(diComplex: DIComplex): Unit
+  def startComplex(complex: InfosetComplexElement): 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
+   * @param complex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endComplex(diComplex: DIComplex): Unit
+  def endComplex(complex: InfosetComplexElement): 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
+   * @param array the array that is started. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def startArray(diArray: DIArray): Unit
+  def startArray(array: InfosetArray): 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
+   * @param array the array that is ended. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def endArray(diArray: DIArray): Unit
+  def endArray(array: InfosetArray): Unit
 
-  def getStatus(): Status = {
-    // Done, Ready (Not started), Visiting (part way done - can retry to visit 
more)...
-    status
-  }
+  def getStatus(): Status
 
   /**
-   * Helper function to determine if an element is nilled or not, taking into
-   * account whether or not the nilled state has been set yet.
+   * Override this to be fed any exceptions thrown by the start/end methods of 
this class.
+   * This is mostly to facilitate users debugging their code that uses the API.
    *
-   * @param diElement the element to check the nilled state of
+   * This saves the user of the API from having to wrap try/catch around their
+   * start/end method bodies.

Review Comment:
   Removed. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,266 @@
+/*
+ * 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.runtime1.api
+
+import java.lang.{ Boolean => JBoolean }
+import java.lang.{ Byte => JByte }
+import java.lang.{ Double => JDouble }
+import java.lang.{ Float => JFloat }
+import java.lang.{ Integer => JInt }
+import java.lang.{ Long => JLong }
+import java.lang.{ Number => JNumber }
+import java.lang.{ Short => JShort }
+import java.lang.{ String => JString }
+import java.math.{ BigDecimal => JBigDecimal }
+import java.math.{ BigInteger => JBigInt }
+import java.net.URI
+
+import com.ibm.icu.util.Calendar
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+
+  /**
+   * @return the metadata of the element that is an array
+   */
+  override def metadata: ElementMetadata
+
+  /**
+   * @return the number of items in the array.
+   */
+  def length: Long
+
+  /**
+   * Access to an infoset element of the array.
+   * @param occursIndex1b the one-based index of the element to be accessed
+   * @return the infoset element located at the given index
+   */
+  def apply(occursIndex1b: Long): InfosetElement
+}
+
+/**
+ * API access to elements of the DFDL Infoset of both
+ * complex and simple type.
+ */
+trait InfosetElement extends InfosetItem {
+
+  /**
+   * In DFDL both simple and complex type elements can be
+   * nilled.
+   *
+   * @return true if the element is nilled, false otherwise.
+   */
+  def isNilled: Boolean
+
+  /**
+   * @return true if the element is a string or hexBinary of length 0, false 
otherwise.

Review Comment:
   unused. removed. 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetOutputter.scala:
##########
@@ -84,75 +85,98 @@ trait InfosetOutputter {
    *                 value, nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endSimple(diSimple: DISimple): Unit
+  def endSimple(diSimple: InfosetSimpleElement): 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
+   * @param complex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def startComplex(diComplex: DIComplex): Unit
+  def startComplex(complex: InfosetComplexElement): 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
+   * @param complex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endComplex(diComplex: DIComplex): Unit
+  def endComplex(complex: InfosetComplexElement): 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
+   * @param array the array that is started. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def startArray(diArray: DIArray): Unit
+  def startArray(array: InfosetArray): 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
+   * @param array the array that is ended. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def endArray(diArray: DIArray): Unit
+  def endArray(array: InfosetArray): Unit
 
-  def getStatus(): Status = {
-    // Done, Ready (Not started), Visiting (part way done - can retry to visit 
more)...
-    status
-  }
+  def getStatus(): Status
 
   /**
-   * Helper function to determine if an element is nilled or not, taking into
-   * account whether or not the nilled state has been set yet.
+   * Override this to be fed any exceptions thrown by the start/end methods of 
this class.
+   * This is mostly to facilitate users debugging their code that uses the API.
    *
-   * @param diElement the element to check the nilled state of
+   * This saves the user of the API from having to wrap try/catch around their
+   * start/end method bodies.
    *
-   * @return true if the nilled state has been set and is true. false if the
-   *         nilled state is false or if the nilled state has not been set yet
-   *         (e.g. during debugging)
+   * @param e the exception thrown by one of the other methods.
    */
-  final def isNilled(diElement: DIElement): Boolean = {
-    val maybeIsNilled = diElement.maybeIsNilled
-    maybeIsNilled.isDefined && maybeIsNilled.get == true
-  }
+  def exceptionOccurred(e: Exception): Unit
+
+}
+
+/**
+ * Methods that provide Blob (Binary Large Object) support.
+ *
+ * FIXME: Scaladoc
+ */
+trait BlobMethodsMixin {
+
+  def setBlobAttributes(blobDir: Path, blobPrefix: String, blobSuffix: 
String): Unit
+  def setBlobPaths(empty: Seq[Path]): Unit
+  def getBlobDirectory(): Path
+  def getBlobPrefix(): String
+  def getBlobSuffix(): String
+
+}

Review Comment:
   Since it has one constant implementation for all InfosetOutputters, it isn't 
really part of the API.  Users neither need to override any of it, nor call any 
of it. 
   
   That said, I can elimiinate the trait,and since InfosetOutputterImpl is 
going away it just becomes a trait mixed into InfosetOutputter. 
   
   



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetOutputter.scala:
##########
@@ -84,75 +85,98 @@ trait InfosetOutputter {
    *                 value, nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endSimple(diSimple: DISimple): Unit
+  def endSimple(diSimple: InfosetSimpleElement): 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
+   * @param complex the complex element that is started. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def startComplex(diComplex: DIComplex): Unit
+  def startComplex(complex: InfosetComplexElement): 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
+   * @param complex the complex element that is ended. Various fields of
    *                  DIComplex can be accessed to determine things like the
    *                  nil, name, namespace, etc.
    */
   @throws[Exception]
-  def endComplex(diComplex: DIComplex): Unit
+  def endComplex(complex: InfosetComplexElement): 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
+   * @param array the array that is started. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def startArray(diArray: DIArray): Unit
+  def startArray(array: InfosetArray): 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
+   * @param array the array that is ended. Various fields of
    *                  DIArray can be accessed to determine things like the
    *                  name, namespace, etc.
    */
   @throws[Exception]
-  def endArray(diArray: DIArray): Unit
+  def endArray(array: InfosetArray): Unit
 
-  def getStatus(): Status = {
-    // Done, Ready (Not started), Visiting (part way done - can retry to visit 
more)...
-    status
-  }
+  def getStatus(): Status
 
   /**
-   * Helper function to determine if an element is nilled or not, taking into
-   * account whether or not the nilled state has been set yet.
+   * Override this to be fed any exceptions thrown by the start/end methods of 
this class.
+   * This is mostly to facilitate users debugging their code that uses the API.
    *
-   * @param diElement the element to check the nilled state of
+   * This saves the user of the API from having to wrap try/catch around their
+   * start/end method bodies.
    *
-   * @return true if the nilled state has been set and is true. false if the
-   *         nilled state is false or if the nilled state has not been set yet
-   *         (e.g. during debugging)
+   * @param e the exception thrown by one of the other methods.
    */
-  final def isNilled(diElement: DIElement): Boolean = {
-    val maybeIsNilled = diElement.maybeIsNilled
-    maybeIsNilled.isDefined && maybeIsNilled.get == true
-  }
+  def exceptionOccurred(e: Exception): Unit

Review Comment:
   Removed.



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetOutputterImpl.scala:
##########
@@ -0,0 +1,47 @@
+/*
+ * 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.runtime1.infoset
+
+import org.apache.daffodil.runtime1.api.InfosetElement
+
+abstract class InfosetOutputterImpl() extends BlobMethodsImpl with 
InfosetOutputter {
+
+  import Status._
+
+  private def status: Status = READY
+
+  override def getStatus(): Status = {
+    // Done, Ready (Not started), Visiting (part way done - can retry to visit 
more)...
+    status
+  }
+
+  /**
+   * Helper function to determine if an element is nilled or not, taking into
+   * account whether or not the nilled state has been set yet.
+   *
+   * @param elem the element to check the nilled state of
+   * @return true if the nilled state has been set and is true. false if the
+   *         nilled state is false or if the nilled state has not been set yet
+   *         (e.g. during debugging)
+   */
+  final def isNilled(elem: InfosetElement): Boolean = {
+    val diElement = elem.asInstanceOf[DIElement]
+    val maybeIsNilled = diElement.maybeIsNilled
+    maybeIsNilled.isDefined && maybeIsNilled.get == true
+  }

Review Comment:
   removed isNilled method (only needed in one place)



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/JsonInfosetOutputter.scala:
##########
@@ -112,11 +116,12 @@ class JsonInfosetOutputter private (writer: 
java.io.Writer, pretty: Boolean)
     }
   }
 
-  override def endSimple(simple: DISimple): Unit = {
+  override def endSimple(se: InfosetSimpleElement): Unit = {
     // nothing to do
   }
 
-  override def startComplex(complex: DIComplex): Unit = {
+  override def startComplex(ce: InfosetComplexElement): Unit = {
+    val complex = ce.asInstanceOf[DIComplex]

Review Comment:
   fixed



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/JsonInfosetOutputter.scala:
##########
@@ -92,12 +96,12 @@ class JsonInfosetOutputter private (writer: java.io.Writer, 
pretty: Boolean)
     if (pretty) outputIndentation(writer)
   }
 
-  override def startSimple(simple: DISimple): Unit = {
+  override def startSimple(simple: InfosetSimpleElement): Unit = {
     startNode()
     startElement(simple)
-    if (!isNilled(simple) && simple.hasValue) {
+    if (!simple.isNilled && simple.hasValue) {

Review Comment:
   I removed hasValue from the api.InfosetSimpleElement trait. 
   
   We do need it, but it can be on DISimple only 



##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala:
##########
@@ -665,14 +675,29 @@ sealed class ElementRuntimeData(
     fillByteEvArg,
     maybeCheckByteAndBitOrderEvArg,
     maybeCheckBitOrderAndCharsetEvArg,
-  ) {
+  )
+  with ElementMetadata
+  with SimpleElementMetadata
+  with ComplexElementMetadata {
+
+  override def toQName: String = namedQName.toQNameString
 
   override def isRequiredScalar = !isArray && isRequiredInUnparseInfoset
 
   final def childERDs = children
 
+  final override def childMetadata: Seq[ElementRuntimeData] = childERDs

Review Comment:
   removing 
    I don't want to have to filter it on isHidden of enclosing sequences. 



-- 
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]

Reply via email to