stevedlawrence commented on code in PR #1112:
URL: https://github.com/apache/daffodil/pull/1112#discussion_r1387930288
##########
daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/SequenceTermRuntime1Mixin.scala:
##########
@@ -49,6 +50,10 @@ trait SequenceTermRuntime1Mixin { self: SequenceTermBase =>
fillByteEv,
maybeCheckByteAndBitOrderEv,
maybeCheckBitOrderAndCharsetEv,
+ this match {
+ case sgr: SequenceGroupRef => sgr.isHidden
+ case _ => false
+ },
Review Comment:
Is it worth adding an `isHidden` member to `SequenceTermBase` that defaults
to false, and `SequenceGroupRef` overrides it? So this match case just becomes
`isHidden`? Maybe that refactor is best done in another PR.
##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala:
##########
@@ -514,6 +508,13 @@ class DataProcessor private[japi] (private var dp:
SDataProcessor)
*/
def save(output: WritableByteChannel): Unit = dp.save(output)
+ /**
+ * Walks the handler over the runtime metadata structures
+ *
+ * @param handler - the handler is called-back during the walk as each
metadata structure is encountered.
+ */
+ def walkMetadata(handler: MetadataHandler) = dp.walkMetadata(handler)
Review Comment:
Can you add `: Unit` to this to make it obvious this doesn't return anything?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
Review Comment:
Do API users need access to the `parent`?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
Review Comment:
Have you looked at what is generated for JavaDoc to make sure it seems
reasonable? I imagine this will all end up in the JAPI, it would be good to
verify it looks sane.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
Review Comment:
What happens if a API user calls `asSimple` when the element is a complex,
or vice versa? Do users even ever get a `InfosetElement`? Seems they should
always get a `InfosetSimpleElement` or an `InfosetComplexElement` so these
methods should be needed?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala:
##########
@@ -1558,6 +1590,29 @@ sealed class DISimple(override val erd:
ElementRuntimeData)
Assert.invariantFailed("Should not try to remove a child of a simple type")
}
+ // call to getAnyRef here seems redundant
+ // but tests fail that compare objects if this call isn't here
+ // Boxing/Unboxing related perhaps
+ @inline private def v = dataValue.getAnyRef
+
+ override def getAnyRef: AnyRef = v.asInstanceOf[AnyRef]
+ override def getBigDecimal: JBigDecimal = v.asInstanceOf[JBigDecimal]
+ override def getCalendar: DFDLCalendar = v.asInstanceOf[DFDLCalendar]
+ override def getDate: DFDLDate = v.asInstanceOf[DFDLDate]
+ override def getTime: DFDLTime = v.asInstanceOf[DFDLTime]
+ override def getDateTime: DFDLDateTime = v.asInstanceOf[DFDLDateTime]
+ override def getByteArray: Array[Byte] = v.asInstanceOf[Array[Byte]]
+ override def getBoolean: JBoolean = v.asInstanceOf[JBoolean]
+ override def getNumber: JNumber = v.asInstanceOf[JNumber]
+ override def getByte: JByte = v.asInstanceOf[JByte]
+ override def getShort: JShort = v.asInstanceOf[JShort]
+ override def getInt: JInt = v.asInstanceOf[JInt]
+ override def getLong: JLong = v.asInstanceOf[JLong]
+ override def getDouble: JDouble = v.asInstanceOf[JDouble]
+ override def getFloat: JFloat = v.asInstanceOf[JFloat]
+ override def getBigInt: JBigInt = v.asInstanceOf[JBigInt]
+ override def getString: JString = v.asInstanceOf[JString]
+ override def getURI: URI = v.asInstanceOf[URI]
Review Comment:
Can these just call `dataValue.getXYZ`? Doesn't that already do the
asInstanceOf stuff? Avoids some duplication and makes it so if we ever chang
DataValue this gets those changes?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/XMLInfosetOutputterMixin.scala:
##########
@@ -0,0 +1,62 @@
+/*
+ * 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.lib.equality._
+import org.apache.daffodil.lib.util.Maybe
+import org.apache.daffodil.lib.xml.XMLUtils
+
+trait XMLInfosetOutputterMixin {
+
+ def remapped(dataValueAsString: String) =
+ XMLUtils.remapXMLIllegalCharactersToPUA(dataValueAsString)
+
+ /**
+ * String suitable for use in the text of a Processing Instruction.
+ *
+ * The text is a pseudo-XML string.
+ */
+ protected final def fmtInfo(diTerm: DITerm): Maybe[String] = {
Review Comment:
Should we just drop the fmtInfo stuff? Seems like nothing uses it, and my
guess it's is only used for debugging? If we do need access to fmtInfo, we
should make that available in the CLI or VS Code debugger.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala:
##########
@@ -689,6 +698,10 @@ sealed class ElementRuntimeData(
name
}
}
+
+ override def namespace: NS = dpathElementCompileInfo.namedQName.namespace
+ override def optNamespacePrefix: Option[String] =
dpathElementCompileInfo.namedQName.prefix
+ override def sscd: String = dpathElementCompileInfo.sscd
Review Comment:
I've forgotten what does sscd stands for. Which makes me thinks it's used
rarely enough that maybe it needs a more descriptive name? Could be done in
another PR, since it's not related to this.
##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/infoset/Infoset.scala:
##########
@@ -161,7 +160,7 @@ abstract class InfosetOutputter extends SInfosetOutputter {
*/
@throws[Exception]
- def startSimple(diSimple: DISimple): Unit
+ def startSimple(diSimple: InfosetSimpleElement): Unit
Review Comment:
We should rename the parameter names too, probably just drop the `di`, e.g.
`diSimple` -> `simple`.
##########
daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala:
##########
@@ -350,6 +349,27 @@ trait QNameBase extends Serializable {
if (prefix.isDefined) prefix.get + ":" + local else local
}
+ private lazy val _Prefix_LocalName = toQNameString.replace(":", "_")
+
+ /**
+ * Maps the QName to a name like prefix_localName for use with
+ * data models/representations that don't have namespaces.
+ */
+ def toPrefix_localName = {
Review Comment:
I'm not sure I love this name. I feel like this wants to be `toSafeString`
or something like that. `safe` is probably the wrong word, but `toFooString`
feels like a more clear name about what it's doing.
##########
daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala:
##########
@@ -350,6 +349,27 @@ trait QNameBase extends Serializable {
if (prefix.isDefined) prefix.get + ":" + local else local
}
+ private lazy val _Prefix_LocalName = toQNameString.replace(":", "_")
Review Comment:
This logic feels like it wants to be in the MetaDataHandler or
InfosetWalkers. Different implementations are possibly going to have different
restrictions on what makes a valid name or a name that fits best into their
system. I also imagine most implementations could get away with just dropping
the namespace altogether. Schemas that rely on namespaces for uniqueness are
fairly rare, and those that do exist should probably be changed or deprecated.
##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala:
##########
@@ -514,6 +508,13 @@ class DataProcessor private[japi] (private var dp:
SDataProcessor)
*/
def save(output: WritableByteChannel): Unit = dp.save(output)
+ /**
+ * Walks the handler over the runtime metadata structures
+ *
+ * @param handler - the handler is called-back during the walk as each
metadata structure is encountered.
+ */
+ def walkMetadata(handler: MetadataHandler) = dp.walkMetadata(handler)
Review Comment:
I'm not sure I love the name `walkMetadata`. If you're not familiar with
Daffodil internals, I'm not sure you would know what "metadata" means and if
you would want to walk it. That said, I can't think of a better name, so maybe
it just needs a comment explaining what what it means to walk metadata.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
Review Comment:
What does `isEmpty` represent? Seems an API user should never be handed an
infoset element that is empty.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
Review Comment:
Thoughts on dropping name and namespace since users have access to the
metadata?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,80 @@
+package org.apache.daffodil.runtime1.api
+
+import org.apache.daffodil.lib.exceptions.SchemaFileLocation
+import org.apache.daffodil.lib.xml.NS
+import org.apache.daffodil.lib.xml.NamedQName
+import org.apache.daffodil.runtime1.dpath.PrimTypeNode
+
+/*
+ * This is the supportable API for access to the RuntimeData structures
+ */
+trait Metadata {
+ def schemaFileLocation: SchemaFileLocation
Review Comment:
`SchemaFileLocation` isn't part of the api. In the JAPI/SAPI we map things
to a `LocationInSchemaFile` (not sure if that's the same thing?). I'm not sure
how this would show up in the JavaDocs
##########
daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala:
##########
@@ -350,6 +349,27 @@ trait QNameBase extends Serializable {
if (prefix.isDefined) prefix.get + ":" + local else local
}
+ private lazy val _Prefix_LocalName = toQNameString.replace(":", "_")
Review Comment:
Can this just be something like `prefix + "_" + localName`?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala:
##########
@@ -1650,32 +1708,71 @@ sealed class DIComplex(override val erd:
ElementRuntimeData)
}
}
+ final def getChild(
+ childMetadata: ElementMetadata,
+ enableLinearSearch: Boolean,
Review Comment:
I suggest this goes away. Users should only get access to children via a
walker. If they need by-name access, then they need to walk the infoset and
build their own internal representation that gives them that.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
+}
+
+trait InfosetComplexElement extends InfosetElement {
+ override def metadata: ComplexElementMetadata
+ def getChildElement(childMetadata: ElementMetadata): InfosetElement
+ def getChildArray(childMetadata: ElementMetadata): InfosetArray
+ def getChild(childMetadata: ElementMetadata): InfosetItem
+}
+
+trait InfosetSimpleElement extends InfosetElement {
+
+ override def metadata: SimpleElementMetadata
+
+ /**
+ * 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.
+ */
+ def getAnyRef: AnyRef
Review Comment:
Should we remove `getAnyRef`? A API user should never need that.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
+}
+
+trait InfosetComplexElement extends InfosetElement {
+ override def metadata: ComplexElementMetadata
+ def getChildElement(childMetadata: ElementMetadata): InfosetElement
+ def getChildArray(childMetadata: ElementMetadata): InfosetArray
+ def getChild(childMetadata: ElementMetadata): InfosetItem
+}
+
+trait InfosetSimpleElement extends InfosetElement {
+
+ override def metadata: SimpleElementMetadata
+
+ /**
+ * 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.
+ */
+ def getAnyRef: AnyRef
+ def getBigDecimal: JBigDecimal
+ def getCalendar: DFDLCalendar
+ def getDate: DFDLDate
+ def getTime: DFDLTime
+ def getDateTime: DFDLDateTime
+ def getByteArray: Array[Byte]
+ def getBoolean: JBoolean
+ def getNumber: JNumber
+ def getByte: JByte
+ def getShort: JShort
+ def getInt: JInt
+ def getLong: JLong
+ def getDouble: JDouble
+ def getFloat: JFloat
+ def getBigInt: JBigInt
+ def getString: JString
+ def getURI: URI
+}
Review Comment:
We probably need javadocs on these functions individually. It's going to be
repetetive, but is needed for Javadocs to look correct.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
+}
+
+trait InfosetComplexElement extends InfosetElement {
+ override def metadata: ComplexElementMetadata
+ def getChildElement(childMetadata: ElementMetadata): InfosetElement
+ def getChildArray(childMetadata: ElementMetadata): InfosetArray
+ def getChild(childMetadata: ElementMetadata): InfosetItem
+}
+
+trait InfosetSimpleElement extends InfosetElement {
+
+ override def metadata: SimpleElementMetadata
+
+ /**
+ * 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.
+ */
+ def getAnyRef: AnyRef
+ def getBigDecimal: JBigDecimal
+ def getCalendar: DFDLCalendar
+ def getDate: DFDLDate
+ def getTime: DFDLTime
+ def getDateTime: DFDLDateTime
+ def getByteArray: Array[Byte]
+ def getBoolean: JBoolean
+ def getNumber: JNumber
+ def getByte: JByte
+ def getShort: JShort
+ def getInt: JInt
+ def getLong: JLong
+ def getDouble: JDouble
+ def getFloat: JFloat
+ def getBigInt: JBigInt
+ def getString: JString
+ def getURI: URI
+}
+
+trait InfosetDocument extends InfosetItem {
+ override def metadata: ElementMetadata
+}
+
+trait InfosetItem {
+
+ def metadata: Metadata
+
+ /**
+ * The totalElementCount is the total count of how many elements this
InfosetItem contains.
+ *
+ * (Used to call this 'size', but size is often a length-like thing, so
changed name
+ * to be more distinctive)
+ */
+ def totalElementCount: Long
Review Comment:
Do API users need this? I'm not even sure what this value represents or what
it's used for. Looking at the implementation, totalElementCount is the number
of children recursively? Seems like that number wouldn't be all that useful.
And it might not even be accurate, since I imagine it's possible all the
children haven't been finalized yet, since the infoset is often in a state
where parts can be walked but parts can't.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
+}
+
+trait InfosetComplexElement extends InfosetElement {
+ override def metadata: ComplexElementMetadata
+ def getChildElement(childMetadata: ElementMetadata): InfosetElement
+ def getChildArray(childMetadata: ElementMetadata): InfosetArray
+ def getChild(childMetadata: ElementMetadata): InfosetItem
+}
Review Comment:
Should we grant access to children this way? This allows users to walk and
infoset themselves, which is dangerous. An infoset is often in a state where it
is only partially built and children should not be accessed, which only
Daffodil internals know when that is.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,80 @@
+package org.apache.daffodil.runtime1.api
+
+import org.apache.daffodil.lib.exceptions.SchemaFileLocation
+import org.apache.daffodil.lib.xml.NS
+import org.apache.daffodil.lib.xml.NamedQName
+import org.apache.daffodil.runtime1.dpath.PrimTypeNode
+
+/*
+ * This is the supportable API for access to the RuntimeData structures
+ */
+trait Metadata {
+ def schemaFileLocation: SchemaFileLocation
+ def path: String
+ def diagnosticDebugName: String
+ override def toString = diagnosticDebugName
+}
+
+trait TermMetadata extends Metadata {
+ def isArray: Boolean
+}
+
+trait ElementMetadata extends TermMetadata {
+ def isSimpleType: Boolean
+ def isComplexType: Boolean
+
+ def name: String
+ def namespace: NS
+ def optNamespacePrefix: Option[String]
+ def isArray: Boolean
+ def isOptional: Boolean
+ def namedQName: NamedQName
+
+ def sscd: String
+ def isNillable: Boolean
+
+ def runtimeProperties: java.util.Map[String, String]
+
+}
+
+trait ComplexElementMetadata extends ElementMetadata {
+
+ def childMetadata: Seq[ElementMetadata]
Review Comment:
Similar questions as earlier, should we grant access to children stuff? That
would allow users to implement their own walkers, which feels unsafe. Seems we
only want to give access to this element and only this element. They'll see the
childMetadata when we walk to it.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Infoset.scala:
##########
@@ -0,0 +1,122 @@
+/*
+ * 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 org.apache.daffodil.lib.calendar.DFDLCalendar
+import org.apache.daffodil.lib.calendar.DFDLDate
+import org.apache.daffodil.lib.calendar.DFDLDateTime
+import org.apache.daffodil.lib.calendar.DFDLTime
+
+/**
+ * API access to array objects in the DFDL Infoset
+ */
+trait InfosetArray extends InfosetItem {
+ override def metadata: ElementMetadata // the element that is an array
+ def getOccurrence(occursIndex: Long): InfosetElement
+ def length: Long
+ final def apply(occursIndex: Long): InfosetElement =
getOccurrence(occursIndex)
+ final def apply(occursIndex: Int) : InfosetElement =
getOccurrence(occursIndex.toLong)
+}
+
+/**
+ * API access to elements of the DFDL Infoset
+ */
+trait InfosetElement extends InfosetItem {
+ def parent: InfosetComplexElement
+ def isNilled: Boolean
+ def isEmpty: Boolean
+ def asSimple: InfosetSimpleElement
+ def asComplex: InfosetComplexElement
+
+ /*
+ * For API users to avoid the need to access RuntimeData
+ */
+ def metadata: ElementMetadata
+ def name = metadata.name
+ def namespace = metadata.namespace
+}
+
+trait InfosetComplexElement extends InfosetElement {
+ override def metadata: ComplexElementMetadata
+ def getChildElement(childMetadata: ElementMetadata): InfosetElement
+ def getChildArray(childMetadata: ElementMetadata): InfosetArray
+ def getChild(childMetadata: ElementMetadata): InfosetItem
+}
+
+trait InfosetSimpleElement extends InfosetElement {
+
+ override def metadata: SimpleElementMetadata
+
+ /**
+ * 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.
+ */
+ def getAnyRef: AnyRef
+ def getBigDecimal: JBigDecimal
+ def getCalendar: DFDLCalendar
+ def getDate: DFDLDate
+ def getTime: DFDLTime
+ def getDateTime: DFDLDateTime
Review Comment:
These calendar/time types are kindof internal I think? We might want to
think if there's something better to return here, like a `Calendar` or some
other Java date/time structure.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala:
##########
@@ -1157,6 +1180,8 @@ final class DIArray(
) extends DINode
with InfosetArray {
+ override def metadata: ElementMetadata = erd.asInstanceOf[ElementMetadata]
Review Comment:
Is `asInstanceOf` needed here? If `erd` implements `ElementMetaData`, should
it be fine to just return erd?
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/InfosetImpl.scala:
##########
@@ -1079,27 +1101,27 @@ sealed trait DIElement
protected final var _isHidden = false
final def isHidden: Boolean = _isHidden
- override def setHidden(): Unit = {
+ def setHidden(): Unit = {
_isHidden = true
}
final def runtimeData = erd
- protected final var _parent: InfosetComplexElement = null
+ protected final var _parent: DIComplex = null
Review Comment:
This is a great change and something we should do everywhere infosets appear
in the code (maybe this PR does that?). Seems Daffodil wants use the `DI`
variant internally everywhere. The only place the non-`DI` variant should is
the public functions like the walkers so we can limit what parts a user has
acess to. But Daffodil internals should have access to all parts of a DI. I
feel like there are a number of places where that's not the case (though maybe
this PR fixed all those?) and should make a lot of `asInstanceOf[DIFoo]` go
away.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/Metadata.scala:
##########
@@ -0,0 +1,80 @@
+package org.apache.daffodil.runtime1.api
+
+import org.apache.daffodil.lib.exceptions.SchemaFileLocation
+import org.apache.daffodil.lib.xml.NS
+import org.apache.daffodil.lib.xml.NamedQName
+import org.apache.daffodil.runtime1.dpath.PrimTypeNode
+
+/*
+ * This is the supportable API for access to the RuntimeData structures
+ */
+trait Metadata {
+ def schemaFileLocation: SchemaFileLocation
+ def path: String
+ def diagnosticDebugName: String
+ override def toString = diagnosticDebugName
+}
+
+trait TermMetadata extends Metadata {
+ def isArray: Boolean
+}
+
+trait ElementMetadata extends TermMetadata {
+ def isSimpleType: Boolean
+ def isComplexType: Boolean
+
+ def name: String
+ def namespace: NS
+ def optNamespacePrefix: Option[String]
+ def isArray: Boolean
+ def isOptional: Boolean
+ def namedQName: NamedQName
+
+ def sscd: String
Review Comment:
Need a new name for sscd if this is going to be publicly available to users.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/ScalaXMLInfosetOutputter.scala:
##########
@@ -17,20 +17,23 @@
package org.apache.daffodil.runtime1.infoset
-import scala.collection.mutable.ListBuffer
-import scala.xml.MetaData
-import scala.xml.Null
-import scala.xml.UnprefixedAttribute
-
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.util.MStackOf
import org.apache.daffodil.lib.util.Maybe
import org.apache.daffodil.lib.xml.XMLUtils
+import org.apache.daffodil.runtime1.api.InfosetArray
+import org.apache.daffodil.runtime1.api.InfosetComplexElement
+import org.apache.daffodil.runtime1.api.InfosetSimpleElement
import org.apache.daffodil.runtime1.dpath.NodeInfo
+import scala.collection.mutable.ListBuffer
+import scala.xml.MetaData
+import scala.xml.Null
+import scala.xml.UnprefixedAttribute
Review Comment:
You might need to change your IDE settings. I think scala imports are
supposed to be before daffodil imports. Can you configure your IDE to use the
.scalafmt.conf file?
##########
daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala:
##########
@@ -514,6 +508,13 @@ class DataProcessor private[japi] (private var dp:
SDataProcessor)
*/
def save(output: WritableByteChannel): Unit = dp.save(output)
+ /**
+ * Walks the handler over the runtime metadata structures
+ *
+ * @param handler - the handler is called-back during the walk as each
metadata structure is encountered.
+ */
+ def walkMetadata(handler: MetadataHandler) = dp.walkMetadata(handler)
Review Comment:
Very good points. Suggest these be added to a comment somewhere.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/JDOMInfosetOutputter.scala:
##########
@@ -46,7 +49,8 @@ class JDOMInfosetOutputter extends InfosetOutputter with
XMLInfosetOutputter {
result = Maybe(root.asInstanceOf[org.jdom2.Document])
}
- def startSimple(diSimple: DISimple): Unit = {
+ override def startSimple(se: InfosetSimpleElement): Unit = {
+ val diSimple = se.asInstanceOf[DISimple]
Review Comment:
Is casting to a DISimple done to avoid having to update other outputters and
deal with that later? I assume the goal is these infoset outputters should only
use InfosetFooEelements? Doing the conversion would be good evidence that the
InfosetElement API interface makes everything needed available.
##########
daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/MetadataWalker.scala:
##########
@@ -0,0 +1,76 @@
+package org.apache.daffodil.runtime1.processors
+
+import org.apache.daffodil.lib.exceptions.Assert
+import org.apache.daffodil.runtime1.api.MetadataHandler
+import org.apache.daffodil.runtime1.api.SequenceMetadata
+
+/**
+ * Walks the schema, but not the DSOM schema, it walks the RuntimeData objects
that
+ * represent the DFDL schema at runtime.
+ *
+ * @param dp
+ */
+class MetadataWalker(private val dp: DataProcessor) {
+
+ private lazy val rootERD = dp.ssrd.elementRuntimeData
+
+ def walk(handler: MetadataHandler): Unit = {
+ walkTerm(handler, rootERD)
+ }
+
+ private def walkTerm(handler: MetadataHandler, trd: TermRuntimeData): Unit =
{
+ trd match {
+ case err: ErrorERD => Assert.invariantFailed("should not get ErrorERDs")
+ case erd: ElementRuntimeData => walkElement(handler, erd)
+ case srd: SequenceRuntimeData => walkSequence(handler, srd)
+ case crd: ChoiceRuntimeData => walkChoice(handler, crd)
+ case _ => Assert.invariantFailed(s"unrecognized TermRuntimeData subtype:
$trd")
+ }
+ }
+
+ private def walkElement(handler: MetadataHandler, erd: ElementRuntimeData):
Unit = {
+ if (erd.optComplexTypeModelGroupRuntimeData.isDefined)
+ walkComplexElement(handler, erd)
+ else
+ walkSimpleElement(handler, erd)
+ }
+
+ private def walkComplexElement(
+ handler: MetadataHandler,
+ erd: ElementRuntimeData,
+ ): Unit = {
+ val mgrd = erd.optComplexTypeModelGroupRuntimeData.getOrElse {
+ Assert.invariantFailed("not a complex type element")
+ }
+ handler.startComplexElementMetadata(erd)
+ walkTerm(handler, mgrd)
+ handler.endComplexElementMetadata(erd)
+ }
+
+ private def walkSimpleElement(
+ handler: MetadataHandler,
+ erd: ElementRuntimeData,
+ ): Unit = {
+ handler.simpleElementMetadata(erd)
+ }
+
+ private def walkSequence(handler: MetadataHandler, sm: SequenceMetadata):
Unit = {
+ val srd = sm.asInstanceOf[SequenceRuntimeData]
+ if (!srd.isHidden) {
+ // handler.startSequence()
+ srd.groupMembers.map { trd =>
+ walkTerm(handler, trd)
+ }
+ // handler.endSequence()
+ }
+ }
+
+ private def walkChoice(handler: MetadataHandler, crd: ChoiceRuntimeData):
Unit = {
+ // handler.startChoice()
Review Comment:
Seems a walker handler would want to know that the children are options of a
choice and could be converted to a union or something. Can they know that
without start/endChoice?
--
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]