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>