You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by mb...@apache.org on 2019/06/18 13:50:55 UTC
[incubator-daffodil] branch master updated: DSOM backpointer - def
to ref - alternative in place.
This is an automated email from the ASF dual-hosted git repository.
mbeckerle pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
The following commit(s) were added to refs/heads/master by this push:
new 015891f DSOM backpointer - def to ref - alternative in place.
015891f is described below
commit 015891ff982144ab07f092a25ab133707a9a31e9
Author: Michael Beckerle <mb...@tresys.com>
AuthorDate: Mon Jun 3 11:59:21 2019 -0400
DSOM backpointer - def to ref - alternative in place.
This is incremental progress toward fixing the schema compiler
space/speed problem. (DAFFODIL-1444).
The tests in daffodil-core-unittests TestRefMap demonstrate exponential
growth of schema component instances being compiled versus the number of
actual "real" schema components.
Root.refMap allows any component (having a factory), to determine what
is referring to it from within the schema.
SchemaComponents have a referringComponents that allows one to obtain
the list of components referring to this one.
DAFFODIL-1444
---
.../org/apache/daffodil/compiler/Compiler.scala | 1 +
.../daffodil/dsom/AnnotatedSchemaComponent.scala | 4 -
.../org/apache/daffodil/dsom/ChoiceGroup.scala | 2 -
.../org/apache/daffodil/dsom/ComplexTypes.scala | 5 +-
.../org/apache/daffodil/dsom/DFDLSchemaFile.scala | 1 +
.../org/apache/daffodil/dsom/ElementBase.scala | 4 +-
.../apache/daffodil/dsom/ElementDeclMixin.scala | 215 ++++---
.../org/apache/daffodil/dsom/ElementRef.scala | 2 +
.../apache/daffodil/dsom/GlobalElementDecl.scala | 8 +-
.../daffodil/dsom/GlobalElementDeclFactory.scala | 9 +-
.../scala/org/apache/daffodil/dsom/GroupDef.scala | 19 +-
.../daffodil/dsom/InitiatedTerminatedMixin.scala | 6 +-
.../apache/daffodil/dsom/LocalElementDecl.scala | 2 +-
.../org/apache/daffodil/dsom/ModelGroup.scala | 17 +-
.../scala/org/apache/daffodil/dsom/Nesting.scala | 65 +-
.../main/scala/org/apache/daffodil/dsom/Root.scala | 105 +++-
.../daffodil/dsom/RuntimePropertyMixins.scala | 6 +-
.../org/apache/daffodil/dsom/SchemaComponent.scala | 58 +-
.../daffodil/dsom/SchemaComponentFactory.scala | 8 -
.../org/apache/daffodil/dsom/SchemaDocument.scala | 1 +
.../scala/org/apache/daffodil/dsom/SchemaSet.scala | 3 +
.../org/apache/daffodil/dsom/SequenceGroup.scala | 4 -
.../main/scala/org/apache/daffodil/dsom/Term.scala | 14 +-
.../org/apache/daffodil/grammar/AlignedMixin.scala | 7 +-
.../daffodil/grammar/SequenceGrammarMixin.scala | 6 +-
.../grammar/primitives/PrimitivesFraming.scala | 31 +-
.../apache/daffodil/dsom/TestDsomCompiler.scala | 11 +-
.../org/apache/daffodil/dsom/TestRefMap.scala | 651 +++++++++++++++++++++
.../apache/daffodil/dsom/CompiledExpression1.scala | 41 +-
.../org/apache/daffodil/infoset/InfosetImpl.scala | 10 -
.../section12/aligned_data/Aligned_Data.tdml | 11 +-
31 files changed, 1119 insertions(+), 208 deletions(-)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
index e3dbfdc..fd1e3b2 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
@@ -79,6 +79,7 @@ final class ProcessorFactory(val sset: SchemaSet)
with HavingRootSpec {
final override def enclosingComponentDef: Option[SchemaComponent] = None
+ final override def enclosingComponentDefs = Seq()
lazy val (generateParser, generateUnparser) = {
val (context, policy) = tunable.parseUnparsePolicy match {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
index a85d2ab..253d28d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
@@ -186,10 +186,6 @@ trait AnnotatedSchemaComponent
with AnnotatedMixin
with OverlapCheckMixin {
- requiredEvaluations(annotationObjs)
- requiredEvaluations(nonDefaultPropertySources)
- requiredEvaluations(defaultPropertySources)
-
/**
* Since validation of extra attributes on XML Schema elements is
* normally lax validation, we can't count on validation of DFDL schemas
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
index cfccc7c..fd791d4 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ChoiceGroup.scala
@@ -114,8 +114,6 @@ abstract class ChoiceTermBase(
requiredEvaluations(branchesAreNotIVCElements)
requiredEvaluations(modelGroupRuntimeData.preSerialization)
- protected final override lazy val myPeers = choicePeers
-
final protected lazy val optionChoiceDispatchKeyRaw = findPropertyOption("choiceDispatchKey")
final protected lazy val choiceDispatchKeyRaw = requireProperty(optionChoiceDispatchKeyRaw)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
index 65b2fe9..d1aa928 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ComplexTypes.scala
@@ -69,7 +69,7 @@ final class GlobalComplexTypeDefFactory(xmlArg: Node, schemaDocumentArg: SchemaD
extends SchemaComponentFactory(xmlArg, schemaDocumentArg)
with GlobalNonElementComponentMixin {
- def forElement(elementDecl: ElementDeclMixin) = new GlobalComplexTypeDef(xml, schemaDocument, elementDecl)
+ def forElement(elementDecl: ElementDeclMixin) = new GlobalComplexTypeDef(xml, schemaDocument, elementDecl, this)
override lazy val namedQName = QName.createGlobal(name, targetNamespace, xml.scope)
}
@@ -80,7 +80,8 @@ final class GlobalComplexTypeDefFactory(xmlArg: Node, schemaDocumentArg: SchemaD
final class GlobalComplexTypeDef(
xmlArg: Node,
schemaDocumentArg: SchemaDocument,
- val elementDecl: ElementDeclMixin)
+ val elementDecl: ElementDeclMixin,
+ override val factory: GlobalComplexTypeDefFactory)
extends ComplexTypeBase(xmlArg, schemaDocumentArg)
with GlobalNonElementComponentMixin
with NestingTraversesToReferenceMixin {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLSchemaFile.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLSchemaFile.scala
index 93b9371..1fc28ef 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLSchemaFile.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLSchemaFile.scala
@@ -74,6 +74,7 @@ final class DFDLSchemaFile(
lazy val schemaSource = schemaSourceArg
final override protected def enclosingComponentDef = None
+ final override protected def enclosingComponentDefs = Seq()
private var validationDiagnostics_ : Seq[Diagnostic] = Nil
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index 9045db0..d2690b8 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -119,8 +119,8 @@ trait ElementBase
def complexType: ComplexTypeBase
- lazy final val optSimpleType = if (isSimpleType) Some(simpleType) else None
- lazy final val optComplexType = if (isComplexType) Some(complexType) else None
+ def optSimpleType: Option[SimpleTypeBase]
+ def optComplexType: Option[ComplexTypeBase]
/**
* Irrespective of whether the type of this element is immediate or
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementDeclMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementDeclMixin.scala
index 92f5bad..2c43a79 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementDeclMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementDeclMixin.scala
@@ -27,15 +27,10 @@ trait ElementLikeMixin
extends AnnotatedSchemaComponent
with ProvidesDFDLStatementMixin {
- private lazy val elementBase = this match {
- case ged: GlobalElementDecl => ged.elementRef
- case eb: ElementBase => eb
- }
-
protected final def annotationFactory(node: Node): Option[DFDLAnnotation] = {
node match {
case <dfdl:element>{ contents @ _* }</dfdl:element> => Some(new DFDLElement(node, this))
- case _ => elementBase.annotationFactoryForDFDLStatement(node, this)
+ case _ => annotationFactoryForDFDLStatement(node, this)
}
}
@@ -46,25 +41,81 @@ trait ElementLikeMixin
/**
* Shared by all element declarations local or global
*/
-trait ElementDeclMixin
+sealed trait ElementDeclMixin
extends ElementLikeMixin {
def namedQName: NamedQName
- final override protected def optReferredToComponent = typeDef match {
+ def optReferredToComponent: Option[AnnotatedSchemaComponent]
+
+ def optImmediateSimpleType: Option[SimpleTypeBase]
+
+ def optImmediateComplexType: Option[ComplexTypeBase]
+
+ def immediateType: Option[TypeBase]
+
+ def typeName: Option[String]
+
+ def optNamedSimpleType: Option[SimpleTypeBase]
+
+ def optNamedComplexType: Option[GlobalComplexTypeDef]
+
+ def optSimpleType: Option[SimpleTypeBase]
+
+ def optComplexType: Option[ComplexTypeBase]
+
+ def namedTypeQName: Option[RefQName]
+
+ def namedType: Option[TypeBase]
+
+ def typeDef: TypeBase
+
+ final def isSimpleType: Boolean = optSimpleType.isDefined
+
+ final def isComplexType = !isSimpleType
+
+ def defaultAttr: Option[Seq[Node]]
+
+ def defaultValueAsString: String
+
+ final def primType = optSimpleType.get.primType
+
+ final def hasDefaultValue: Boolean = defaultAttr.isDefined
+
+ def isNillable: Boolean
+
+ final def simpleType: SimpleTypeBase = optSimpleType.get
+
+ final def complexType: ComplexTypeBase = optComplexType.get
+
+ /**
+ * Convenience methods for unit testing purposes.
+ */
+ final def sequence = complexType.sequence
+ final def choice = complexType.choice
+}
+
+sealed trait ElementDeclInstanceImplMixin
+ extends ElementDeclMixin {
+
+ final override lazy val optReferredToComponent = typeDef match {
case std: SimpleTypeDefBase => Some(std)
case ctd: ComplexTypeBase => None // in DFDL v1.0 complex types are not annotated, so can't carry properties nor statements.
case _ => None
}
- final def immediateType: Option[TypeBase] = LV('immediateType) {
- val st = xml \ "simpleType"
+ final override lazy val optNamedComplexType: Option[GlobalComplexTypeDef] = {
+ namedTypeQName.flatMap { qn =>
+ val gctdFactory = schemaSet.getGlobalComplexTypeDef(qn)
+ val res = gctdFactory.map { gctdf => gctdf.forElement(this) }
+ res
+ }
+ }
+
+ final override lazy val optImmediateComplexType: Option[ComplexTypeBase] = LV('optImmediateComplexType) {
val ct = xml \ "complexType"
val nt = typeName
- if (st.length == 1) {
- val lstd = new LocalSimpleTypeDef(st(0), this)
- Some(lstd)
- } else if (ct.length == 1)
+ if (ct.length == 1)
Some(new LocalComplexTypeDef(ct(0), this))
else {
Assert.invariant(nt != "")
@@ -72,43 +123,22 @@ trait ElementDeclMixin
}
}.value
- private lazy val typeName = getAttributeOption("type")
+ final override lazy val optComplexType =
+ optNamedComplexType.orElse(optImmediateComplexType.collect { case ct: ComplexTypeBase => ct })
- private def namedTypeQName: Option[RefQName] = LV('namedTypeQName) {
- typeName match {
- case Some(tname) =>
- Some(QName.resolveRef(tname, namespaces, tunable).get)
- case None => None
+ final override lazy val namedType: Option[TypeBase] = LV('namedTypeDef) {
+ val res = optNamedSimpleType.orElse(optNamedComplexType).orElse {
+ namedTypeQName.map { qn => SDE("No type definition found for '%s'.", qn.toPrettyString) }
}
+ if (optNamedSimpleType.isDefined &&
+ optNamedComplexType.isDefined)
+ SDE("Both a simple type and a complex type definition found for %s.", namedTypeQName.get.toPrettyString)
+ res
}.value
- private def namedType: Option[TypeBase] = LV('namedTypeDef) {
- namedTypeQName match {
- case None => None
- case Some(qn) => {
-
- val ss = schemaSet
- val optPrimitiveType = ss.getPrimitiveType(qn)
- if (optPrimitiveType.isDefined) optPrimitiveType
- else {
- val gstd = ss.getGlobalSimpleTypeDef(qn)
- val gctd = ss.getGlobalComplexTypeDef(qn)
- val res = (gstd, gctd) match {
- case (Some(_), None) => gstd
- case (None, Some(gctdFactory)) => Some(gctdFactory.forElement(this))
- // Note: Validation of the DFDL Schema doesn't necessarily check referential integrity
- // or other complex constraints like conflicting names.
- // So we check it here explicitly.
- case (None, None) => schemaDefinitionError("No type definition found for '%s'.", qn.toPrettyString)
- case (Some(_), Some(_)) => schemaDefinitionError("Both a simple and a complex type definition found for '%s'", qn.toPrettyString)
- }
- res
- }
- }
- }
- }.value
+ final override lazy val immediateType = optImmediateSimpleType.orElse(optImmediateComplexType)
- final lazy val typeDef: TypeBase = LV('typeDef) {
+ final override lazy val typeDef: TypeBase = LV('typeDef) {
(immediateType, namedType) match {
case (Some(ty), None) => ty
case (None, Some(ty)) => ty
@@ -119,50 +149,81 @@ trait ElementDeclMixin
}
}.value
- final lazy val isSimpleType = LV('isSimpleType) {
- typeDef match {
- case _: SimpleTypeBase => true
- case _: ComplexTypeBase => false
- case _ => Assert.invariantFailed("Must be either SimpleType or ComplexType")
- }
+}
+
+trait ElementDeclFactoryImplMixin
+ extends ElementDeclMixin {
+
+ final override lazy val optImmediateSimpleType: Option[SimpleTypeBase] = LV('optImmediateSimpleType) {
+ val st = xml \ "simpleType"
+ if (st.length == 1) {
+ val lstd = new LocalSimpleTypeDef(st(0), this)
+ Some(lstd)
+ } else None
}.value
- final def isComplexType = !isSimpleType
+ final override lazy val typeName = getAttributeOption("type")
+
+ final override lazy val namedTypeQName: Option[RefQName] = {
+ typeName.map { tname =>
+ QName.resolveRef(tname, namespaces, tunable).get
+ }
+ }
+
+ final lazy val optNamedSimpleType: Option[SimpleTypeBase] = {
+ namedTypeQName.flatMap { qn =>
+ schemaSet.getPrimitiveType(qn).orElse(schemaSet.getGlobalSimpleTypeDef(qn))
+ }
+ }
- private def defaultAttr = xml.attribute("default")
+ final override lazy val optSimpleType =
+ optNamedSimpleType.orElse(optImmediateSimpleType.collect { case st: SimpleTypeBase => st })
- final lazy val defaultValueAsString = {
+ final override lazy val defaultAttr = xml.attribute("default")
+
+ final override lazy val defaultValueAsString = {
Assert.usage(hasDefaultValue)
val dv = defaultAttr.get.text
- schemaDefinitionWhen(dv =:= "" && !(primType =:= PrimType.String), "Type was %s, but only type xs:string can have XSD default=\"\".",
+ schemaDefinitionWhen(
+ dv =:= "" && !(primType =:= PrimType.String),
+ "Type was %s, but only type xs:string can have XSD default=\"\".",
primType.toString)
dv
}
- // shorthand
- final lazy val primType = {
- val res = typeDef.asInstanceOf[SimpleTypeBase].primType
- res
- }
+ final override lazy val isNillable = (xml \ "@nillable").text == "true"
- final lazy val hasDefaultValue: Boolean = {
- Assert.usage(isSimpleType)
- defaultAttr.isDefined
- }
+ override def namedType: Option[TypeBase] = Assert.usageError("Not to be called on Element Decl Factories")
+ override def optComplexType: Option[ComplexTypeBase] = Assert.usageError("Not to be called on Element Decl Factories")
+ override def optNamedComplexType: Option[GlobalComplexTypeDef] = Assert.usageError("Not to be called on Element Decl Factories")
+ override def typeDef: TypeBase = Assert.usageError("Not to be called on Element Decl Factories")
+ override def immediateType: Option[TypeBase] = Assert.usageError("Not to be called on Element Decl Factories")
+ override def optImmediateComplexType: Option[ComplexTypeBase] = Assert.usageError("Not to be called on Element Decl Factories")
+}
- final lazy val isNillable = (xml \ "@nillable").text == "true"
+trait ElementDeclNonFactoryDelegatingMixin
+ extends ElementDeclFactoryImplMixin
+ with ElementDeclInstanceImplMixin
- final def simpleType = typeDef match {
- case st: SimpleTypeBase => st
- case ct: ComplexTypeBase =>
- Assert.invariantFailed("Must be simple type: " + namedQName)
- }
+trait ElementDeclFactoryDelegatingMixin
+ extends ElementDeclInstanceImplMixin {
- final def complexType = typeDef.asInstanceOf[ComplexTypeBase]
- /**
- * Convenience methods for unit testing purposes.
- */
- final def sequence = complexType.sequence
- final def choice = complexType.choice
+ protected def delegate: ElementDeclFactoryImplMixin
+
+ final override def typeName: Option[String] = delegate.typeName
+
+ final override def namedTypeQName: Option[RefQName] = delegate.namedTypeQName
+
+ final override def optImmediateSimpleType: Option[SimpleTypeBase] = delegate.optImmediateSimpleType
+
+ final override def optNamedSimpleType: Option[SimpleTypeBase] = delegate.optNamedSimpleType
+
+ final override def optSimpleType: Option[SimpleTypeBase] = delegate.optSimpleType
+
+ final override def defaultAttr: Option[Seq[Node]] = delegate.defaultAttr
+
+ final override def defaultValueAsString: String = delegate.defaultValueAsString
+
+ final override def isNillable: Boolean = delegate.isNillable
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
index 2202c48..c05f1c4 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementRef.scala
@@ -51,6 +51,8 @@ abstract class AbstractElementRef(
def isSimpleType: Boolean = this.referencedElement.isSimpleType
def simpleType: SimpleTypeBase = this.referencedElement.simpleType
def primType: NodeInfo.PrimType = this.referencedElement.primType
+ def optSimpleType = this.referencedElement.optSimpleType
+ def optComplexType = this.referencedElement.optComplexType
override lazy val optReferredToComponent = Some(referencedElement)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDecl.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDecl.scala
index 6a43609..726750d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDecl.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDecl.scala
@@ -22,16 +22,20 @@ import scala.xml.Node
final class GlobalElementDecl(
xmlArg: Node,
schemaDocument: SchemaDocument,
- elementRefArg: => AbstractElementRef)
+ elementRefArg: => AbstractElementRef,
+ override val factory: GlobalElementDeclFactory)
extends AnnotatedSchemaComponentImpl(xmlArg, schemaDocument)
with GlobalElementComponentMixin
- with ElementDeclMixin
+ with ElementDeclFactoryDelegatingMixin
with NestingTraversesToReferenceMixin
with ResolvesProperties {
+
// global elements combined with element references referring to them can
// be multiple occurring (aka arrays) hence, we have to have things
// that take root and referenced situation into account.
+ final override def delegate = factory
+
lazy val elementRef = elementRefArg
override lazy val dpathCompileInfo = elementRef.dpathElementCompileInfo
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDeclFactory.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDeclFactory.scala
index 894a416..369600d 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDeclFactory.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GlobalElementDeclFactory.scala
@@ -32,18 +32,21 @@ import scala.xml.Node
*/
class GlobalElementDeclFactory(xmlArg: Node, schemaDocumentArg: SchemaDocument)
extends SchemaComponentFactory(xmlArg, schemaDocumentArg)
- with GlobalElementComponentMixin {
+ with GlobalElementComponentMixin
+ with ElementDeclFactoryImplMixin {
+
+ override def optReferredToComponent: Option[AnnotatedSchemaComponent] = None
def forRoot() = asRoot // cache. Not a new one every time.
private lazy val asRoot = {
- lazy val ged = new GlobalElementDecl(xml, schemaDocument, root)
+ lazy val ged = new GlobalElementDecl(xml, schemaDocument, root, this)
lazy val root: Root = new Root(xml, schemaDocument, namedQName, ged)
root
}
def forElementRef(eRef: AbstractElementRef) = {
- new GlobalElementDecl(xml, schemaDocument, eRef)
+ new GlobalElementDecl(xml, schemaDocument, eRef, this)
}
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
index d3dcc62..96ba3c9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupDef.scala
@@ -34,14 +34,14 @@ final class GlobalGroupDefFactory(defXML: Node, schemaDocument: SchemaDocument)
val list = contents.collect {
case groupXML @ <sequence>{ _* }</sequence> => {
lazy val gref: SequenceGroupRef = new SequenceGroupRef(gdef, refXML, refLexicalParent, position, isHidden)
- lazy val gdef: GlobalSequenceGroupDef = new GlobalSequenceGroupDef(defXML, groupXML, schemaDocument, gref)
+ lazy val gdef: GlobalSequenceGroupDef = new GlobalSequenceGroupDef(defXML, groupXML, schemaDocument, gref, this)
gref.groupDef
gdef.groupRef
(gref, gdef)
}
case groupXML @ <choice>{ _* }</choice> =>
lazy val gref: ChoiceGroupRef = new ChoiceGroupRef(gdef, refXML, refLexicalParent, position, isHidden)
- lazy val gdef: GlobalChoiceGroupDef = new GlobalChoiceGroupDef(defXML, groupXML, schemaDocument, gref)
+ lazy val gdef: GlobalChoiceGroupDef = new GlobalChoiceGroupDef(defXML, groupXML, schemaDocument, gref, this)
gref.groupDef
gdef.groupRef
(gref, gdef)
@@ -108,7 +108,8 @@ sealed abstract class GlobalGroupDef(
defXML: Node,
groupXML: Node,
schemaDocumentArg: SchemaDocument,
- grefArg: => GroupRef)
+ grefArg: => GroupRef,
+ override val factory: GlobalGroupDefFactory)
extends AnnotatedSchemaComponentImpl(groupXML, schemaDocumentArg)
with GroupDefLike
with GlobalNonElementComponentMixin
@@ -136,12 +137,16 @@ sealed abstract class GlobalGroupDef(
final override lazy val referringComponent = Some(groupRef.asModelGroup)
}
-final class GlobalSequenceGroupDef(defXMLArg: Node, seqXML: Node, schemaDocument: SchemaDocument, gref: => SequenceGroupRef)
- extends GlobalGroupDef(defXMLArg, seqXML, schemaDocument, gref)
+final class GlobalSequenceGroupDef(
+ defXMLArg: Node, seqXML: Node, schemaDocument: SchemaDocument, gref: => SequenceGroupRef,
+ factory: GlobalGroupDefFactory)
+ extends GlobalGroupDef(defXMLArg, seqXML, schemaDocument, gref, factory)
with SequenceDefMixin
-final class GlobalChoiceGroupDef(defXMLArg: Node, choiceXML: Node, schemaDocument: SchemaDocument, gref: => ChoiceGroupRef)
- extends GlobalGroupDef(defXMLArg, choiceXML, schemaDocument, gref)
+final class GlobalChoiceGroupDef(
+ defXMLArg: Node, choiceXML: Node, schemaDocument: SchemaDocument, gref: => ChoiceGroupRef,
+ factory: GlobalGroupDefFactory)
+ extends GlobalGroupDef(defXMLArg, choiceXML, schemaDocument, gref, factory)
with ChoiceDefMixin {
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
index 204c972..2c4c971 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/InitiatedTerminatedMixin.scala
@@ -46,8 +46,6 @@ trait InitiatedTerminatedMixin
*/
lazy val hasInitiator = {
val hasOne = initiatorExpr.isKnownNonEmpty
- if (parentSaysInitiatedContent)
- schemaDefinitionUnless(hasOne, "Enclosing group has initiatedContent='yes', but initiator is not defined.")
hasOne
}
@@ -63,10 +61,10 @@ trait InitiatedTerminatedMixin
res
}
- lazy val initiatorDiscriminator = prod("initiatorDiscriminator", parentSaysInitiatedContent) { InitiatedContent(this) }
+ private lazy val initiatorDiscriminator = prod("initiatorDiscriminator", parentSaysInitiatedContent) { InitiatedContent(this) }
lazy val initiatorRegion = prod("initiatorRegion", hasInitiator) { initiatorItself ~ initiatorDiscriminator }
- lazy val initiatorItself = delimMTA ~ Initiator(this)
+ private lazy val initiatorItself = delimMTA ~ Initiator(this)
lazy val terminatorRegion = prod("terminatorRegion", hasTerminator) { delimMTA ~ Terminator(this) }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/LocalElementDecl.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/LocalElementDecl.scala
index ab1c040..c736249 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/LocalElementDecl.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/LocalElementDecl.scala
@@ -25,7 +25,7 @@ sealed abstract class LocalElementDeclBase(
final override val position: Int)
extends ElementBase
with LocalElementComponentMixin
- with ElementDeclMixin
+ with ElementDeclNonFactoryDelegatingMixin
with NestingLexicalMixin {
requiredEvaluations(minOccurs, maxOccurs)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
index fb67462..4c80510 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ModelGroup.scala
@@ -32,6 +32,7 @@ import org.apache.daffodil.infoset.ChoiceBranchEndEvent
import java.lang.{ Integer => JInt }
import org.apache.daffodil.schema.annotation.props.AlignmentType
import org.apache.daffodil.schema.annotation.props.gen.AlignmentUnits
+import org.apache.daffodil.schema.annotation.props.gen.YesNo
/**
* A factory for model groups.
@@ -143,6 +144,7 @@ abstract class ModelGroup(index: Int)
with NestingLexicalMixin {
requiredEvaluations(groupMembers)
+ requiredEvaluations(initiatedContentCheck)
/**
* FIXME: DAFFODIL-2132. This tells us if framing is expressed on the schema.
@@ -164,7 +166,6 @@ abstract class ModelGroup(index: Int)
final lazy val representedMembers = groupMembers.filter { _.isRepresented }
def xmlChildren: Seq[Node]
- protected def myPeers: Option[Seq[ModelGroup]]
final override def isScalar = true
final override def isOptional = false
@@ -174,13 +175,6 @@ abstract class ModelGroup(index: Int)
override lazy val diagnosticDebugName = prettyBaseName + prettyIndex
- /**
- * This is only the immediately enclosing model group. It doesn't walk outward.
- */
- final lazy val enclosingComponentModelGroup = enclosingComponent.collect { case mg: ModelGroup => mg }
- final lazy val sequencePeers = enclosingComponentModelGroup.map { _.sequenceChildren }
- final lazy val choicePeers = enclosingComponentModelGroup.map { _.choiceChildren }
-
override lazy val alignmentValueInBits: JInt = {
this.alignment match {
case AlignmentType.Implicit => this.alignmentUnits match {
@@ -421,4 +415,11 @@ abstract class ModelGroup(index: Int)
}
}.value
+ lazy val initiatedContentCheck: Unit = {
+ if (initiatedContent eq YesNo.Yes) {
+ groupMembers.foreach { term =>
+ term.schemaDefinitionUnless(term.hasInitiator, "Enclosing group has initiatedContent='yes', but initiator is not defined.")
+ }
+ }
+ }
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Nesting.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Nesting.scala
index d8d690d..84e3d22 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Nesting.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Nesting.scala
@@ -19,6 +19,15 @@ package org.apache.daffodil.dsom
import org.apache.daffodil.exceptions.Assert
+/**
+ * When a global schema component is referenced, the "backpointer" is represented by
+ * this class. The lexical position is the index within the enclosing construct's lexical parent.
+ * For example, if an element ref is referencing a global element decl, then the encloser is
+ * the elementRef, and the lexical position is which index, within the sequence/choice that
+ * contains that particular elementRef.
+ */
+case class EnclosingComponentDef(encloser: SchemaComponent, lexicalPosition: Int)
+
trait NestingMixin {
/** The lexically enclosing schema component */
@@ -33,8 +42,15 @@ trait NestingMixin {
* Not for format annotations however. We don't backpoint those to
* other format annotations that ref them.
*/
+ //
+ // Uncomment this to chase down these usages and revise them.
+ //
+ //
+ // @deprecated("2019-06-03", "Use enclosingComponentDefs method, and deal with sharing.")
protected def enclosingComponentDef: Option[SchemaComponent]
+ protected def enclosingComponentDefs: Seq[EnclosingComponentDef]
+
/**
* The enclosing component, and follows back-references
* from types to their elements, from globalElementDef to
@@ -45,7 +61,15 @@ trait NestingMixin {
* referenced from a element ref or group ref, is NOT the ref object, but the
* component that contains the ref object
*/
+ //
+ // Uncomment this to chase down these usages and revise them.
+ //
+ //
+ // @deprecated("2019-06-03", "Rewrite to use lexicalParent or enclosingComponents methods, and deal with sharing.")
final lazy val enclosingComponent: Option[SchemaComponent] = enclosingComponentDef
+
+ final lazy val enclosingComponents: Seq[EnclosingComponentDef] =
+ enclosingComponentDefs
}
/**
@@ -54,24 +78,61 @@ trait NestingMixin {
* schema components.
*/
trait NestingLexicalMixin
- extends NestingMixin {
+ extends NestingMixin { self: SchemaComponent =>
+ @deprecated("2019-06-03", "Use enclosingComponentDefs method, and deal with sharing.")
override protected def enclosingComponentDef = optLexicalParent
+ final override protected lazy val enclosingComponentDefs: Seq[EnclosingComponentDef] =
+ optLexicalParent.map {
+ lp =>
+ val pos = self match {
+ case t: Term => t.position
+ case _ => 1
+ }
+ EnclosingComponentDef(lp, pos)
+ }.toSeq
}
/**
* Mixin for all global schema components
*/
trait NestingTraversesToReferenceMixin
- extends NestingMixin {
+ extends NestingMixin { self: SchemaComponent =>
+
+ def factory: SchemaComponentFactory
+ @deprecated("2019-06-03", "Use referringComponents method, and deal with sharing.")
def referringComponent: Option[SchemaComponent]
+ @deprecated("2019-06-03", "Use enclosingComponentDefs method, and deal with sharing.")
final override protected def enclosingComponentDef: Option[SchemaComponent] = {
Assert.invariant(optLexicalParent.isDefined &&
optLexicalParent.get.isInstanceOf[SchemaDocument]) // global things have schema documents as their parents.
referringComponent
}
+ /**
+ * Enables compilation to know all the points of use of a global
+ * component.
+ */
+ def referringComponents: Seq[(String, Seq[RefSpec])] = {
+ schemaSet.root.refMap.get(this.factory) match {
+ case None => Assert.invariantFailed("There are no references to this component: " + this)
+ case Some(seq) => seq
+ }
+
+ }
+
+ final override protected def enclosingComponentDefs: Seq[EnclosingComponentDef] = {
+ Assert.invariant(optLexicalParent.isDefined &&
+ optLexicalParent.get.isInstanceOf[SchemaDocument]) // global things have schema documents as their parents.
+ val res = referringComponents.flatMap {
+ case (_, seq: Seq[RefSpec]) =>
+ seq.map { rs =>
+ EnclosingComponentDef(rs.from, rs.index)
+ }
+ }
+ res
+ }
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Root.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Root.scala
index 18dc0cf..ac624de 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Root.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Root.scala
@@ -17,11 +17,13 @@
package org.apache.daffodil.dsom
+import scala.collection.mutable
+import scala.xml.Node
+import scala.xml.UnprefixedAttribute
+
import org.apache.daffodil.grammar.RootGrammarMixin
import org.apache.daffodil.xml.NamedQName
import org.apache.daffodil.xml.XMLUtils
-import scala.xml.Node
-import scala.xml.UnprefixedAttribute
/**
* Root is a special kind of ElementRef that has no enclosing group.
@@ -45,4 +47,103 @@ final class Root(defXML: Node, parentArg: SchemaDocument,
override lazy val referencedElement = globalElementDecl
lazy val rootParseUnparsePolicy = defaultParseUnparsePolicy
+
+ /**
+ * For any given global schema component, tells us what schema components contain
+ * references to it, and if that reference is from a sequence or choice, the index of
+ * the group member within that sequence/choice.
+ *
+ * This is intended to be used when compilation needs to understand
+ * the context where an object is referenced. This allows the various referencing contexts
+ * to be known, without making copies of schema components for each such context.
+ */
+ lazy val refMap: Map[SchemaComponentFactory, Seq[(String, Seq[RefSpec])]] = {
+ val refEntries: Seq[(SchemaComponentFactory, Seq[RefSpec])] =
+ refTargets.groupBy { _.to }.toSeq
+ val m: Seq[(SchemaComponentFactory, Seq[(String, Seq[RefSpec])])] = refEntries.map {
+ case (to, seq) => (to, seq.groupBy { _.from.shortSchemaComponentDesignator }.toSeq)
+ }
+ m.toMap
+ }
+
+ lazy val refPairsMap: Map[SchemaComponentFactory, Seq[String]] = {
+ refMap.toSeq.map {
+ case (to, seq: Seq[(String, _)]) => (to, seq.map { case (sscd, _) => sscd }.toSeq)
+ }.toMap
+ }
+
+ private lazy val allComponentsSet = new mutable.HashSet[SchemaComponent]
+
+ private def allSchemaComponents(component: SchemaComponent, optIndex: Option[Int]): Unit = {
+ if (allComponentsSet.contains(component)) {
+ // ok
+ } else {
+ allComponentsSet.add(component)
+ component match {
+ case er: ElementBase => er.typeDef match {
+ case std: SimpleTypeDefBase => //ok
+ case ctd: ComplexTypeBase => allSchemaComponents(ctd, None)
+ case _ => // ok
+ }
+ case ct: ComplexTypeBase => allSchemaComponents(ct.modelGroup, None)
+ case mg: ModelGroup => mg.groupMembers.foreach { gm =>
+ allSchemaComponents(gm, Some(gm.position))
+ }
+ }
+ }
+ }
+
+ final lazy val allComponents = {
+ allSchemaComponents(this, None)
+ allComponentsSet.toSeq
+ }
+
+ final lazy val numComponents =
+ allComponents.length
+
+ final lazy val allComponentSSCDs =
+ allComponents.map { _.shortSchemaComponentDesignator }.distinct
+
+ final lazy val numUniqueComponents =
+ allComponentSSCDs.length
+
+ final lazy val refTargets: Seq[RefSpec] = {
+ allComponents.collect {
+ case er: AbstractElementRef => {
+ val ed = er.referencedElement
+ RefSpec(er, ed.factory, er.position) +:
+ ed.optNamedComplexType.map { gctd => RefSpec(ed, gctd.factory, 1) }.toSeq
+ }
+ case ed: LocalElementDecl => {
+ ed.optNamedComplexType.map { gctd => RefSpec(ed, gctd.factory, 1) }.toSeq
+ }
+ case gr: GroupRef => Seq(RefSpec(gr, gr.groupDef.factory, gr.asModelGroup.position))
+ }.flatten
+ }
+
+ lazy val allERefs = allComponents.filter {
+ case er: ElementRef => true
+ case _ => false
+ }.map { _.shortSchemaComponentDesignator }.distinct
+
+ lazy val allGRefs = allComponents.filter {
+ case _: GroupRef => true
+ case _ => false
+ }.map { _.shortSchemaComponentDesignator }.distinct
+
+ lazy val allCTRefs = {
+ val cts = allComponents.collect {
+ case e: ElementBase if (e.optComplexType.isDefined && e.complexType.isInstanceOf[GlobalComplexTypeDef]) => e.complexType
+ }
+ val ctsIDs = cts.map { _.shortSchemaComponentDesignator }.distinct
+ ctsIDs
+ }
+}
+
+case class RefSpec(from: SchemaComponent, to: SchemaComponentFactory, index: Int) {
+
+ override def toString = "RefSpec(from=" +
+ from.shortSchemaComponentDesignator + ", to=" +
+ to.shortSchemaComponentDesignator + ", " + index +
+ ")"
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
index 8b2065c..2c5b7eb 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/RuntimePropertyMixins.scala
@@ -181,9 +181,9 @@ trait DelimitedRuntimeValuedPropertiesMixin
extends TermRuntimeValuedPropertiesMixin
with RawDelimitedRuntimeValuedPropertiesMixin { decl: Term =>
- lazy val isLengthKindDelimited = {
+ private lazy val isLengthKindDelimited = {
this match {
- case mg: ModelGroup => mg.enclosingElement.get.lengthKind == LengthKind.Delimited
+ case mg: ModelGroup => false
case eb: ElementBase => eb.lengthKind == LengthKind.Delimited
}
}
@@ -440,7 +440,7 @@ trait ElementRuntimeValuedPropertiesMixin
res
}
- final lazy val maybeUnparseTargetLengthInBitsEv:Maybe[UnparseTargetLengthInBitsEv] = {
+ final lazy val maybeUnparseTargetLengthInBitsEv: Maybe[UnparseTargetLengthInBitsEv] = {
if (this.isSimpleType && this.simpleType.optRepTypeElement.isDefined) {
this.simpleType.optRepTypeElement.get.maybeUnparseTargetLengthInBitsEv
} else {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponent.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponent.scala
index 9cfe5be..bf30bd5 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponent.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponent.scala
@@ -133,6 +133,10 @@ trait SchemaComponent
ee
}.value
+ //
+ // Uncomment this to chase down these usages and revise them.
+ //
+ // @deprecated("2019-06-03", "Use enclosingTerms and deal with shared object with multiple referencers/enclosers.")
final lazy val enclosingTerm: Option[Term] = {
val ec = enclosingComponent
val et = ec match {
@@ -143,16 +147,65 @@ trait SchemaComponent
et
}
+ final lazy val enclosingTerms: Seq[Term] = {
+ val ec = enclosingComponents.map { _.encloser }
+ val et = ec.flatMap { sc =>
+ sc match {
+ case t: Term => Seq(t)
+ case ct: ComplexTypeBase => ct.enclosingTerms
+ case gedf: GlobalElementDeclFactory => gedf.enclosingComponents.map { _.encloser }.flatMap { _.enclosingTerms }
+ case _ => Assert.invariantFailed("Should only be Term or ComplexType")
+ }
+ }
+ et
+ }
+
/**
* path is used in diagnostic messages and code debug
* messages; hence, it is very important that it be
* very dependable.
*/
override lazy val path = {
- val p = scPath.map { _.diagnosticDebugName }.mkString("::")
+ val list = scPath.filter { isComponentForSSCD(_) }
+ val p = list.map { _.diagnosticDebugName }.mkString("::")
p
}
+ private def isComponentForSSCD(sc: SchemaComponent) = {
+ sc match {
+ case _: SchemaDocument => false
+ case _: XMLSchemaDocument => false
+ case _: DFDLSchemaFile => false
+ case _: Schema => false
+ case _: SchemaSet => false
+ case _ => true
+ }
+ }
+
+ lazy val shortSchemaComponentDesignator: String = {
+ val list = scPath.filter { isComponentForSSCD(_) }
+ val sscdStrings = list.map { sc =>
+ sc match {
+ case er: AbstractElementRef => "er" + (if (er.position > 1) er.position else "") + "=" + er.namedQName
+ case e: ElementBase => "e" + (if (e.position > 1) e.position else "") + "=" + e.namedQName
+ case ed: GlobalElementDecl => "e=" + ed.namedQName
+ case ct: GlobalComplexTypeDef => "ct=" + ct.namedQName
+ case ct: ComplexTypeBase => "ct"
+ case st: SimpleTypeDefBase => "st=" + st.namedQName
+ case st: SimpleTypeBase => "st=" + st.primType.globalQName
+ case cgr: ChoiceGroupRef => "cgr" + (if (cgr.position > 1) cgr.position else "") + "=" + cgr.groupDef.namedQName
+ case cgd: GlobalChoiceGroupDef => "cgd=" + cgd.namedQName
+ case sgr: SequenceGroupRef => "sgr" + (if (sgr.isHidden) "h" else "") + (if (sgr.position > 1) sgr.position else "") + "=" + sgr.groupDef.namedQName
+ case sgd: GlobalSequenceGroupDef => "sgd=" + sgd.namedQName
+ case cg: Choice => "c" + (if (cg.position > 1) cg.position else "")
+ case sg: Sequence => "s" + (if (sg.isHidden) "h" else "") + (if (sg.position > 1) sg.position else "")
+ case sc => Assert.invariantFailed("Unexpected component type: " + sc)
+ }
+ }
+ val sscd = sscdStrings.mkString(":")
+ sscd
+ }
+
/**
* Elements only e.g., /foo/ex:bar
*/
@@ -200,7 +253,6 @@ trait SchemaComponent
val dfdlBinding = new scala.xml.NamespaceBinding("dfdl", XMLUtils.DFDL_NAMESPACE.toString, xml.scope)
scala.xml.Elem("dfdl", label, emptyXMLMetadata, dfdlBinding, true)
}
-
}
/**
@@ -218,6 +270,8 @@ final class Schema(val namespace: NS, schemaDocs: Seq[SchemaDocument], schemaSet
override def targetNamespace: NS = namespace
final override protected def enclosingComponentDef = None
+ final override protected def enclosingComponentDefs = Seq()
+
override lazy val schemaDocument: SchemaDocument = Assert.usageError("schemaDocument should not be called on Schema")
override lazy val schemaSet = schemaSetArg
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponentFactory.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponentFactory.scala
index 49d83c8..07334aa 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponentFactory.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaComponentFactory.scala
@@ -39,14 +39,6 @@ abstract class SchemaComponentFactory(
this(xml, Option(lexicalParent))
}
-abstract class AnnotatedSchemaComponentFactory(
- final override val xml: Node,
- final override val optLexicalParent: Option[SchemaComponent])
- extends AnnotatedSchemaComponent
- with NestingLexicalMixin {
-
-}
-
trait SchemaFileLocatableImpl
extends SchemaFileLocatable {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaDocument.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaDocument.scala
index c7132d0..99fad36 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaDocument.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaDocument.scala
@@ -53,6 +53,7 @@ import org.apache.daffodil.xml.XMLUtils
trait SchemaDocumentMixin { self: SchemaComponent =>
protected final override def enclosingComponentDef: Option[SchemaComponent] = None
+ protected final override def enclosingComponentDefs = Seq()
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaSet.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaSet.scala
index 4f26d77..dcab2e0 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaSet.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SchemaSet.scala
@@ -94,7 +94,10 @@ final class SchemaSet(
override lazy val schemaSet = this
// These things are needed to satisfy the contract of being a schema component.
final override protected def enclosingComponentDef = None
+ final override protected def enclosingComponentDefs = Seq()
+
override lazy val schemaDocument = Assert.usageError("schemaDocument should not be called on SchemaSet")
+ override lazy val xmlSchemaDocument = Assert.usageError("xmlSchemaDocument should not be called on SchemaSet")
override lazy val lineAttribute: Option[String] = None
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
index 8f85b8c..11b723a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/SequenceGroup.scala
@@ -97,8 +97,6 @@ abstract class SequenceGroupTermBase(
protected def apparentXMLChildren: Seq[Node]
- final override lazy val myPeers = sequencePeers
-
final override lazy val hasDelimiters = hasInitiator || hasTerminator || hasSeparator
protected def hiddenGroupRefOption: PropertyLookupResult
@@ -420,8 +418,6 @@ final class ChoiceBranchImpliedSequence(rawGM: Term)
def modelGroupRuntimeData: ModelGroupRuntimeData = sequenceRuntimeData
- protected def myPeers: Option[Seq[ModelGroup]] = None
-
def xmlChildren: Seq[scala.xml.Node] = Seq(xml)
// Members declared in Term
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
index 01e8c45..9e8262c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/Term.scala
@@ -102,6 +102,9 @@ trait Term
with TermEncodingMixin
with EscapeSchemeRefMixin {
+ requiredEvaluations(annotationObjs)
+ requiredEvaluations(nonDefaultPropertySources)
+ requiredEvaluations(defaultPropertySources)
requiredEvaluations(termChecks)
private lazy val termChecks = {
@@ -233,8 +236,6 @@ trait Term
final val tID = UUID.randomUUID()
- lazy val someEnclosingComponent = enclosingComponent.getOrElse(Assert.invariantFailed("All terms except a root element have an enclosing component."))
-
/** Overridden as false for elements with dfdl:inputValueCalc property. */
lazy val isRepresented = true
@@ -335,7 +336,14 @@ trait Term
// but if we have a CT as our parent, the group around the element whose type
// that is, isn't "immediately enclosing".
}
- case _ => Assert.invariantFailed("immediatelyEnclosingModelGroup called on " + this + "with lexical parent " + lexicalParent)
+ case qe: QuasiElementDeclBase => {
+ //
+ // If your lexical parent is a Quasi-element, then your model group is
+ // the one surrounding the quasi-element.
+ //
+ qe.immediatelyEnclosingModelGroup
+ }
+ case _ => Assert.invariantFailed("immediatelyEnclosingModelGroup called on " + this + " with lexical parent " + lexicalParent)
}
res
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
index 802a66f..92d1ebe 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
@@ -127,6 +127,8 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
LengthExact(trailingSkipInBits)
}
+ private lazy val unaligned = AlignmentMultipleOf(1)
+
private lazy val priorAlignmentApprox: AlignmentMultipleOf = {
if (this.isInstanceOf[Root] || this.isInstanceOf[QuasiElementDeclBase]) {
AlignmentMultipleOf(0) // root and quasi elements are aligned with anything
@@ -179,7 +181,10 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
csa
}.toSeq
val priorAlignmentsApprox = priorSibsAlignmentsApprox ++ parentAlignmentApprox ++ arraySelfAlignment
- priorAlignmentsApprox.reduce(_ * _)
+ if (priorAlignmentsApprox.isEmpty)
+ unaligned
+ else
+ priorAlignmentsApprox.reduce(_ * _)
}
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
index 116db3f..9901baf 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
@@ -30,7 +30,7 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
else sequenceContent
}
- final lazy val sequenceContent = {
+ private lazy val sequenceContent = {
import columnConstants._
self.sequenceKind match {
case Ordered__ => orderedSequence
@@ -61,7 +61,7 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
/**
* Constants to make the lookup tables below more readable without using fragile whitespace
*/
- object columnConstants {
+ private object columnConstants {
val UNB = -1 // UNBOUNDED
val ZER = 0
val ONE = 1
@@ -100,7 +100,7 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
* algorithm. For arrays these SequenceChild objects enable processing exactly one array instance at
* a time, orchestrated by the surrounding sequence's processor.
*/
- protected def sequenceChild(child: Term, groupIndex: Int): SequenceChild = {
+ private def sequenceChild(child: Term, groupIndex: Int): SequenceChild = {
import columnConstants._
val (max, min, ock) = child match {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesFraming.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesFraming.scala
index d22dfda..f4308c3 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesFraming.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesFraming.scala
@@ -35,7 +35,8 @@ import org.apache.daffodil.dsom.TunableLimitExceededError
abstract class SkipRegion(e: Term, skipLengthInBits: Int, propName: String) extends Terminal(e, skipLengthInBits > 0) {
if (skipLengthInBits > e.tunable.maxSkipLengthInBytes * 8) {
- throw new TunableLimitExceededError(e.schemaFileLocation,
+ throw new TunableLimitExceededError(
+ e.schemaFileLocation,
"Property %s %s(bits) is larger than limit %s(bits).", propName, skipLengthInBits, e.tunable.maxSkipLengthInBytes * 8)
}
@@ -47,15 +48,14 @@ case class LeadingSkipRegion(e: Term) extends SkipRegion(e, e.leadingSkipInBits,
case class TrailingSkipRegion(e: Term) extends SkipRegion(e, e.trailingSkipInBits, "trailingSkip") {
- val lengthKindContext = e match {
- case eb: ElementBase => eb
- case _ => {
- Assert.invariant(e.nearestEnclosingElement != None) //root element is an ElementBase, all others have a nearestEnclosingElement
- e.nearestEnclosingElement.get
+ e match {
+ case eb: ElementBase => {
+ e.schemaDefinitionWhen(
+ e.trailingSkip > 0 && eb.lengthKind == LengthKind.Delimited && !e.hasTerminator,
+ "Property terminator must be defined when trailingSkip > 0 and lengthKind='delimited'")
}
+ case _ => // ok
}
- e.schemaDefinitionWhen(e.trailingSkip > 0 && lengthKindContext.lengthKind == LengthKind.Delimited && !e.hasTerminator,
- "Property terminator must be defined when trailingSkip > 0 and lengthKind='delimited'")
}
case class AlignmentFill(e: Term) extends Terminal(e, !e.isKnownToBeAligned) {
@@ -66,11 +66,16 @@ case class AlignmentFill(e: Term) extends Terminal(e, !e.isKnownToBeAligned) {
lazy val unparser: Unparser = new AlignmentFillUnparser(alignment, e.termRuntimeData)
}
-case class MandatoryTextAlignment(e: Term, alignmentInBits: Int, forDelimiter: Boolean) extends Terminal(e,
- if (forDelimiter)
- !e.isDelimiterKnownToBeTextAligned
- else
- !e.isKnownToBeTextAligned) {
+case class MandatoryTextAlignment(
+ e: Term,
+ alignmentInBits: Int,
+ forDelimiter: Boolean)
+ extends Terminal(
+ e,
+ if (forDelimiter)
+ !e.isDelimiterKnownToBeTextAligned
+ else
+ !e.isKnownToBeTextAligned) {
Assert.invariant(alignmentInBits > 0)
lazy val parser: Parser = new MandatoryTextAlignmentParser(alignmentInBits, e.termRuntimeData)
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
index bde32af..df1a1f9 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
@@ -405,6 +405,7 @@ class TestDsomCompiler extends Logging {
val sset = new SchemaSet(testSchema)
val Seq(sch) = sset.schemas
+ val root = sset.root
val Seq(sd, _) = sch.schemaDocuments
// No annotations
@@ -440,10 +441,10 @@ class TestDsomCompiler extends Logging {
// Tests overlapping properties
// because these unit tests are outside the normal framework,
// we sometimes have to demand things in order for errors to be noticed.
- assertTrue(gs3.isError)
- val msgs = gs3.getDiagnostics.mkString("\n").toLowerCase
+ assertTrue(root.isError)
+ val msgs = root.getDiagnostics.mkString("\n").toLowerCase
assertTrue(msgs.contains("overlap"))
- assertTrue(msgs.contains("alignmentUnits".toLowerCase))
+ assertTrue(msgs.contains("initiator".toLowerCase))
}
@Test def test_group_references {
@@ -490,9 +491,9 @@ class TestDsomCompiler extends Logging {
myGlobal3.asInstanceOf[GlobalSequenceGroupDef]
// Tests overlapping properties
- assertTrue(e5ctgref.isError)
+ assertTrue(e5.isError)
- val msg = e5ctgref.getDiagnostics.mkString("\n").toLowerCase
+ val msg = e5.getDiagnostics.mkString("\n").toLowerCase
val res = msg.contains("overlap")
if (!res) println(msg)
assertTrue(res)
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestRefMap.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestRefMap.scala
new file mode 100644
index 0000000..9467aca
--- /dev/null
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestRefMap.scala
@@ -0,0 +1,651 @@
+/*
+ * 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.dsom
+
+import scala.xml.{ XML, Utility, Node }
+import org.junit.Test
+import org.apache.daffodil.compiler._
+import org.apache.daffodil.Implicits._;
+import org.apache.daffodil.schema.annotation.props.gen.{ YesNo, TextNumberRep, SeparatorPosition, Representation, OccursCountKind, NilKind, LengthKind, ChoiceLengthKind, ByteOrder, BinaryNumberRep, AlignmentUnits }
+import org.apache.daffodil.schema.annotation.props.AlignmentType
+import org.apache.daffodil.util.{ Misc, Logging }
+import org.apache.daffodil.xml.XMLUtils
+import junit.framework.Assert._
+import org.apache.daffodil.api.Diagnostic
+import org.apache.daffodil.util._
+import org.junit.Test
+import org.apache.daffodil.schema.annotation.props.Found
+
+class TestRefMap extends Logging {
+
+ val xsd = XMLUtils.XSD_NAMESPACE
+ val dfdl = XMLUtils.dfdlAppinfoSource // XMLUtils.DFDL_NAMESPACE
+ val xsi = XMLUtils.XSI_NAMESPACE
+ val example = XMLUtils.EXAMPLE_NAMESPACE
+
+ @Test def testRefMapEmpty() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(1, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(1, numEntries)
+ val numRefPairs = root.refPairsMap.size
+ assertEquals(1, numRefPairs) // good proxy for schema size
+ val rootDecl = root.referencedElement
+ val rootRefPair = refMap.get(rootDecl.factory)
+ assertTrue(rootRefPair.isDefined)
+ val Seq((fromSSCD, refSpecs)) = rootRefPair.get
+ assertEquals(root.shortSchemaComponentDesignator, fromSSCD)
+ val Seq(RefSpec(rootRef, to, 1)) = refSpecs
+ assertEquals(root, rootRef)
+ assertEquals(rootDecl.factory, to)
+ }
+
+ @Test def testRefMapComplex1() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:sequence>
+ <xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(4, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(2, numEntries)
+ val numRefPairs = root.refPairsMap.size
+ assertEquals(2, numRefPairs) // good proxy for schema size
+ val rootDecl = root.referencedElement
+ val rootRefPair = refMap.get(rootDecl.factory)
+ assertTrue(rootRefPair.isDefined)
+ val Seq((fromSSCD, refSpecs)) = rootRefPair.get
+ assertEquals(root.shortSchemaComponentDesignator, fromSSCD)
+ val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
+ val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef.factory)
+ assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
+ }
+
+ @Test def testRefMapGroupRefSeq1() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:group ref="ex:g"/>
+ </xs:complexType>
+ <xs:group name="g">
+ <xs:sequence>
+ <xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:group>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(4, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(3, numEntries)
+ val numRefPairs = root.refPairsMap.size
+ assertEquals(3, numRefPairs) // good proxy for schema size
+ val rootDecl = root.referencedElement
+ val rootRefPair = refMap.get(rootDecl.factory)
+ assertTrue(rootRefPair.isDefined)
+ val Seq((fromSSCD, refSpecs)) = rootRefPair.get
+ assertEquals(root.shortSchemaComponentDesignator, fromSSCD)
+ val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
+ val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef.factory)
+ assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
+ val gref = rootDecl.complexType.modelGroup.asInstanceOf[SequenceGroupRef]
+ val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef.factory).get
+ assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
+ assertEquals(4, root.numComponents)
+ assertEquals(4, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapGroupRefChoice1() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:group ref="ex:g"/>
+ </xs:complexType>
+ <xs:group name="g">
+ <xs:choice>
+ <xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:choice>
+ </xs:group>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(5, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(3, numEntries)
+ val numRefPairs = root.refPairsMap.size
+ assertEquals(3, numRefPairs) // good proxy for schema size
+ val rootDecl = root.referencedElement
+ val rootRefPair = refMap.get(rootDecl.factory)
+ assertTrue(rootRefPair.isDefined)
+ val Seq((fromSSCD, refSpecs)) = rootRefPair.get
+ assertEquals(root.shortSchemaComponentDesignator, fromSSCD)
+ val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
+ val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef.factory)
+ assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
+ val gref = rootDecl.complexType.modelGroup.asInstanceOf[ChoiceGroupRef]
+ val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef.factory).get
+ assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
+ assertEquals(5, root.numComponents)
+ assertEquals(5, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapGroupRefNest1() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:group ref="ex:g"/>
+ </xs:complexType>
+ <xs:group name="g">
+ <xs:choice>
+ <xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element ref="ex:r1"/>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="r1" type="ex:ct1"/>
+ <xs:complexType name="ct1">
+ <xs:sequence dfdl:hiddenGroupRef="ex:g1"/>
+ </xs:complexType>
+ <xs:group name="g1">
+ <xs:choice>
+ <xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:choice>
+ </xs:group>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(10, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(6, numEntries)
+ val numRefPairs = root.refPairsMap.size
+ assertEquals(6, numRefPairs) // good proxy for schema size
+ val rootDecl = root.referencedElement
+ val rootRefPair = refMap.get(rootDecl.factory)
+ assertTrue(rootRefPair.isDefined)
+ val Seq((fromSSCD, refSpecs)) = rootRefPair.get
+ assertEquals(root.shortSchemaComponentDesignator, fromSSCD)
+ val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
+ val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef.factory)
+ assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
+ val gref = rootDecl.complexType.modelGroup.asInstanceOf[ChoiceGroupRef]
+ val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef.factory).get
+ assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
+ assertEquals(10, root.numComponents)
+ assertEquals(10, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion1() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:sequence>
+ <xs:group ref="ex:g"/>
+ <xs:group ref="ex:g"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:group name="g">
+ <xs:choice>
+ <xs:element ref="ex:r1"/>
+ <xs:element ref="ex:r1"/>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="r1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(25, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(4, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(6, numRefPairs) // good proxy for schema size
+ val allGRefs = root.allGRefs
+ assertEquals(2, allGRefs.size)
+ val allERefsCount = root.allERefs.size
+ assertEquals(2, allERefsCount)
+ val allCTRefsCount = root.allCTRefs.size
+ assertEquals(1, allCTRefsCount)
+ assertEquals(25, root.numComponents)
+ assertEquals(11, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion2() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r" type="ex:ct"/>
+ <xs:complexType name="ct">
+ <xs:sequence>
+ <xs:group ref="ex:g"/>
+ <xs:group ref="ex:g"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:group name="g">
+ <xs:choice>
+ <xs:element ref="ex:r1"/>
+ <xs:element ref="ex:r1"/>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="r1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:r2"/>
+ <xs:element ref="ex:r2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="r2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(57, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(5, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(8, numRefPairs)
+ assertEquals(57, root.numComponents)
+ assertEquals(15, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion3() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="r">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:r1"/>
+ <xs:element ref="ex:r1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="r1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:r2"/>
+ <xs:element ref="ex:r2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="r2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:r3"/>
+ <xs:element ref="ex:r3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="r3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(61, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(4, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(7, numRefPairs)
+ assertEquals(61, root.numComponents)
+ assertEquals(17, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion4() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="e5">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e4"/>
+ <xs:element ref="ex:e4"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e4">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e3"/>
+ <xs:element ref="ex:e3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e2"/>
+ <xs:element ref="ex:e2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e1"/>
+ <xs:element ref="ex:e1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(125, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(5, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(9, numRefPairs)
+ assertEquals(125, root.numComponents)
+ assertEquals(21, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion5() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="e6">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e5"/>
+ <xs:element ref="ex:e5"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e5">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e4"/>
+ <xs:element ref="ex:e4"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e4">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e3"/>
+ <xs:element ref="ex:e3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e2"/>
+ <xs:element ref="ex:e2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e1"/>
+ <xs:element ref="ex:e1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(253, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(6, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(11, numRefPairs)
+ assertEquals(253, root.numComponents)
+ assertEquals(25, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion6() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="e7">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e6"/>
+ <xs:element ref="ex:e6"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e6">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e5"/>
+ <xs:element ref="ex:e5"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e5">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e4"/>
+ <xs:element ref="ex:e4"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e4">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e3"/>
+ <xs:element ref="ex:e3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e2"/>
+ <xs:element ref="ex:e2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e1"/>
+ <xs:element ref="ex:e1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(509, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(7, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(13, numRefPairs)
+ assertEquals(509, root.numComponents)
+ assertEquals(29, root.numUniqueComponents)
+ }
+
+ @Test def testRefMapExplosion7() {
+ val testSchema = SchemaUtils.dfdlTestSchema(
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+ <dfdl:format ref="tns:GeneralFormat"/>,
+ <xs:element name="e8">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e7"/>
+ <xs:element ref="ex:e7"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e7">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e6"/>
+ <xs:element ref="ex:e6"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e6">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e5"/>
+ <xs:element ref="ex:e5"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e5">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e4"/>
+ <xs:element ref="ex:e4"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e4">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e3"/>
+ <xs:element ref="ex:e3"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e2"/>
+ <xs:element ref="ex:e2"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:e1"/>
+ <xs:element ref="ex:e1"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ <xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>)
+ val compiler = Compiler()
+ val sset = compiler.compileNode(testSchema).sset
+ val root = sset.root
+ val comps = root.allComponents
+ assertEquals(1021, comps.length)
+ val refMap = root.refMap
+ val numEntries = refMap.size
+ assertEquals(8, numEntries)
+ val refPairsMap = root.refPairsMap.toSeq
+ val numRefPairs = refPairsMap.map { _._2.length }.sum
+ assertEquals(15, numRefPairs)
+ assertEquals(1021, root.numComponents)
+ assertEquals(33, root.numUniqueComponents)
+ }
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
index f4a7890..25c58d3 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dsom/CompiledExpression1.scala
@@ -217,10 +217,6 @@ class DPathCompileInfo(
final private def writeObject(out: java.io.ObjectOutputStream): Unit = serializeObject(out)
override def toString = "DPathCompileInfo(%s)".format(path)
- /**
- * The immediate containing parent.
- */
- final lazy val immediateEnclosingCompileInfo: Option[DPathCompileInfo] = parent
/**
* The contract here supports the semantics of ".." in paths.
@@ -237,7 +233,7 @@ class DPathCompileInfo(
eci match {
case None => None
case Some(eci) => {
- val eci2 = eci.immediateEnclosingCompileInfo
+ val eci2 = eci.parent
eci2 match {
case None => None
case Some(ci) => {
@@ -258,7 +254,7 @@ class DPathCompileInfo(
final lazy val elementCompileInfo: Option[DPathElementCompileInfo] = this match {
case e: DPathElementCompileInfo => Some(e)
case d: DPathCompileInfo => {
- val eci = d.immediateEnclosingCompileInfo
+ val eci = d.parent
eci match {
case None => None
case Some(ci) => {
@@ -414,39 +410,6 @@ class DPathElementCompileInfo(
}
/**
- * Returns a subset of the possibles which are truly ambiguous siblings.
- * Does not find all such, but if any exist, it finds some ambiguous
- * Siblings. Only returns empty Seq if there are no ambiguous siblings.
- */
- // private def ambiguousModelGroupSiblings(possibles: Seq[DPathElementCompileInfo]) : Seq[DPathElementCompileInfo] = {
- // val ambiguityLists: Seq[Seq[DPathElementCompileInfo]] = possibles.tails.toSeq.map{
- // possiblesList =>
- // if (possiblesList.isEmpty) Nil
- // else {
- // val one = possiblesList.head
- // val rest = possiblesList.tail
- // val ambiguousSiblings = modelGroupSiblings(one, rest)
- // val allAmbiguous =
- // if (ambiguousSiblings.isEmpty) Nil
- // else one +: ambiguousSiblings
- // allAmbiguous
- // }
- // }
- // val firstAmbiguous = ambiguityLists
- // ambiguityLists.head
- // }
-
- /**
- * Returns others that are direct siblings of a specific one.
- *
- * Direct siblings means they have the same parent, but that parent
- * cannot be a choice.
- */
- // private def modelGroupSiblings(one: DPathElementCompileInfo, rest: Seq[DPathElementCompileInfo]): Seq[DPathElementCompileInfo] = {
- // rest.filter(r => one.immediateEnclosingCompileInfo eq r.immediateEnclosingCompileInfo &&
- // one.immediateEnclosingCompileInfo
- // }
- /**
* Issues a good diagnostic with suggestions about near-misses on names
* like missing prefixes.
*/
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
index 50a43ff..3e60962 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/InfosetImpl.scala
@@ -251,16 +251,6 @@ sealed trait DITerm {
def trd: TermRuntimeData
final def termRuntimeData = trd
-
- protected final def dafPrefix = {
- val ee = trd.dpathCompileInfo.immediateEnclosingCompileInfo.getOrElse {
- trd.dpathCompileInfo
- }
- val pre = ee.namespaces.getPrefix(XMLUtils.dafintURI.uri.toString())
- Assert.invariant(pre ne null)
- pre
- }
-
}
/**
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
index f227c11..7daf02b 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section12/aligned_data/Aligned_Data.tdml
@@ -463,9 +463,18 @@
<xs:element name="e31" dfdl:lengthKind="delimited" dfdl:terminator=")">
<xs:complexType>
+ <!--
+ a sequence doesn't have a lengthKind, so the check for trailingSkip
+ with lengthKind 'delimited' won't fail a check on the sequence here.
+ -->
<xs:sequence dfdl:alignment="8" dfdl:alignmentUnits="bits" dfdl:leadingSkip="0" dfdl:trailingSkip="8">
<xs:element name="s1" type="xs:string" dfdl:lengthKind="delimited" dfdl:encoding="ascii" dfdl:alignment="8" dfdl:terminator=":"/>
- <xs:element name="s2" type="xs:string" dfdl:lengthKind="delimited" dfdl:encoding="ascii" dfdl:alignment="8" dfdl:terminator=":"/>
+ <!--
+ this element violates the requirement that when trailingSkip is non-zero and
+ lengthKind is 'delimited' there must be a terminator.
+ -->
+ <xs:element name="s2" type="xs:string" dfdl:lengthKind="delimited" dfdl:encoding="ascii" dfdl:alignment="8"
+ dfdl:trailingSkip="8"/>
</xs:sequence>
</xs:complexType>
</xs:element>