This is an automated email from the ASF dual-hosted git repository.
olabusayo 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 c43887d Refactor isHidden
c43887d is described below
commit c43887d3976e628e0eb75ba1846dce0676d0ceec
Author: olabusayoT <[email protected]>
AuthorDate: Wed Mar 4 15:32:15 2020 -0500
Refactor isHidden
- Removes isHidden from ElementRuntimeData
- Adds isHidden flag to GroupRef
- Adds private hiddenDepth counter (and associated functions)
- Adds increment/decrement logic (HiddenGroupCombinators) for PState/UState
- overrides increment/decrement functions in UStateForSuspension to
fail on UsageError as these have no place in that context
- Adds check to verify we are out of hidden state at the end of
parsing/unparsing
- Adds isHidden/setHidden logic to InfosetElement/DIElement
- adds "info hidden" to debugger and associated tests
- Reorders info subcommands and objects to maintain alphabetic ordering
- refactors childrenThatAreRecursivelyNotDefaultableOrOVC to
canUnparseIfHidden
- Adds hiddenness to UState/PState toString
- add toNameQString for SGR
- updated SDE for no choices and seqs with no defaultable branches
- refactored sequence unparsers to match choice unparsers when checking
for children that can't be unparsed
- Adds tests for group defs used in both hidden/non-hidden sequence &
choice contexts
- Adds tests for multiply nested hiddenGroupRefs
- add tests to check unparseable children for sequences
- Added test for DAFFODIL-2304
DAFFODIL-2281
---
.../it/scala/org/apache/daffodil/CLI/Util.scala | 14 +
.../apache/daffodil/debugger/TestCLIDebugger.scala | 201 +++++++++++++++
.../scala/org/apache/daffodil/dsom/GroupRef.scala | 17 +-
.../org/apache/daffodil/dsom/ModelGroup.scala | 8 +-
.../org/apache/daffodil/dsom/SchemaComponent.scala | 19 +-
.../org/apache/daffodil/dsom/SequenceGroup.scala | 14 -
.../main/scala/org/apache/daffodil/dsom/Term.scala | 52 ++--
.../org/apache/daffodil/grammar/GrammarTerm.scala | 5 +-
.../daffodil/grammar/ModelGroupGrammarMixin.scala | 21 +-
.../grammar/primitives/ChoiceCombinator.scala | 98 +++----
.../grammar/primitives/HiddenGroupCombinator.scala | 37 +++
.../grammar/primitives/SequenceCombinator.scala | 32 ++-
.../runtime1/ChoiceTermRuntime1Mixin.scala | 16 +-
.../runtime1/ElementBaseRuntime1Mixin.scala | 1 -
.../daffodil/runtime1/TermRuntime1Mixin.scala | 9 +-
.../unparsers/ChoiceAndOtherVariousUnparsers.scala | 100 ++++----
.../processors/unparsers/ElementUnparser.scala | 14 +-
.../unparsers/ExpressionEvaluatingUnparsers.scala | 3 +
.../unparsers/HiddenGroupCombinatorUnparser.scala | 45 ++++
.../daffodil/debugger/InteractiveDebugger.scala | 83 ++++--
.../org/apache/daffodil/infoset/Infoset.scala | 2 +
.../org/apache/daffodil/infoset/InfosetImpl.scala | 20 +-
.../infoset/PartialNextElementResolver.scala | 8 +-
.../apache/daffodil/processors/DataProcessor.scala | 1 +
.../daffodil/processors/ProcessorStateBases.scala | 11 +
.../apache/daffodil/processors/RuntimeData.scala | 4 -
.../processors/parsers/ElementCombinator1.scala | 3 +
.../parsers/HiddenGroupCombinatorParser.scala | 45 ++++
.../daffodil/processors/parsers/PState.scala | 4 +-
.../daffodil/processors/parsers/Parser.scala | 1 +
.../daffodil/processors/unparsers/UState.scala | 10 +
.../section14/sequence_groups/HiddenSequences.tdml | 285 +++++++++++++++++++++
.../section14/sequence_groups/SequenceGroup.tdml | 7 +-
.../SequencesWithHiddenRefs.dfdl.xsd | 153 +++++++++++
.../choice_groups/ChoicesInHiddenContexts.dfdl.xsd | 198 ++++++++++++++
.../section15/choice_groups/HiddenChoices.tdml | 232 +++++++++++++++++
.../sequence_groups/TestHiddenSequences.scala | 63 +++++
.../choice_groups/TestHiddenChoices.scala | 56 ++++
38 files changed, 1626 insertions(+), 266 deletions(-)
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/CLI/Util.scala
b/daffodil-cli/src/it/scala/org/apache/daffodil/CLI/Util.scala
index 3521b93..fc350eb 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/CLI/Util.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/CLI/Util.scala
@@ -22,8 +22,10 @@ import net.sf.expectit.ExpectBuilder
import net.sf.expectit.Expect
import net.sf.expectit.filter.Filters.replaceInString
import java.nio.file.Paths
+import java.io.{File, PrintWriter}
import scala.collection.JavaConverters._
import java.util.concurrent.TimeUnit
+
import org.apache.daffodil.xml.XMLUtils
object Util {
@@ -178,4 +180,16 @@ object Util {
"cat " + str
}
}
+
+ def newTempFile(filePrefix: String, fileSuffix: String, optFileContents:
Option[String] = None): File = {
+ val inputFile = File.createTempFile(filePrefix, fileSuffix)
+ inputFile.deleteOnExit
+ if( optFileContents.nonEmpty) {
+ val contents = optFileContents.get
+ val pw = new PrintWriter(inputFile)
+ pw.write(contents)
+ pw.close
+ }
+ inputFile
+ }
}
diff --git
a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
index 2c991cd..1412ab3 100644
---
a/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
+++
b/daffodil-cli/src/it/scala/org/apache/daffodil/debugger/TestCLIDebugger.scala
@@ -899,6 +899,207 @@ class TestCLIdebugger {
}
}
+ @Test def test_CLI_Debugger_InfoHidden_1() {
+ val schemaFile = Util.daffodilPath(
+
"daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequencesWithHiddenRefs.dfdl.xsd")
+ val inputFile = Util.newTempFile("testInput_", ".tmp", optFileContents =
Some("2~3"))
+ val (testSchemaFile, testInputFile) = if (Util.isWindows) {
+ (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile.getAbsolutePath))
+ } else {
+ (schemaFile, inputFile)
+ }
+
+ val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS)
else Util.start("")
+
+ try {
+ val cmd = String.format("%s -d parse -s %s -r e5 %s", Util.binPath,
testSchemaFile, testInputFile)
+ shell.sendLine(cmd)
+ shell.expect(contains("(debug)"))
+
+ shell.sendLine("break f")
+ shell.sendLine("display info hidden")
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("<f>2</f>"))
+ shell.sendLine("quit")
+ } finally {
+ shell.close()
+ }
+ }
+
+ @Test def test_CLI_Debugger_InfoHidden_2() {
+ val schemaFile = Util.daffodilPath(
+
"daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequencesWithHiddenRefs.dfdl.xsd")
+ val inputFile = Util.newTempFile("testInput_", ".tmp", optFileContents =
Some("2~3"))
+ val (testSchemaFile, testInputFile) = if (Util.isWindows) {
+ (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile.getAbsolutePath))
+ } else {
+ (schemaFile, inputFile)
+ }
+
+ val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS)
else Util.start("")
+
+ try {
+ val cmd = String.format("%s -d parse -s %s -r e4 %s", Util.binPath,
testSchemaFile, testInputFile)
+ shell.sendLine(cmd)
+ shell.expect(contains("(debug)"))
+
+ shell.sendLine("break f")
+ shell.sendLine("display info hidden")
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("<f>3</f>"))
+ shell.sendLine("quit")
+ } finally {
+ shell.close()
+ }
+ }
+
+ @Test def test_CLI_Debugger_InfoHidden_3() {
+ val schemaFile = Util.daffodilPath(
+
"daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd")
+ val inputFile = Util.newTempFile("testInput_", ".tmp", optFileContents =
Some("2,3"))
+ val (testSchemaFile, testInputFile) = if (Util.isWindows) {
+ (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile.getAbsolutePath))
+ } else {
+ (schemaFile, inputFile)
+ }
+
+ val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS)
else Util.start("")
+
+ try {
+ val cmd = String.format("%s -d parse -s %s -r e8 %s", Util.binPath,
testSchemaFile, testInputFile)
+ shell.sendLine(cmd)
+ shell.expect(contains("(debug)"))
+
+ shell.sendLine("break a")
+ shell.sendLine("break h")
+ shell.sendLine("break g")
+ shell.sendLine("break e")
+ shell.sendLine("break f")
+ shell.sendLine("display info hidden")
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("<a>2</a>"))
+ shell.expect(contains("<g />"))
+ } finally {
+ shell.close()
+ }
+ }
+
+ @Test def test_CLI_Debugger_InfoHidden_4() {
+ val schemaFile = Util.daffodilPath(
+
"daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd")
+ val inputFile = Util.newTempFile("testInput_", ".tmp", optFileContents =
Some("[6~]9"))
+ val (testSchemaFile, testInputFile) = if (Util.isWindows) {
+ (Util.cmdConvert(schemaFile), Util.cmdConvert(inputFile.getAbsolutePath))
+ } else {
+ (schemaFile, inputFile)
+ }
+
+ val shell = if (Util.isWindows) Util.start("", envp = DAFFODIL_JAVA_OPTS)
else Util.start("")
+
+ try {
+ val cmd = String.format("%s -d parse -s %s -r e9 %s", Util.binPath,
testSchemaFile, testInputFile)
+ shell.sendLine(cmd)
+ shell.expect(contains("(debug)"))
+
+ shell.sendLine("break e")
+ shell.sendLine("break f")
+ shell.sendLine("break g")
+ shell.sendLine("break h")
+ shell.sendLine("break i")
+ shell.sendLine("display info path hidden")
+
+ shell.sendLine("continue")
+ shell.expect(contains(":f"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":i"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":h"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":e"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":f"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":f"))
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":g"))
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":i"))
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":h"))
+ shell.expect(contains("hidden: false"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":e"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains(":f"))
+ shell.expect(contains("hidden: true"))
+
+ shell.sendLine("continue")
+ shell.expect(contains("<h />"))
+ } finally {
+ shell.close()
+ }
+ }
/* See DFDL-1264
@Test def test_3585_CLI_Debugger_simpleDebugger_unparse() {
val schemaFile =
Util.daffodilPath("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/generalSchema.dfdl.xsd")
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
index e9887b9..02e7896 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/GroupRef.scala
@@ -30,6 +30,11 @@ trait GroupRef { self: ModelGroup =>
final def referredToComponent = groupDef
+ /**
+ * Override in sequenceGroupRef and choiceGroupRef for hidden groups
+ */
+ def isHidden: Boolean
+
final override lazy val optReferredToComponent = Some(referredToComponent)
final override protected lazy val groupMembersDef = LV('groupMembers) {
@@ -101,15 +106,12 @@ final class SequenceGroupRef(
refXML: Node,
refLexicalParent: SchemaComponent,
positionArg: Int,
- isHiddenArg: Boolean)
+ override val isHidden: Boolean)
extends SequenceGroupTermBase(refXML, refLexicalParent, positionArg)
with GroupRef {
private lazy val globalGroupDef = globalGroupDefArg // once only
- override def isHidden = isHiddenArg
- override def isHiddenGroupRef = isHiddenArg
-
private lazy val sgd = groupDef.asInstanceOf[GlobalSequenceGroupDef]
override def xmlChildren = sgd.xmlChildren
@@ -129,7 +131,7 @@ final class ChoiceGroupRef(
refXML: Node,
refLexicalParent: SchemaComponent,
positionArg: Int,
- isHiddenArg: Boolean)
+ override val isHidden: Boolean)
extends ChoiceTermBase(refXML, Option(refLexicalParent), positionArg)
with GroupRef {
@@ -137,10 +139,7 @@ final class ChoiceGroupRef(
private lazy val globalGroupDef = globalGroupDefArg // once only
- override def isHidden = isHiddenArg
- override def isHiddenGroupRef = isHiddenArg
-
- override lazy val groupDef = globalGroupDef
+ override lazy val groupDef = LV('cgrGroupDef){ globalGroupDef }.value
private lazy val cgd = groupDef.asInstanceOf[GlobalChoiceGroupDef]
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 c582031..d18c248 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
@@ -71,7 +71,7 @@ object ModelGroupFactory {
val seq = new Sequence(child, lexicalParent, position) // throwaway
just so we can grab local properties to check for hidden
if (seq.hiddenGroupRefOption.isDefined) {
// explicit check here, because we're about to discard this, and
construct
- // a SequenceGroupRef or ChoiceGroupRef, with isHiddenGroupRef =
true. So this
+ // a SequenceGroupRef or ChoiceGroupRef, with isHidden = true. So
this
// temporary sequence will be discarded after this.
seq.checkHiddenGroupRefHasNoChildren
//
@@ -148,8 +148,6 @@ abstract class ModelGroup(index: Int)
requiredEvaluationsIfActivated(groupMembers)
requiredEvaluationsIfActivated(initiatedContentCheck)
- def isHiddenGroupRef: Boolean = false
-
/**
* FIXME: DAFFODIL-2132. This tells us if framing is expressed on the schema.
* It does NOT tell us if that framing occupies bits in the data stream or
not.
@@ -349,7 +347,7 @@ abstract class ModelGroup(index: Int)
// follow it
Seq(e) ++ e.possibleNextSiblingTerms
}
- case Some(s: SequenceTermBase) if s.isHiddenGroupRef =>
s.possibleNextSiblingTerms
+ case Some(gr: GroupRef) if gr.isHidden => gr.possibleNextSiblingTerms
case Some(mg: ModelGroup) if !mg.mustHaveRequiredElement => Seq(mg)
++ mg.possibleNextSiblingTerms
case Some(e: ElementBase) => Seq(e)
case Some(mg: ModelGroup) => Seq(mg)
@@ -370,7 +368,7 @@ abstract class ModelGroup(index: Int)
*/
final def mustHaveRequiredElement: Boolean = LV('mustHaveRequiredElement) {
this match {
- case s: SequenceTermBase if s.isHiddenGroupRef => false
+ case gr: GroupRef if gr.isHidden => false
case s: SequenceTermBase if s.isOrdered =>
groupMembers.exists {
case e: ElementBase => !e.canBeAbsentFromUnparseInfoset
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 0dd20b6..211bac8 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
@@ -115,21 +115,6 @@ trait SchemaComponent
schemaSet.variableMap
}.value
- /**
- * Whether the component is hidden.
- *
- * Override this in the components that can hide - SequenceGroupRef
- * and ChoiceGroupRef
- */
- def isHidden: Boolean = isHiddenLV
-
- private lazy val isHiddenLV = {
- val optEC = enclosingTerms.headOption // FIXME: broken if there are hidden
and non-hidden uses
- optEC match {
- case None => false
- case Some(ec) => ec.isHidden
- }
- }
lazy val schemaComponent: LookupLocation = this
@@ -229,9 +214,9 @@ trait SchemaComponent
case ct: ComplexTypeBase => "ct"
case st: SimpleTypeDefBase => "st=" + st.namedQName.toQNameString
case st: SimpleTypeBase => "st=" +
st.primType.globalQName.toQNameString
- case cgr: ChoiceGroupRef => "cgr" + (if (cgr.position > 1)
cgr.position else "") + "=" + cgr.groupDef.namedQName.toQNameString
+ case cgr: ChoiceGroupRef => "cgr" + (if (cgr.isHidden) "h" else "") +
(if (cgr.position > 1) cgr.position else "") + "=" +
cgr.groupDef.namedQName.toQNameString
case cgd: GlobalChoiceGroupDef => "cgd=" + cgd.namedQName.toQNameString
- case sgr: SequenceGroupRef => "sgr" + (if (sgr.isHiddenGroupRef) "h"
else "") + (if (sgr.position > 1) sgr.position else "") + "=" +
sgr.groupDef.namedQName
+ case sgr: SequenceGroupRef => "sgr" + (if (sgr.isHidden) "h" else "")
+ (if (sgr.position > 1) sgr.position else "") + "=" +
sgr.groupDef.namedQName.toQNameString
case sgd: GlobalSequenceGroupDef => "sgd=" +
sgd.namedQName.toQNameString
case cg: Choice => "c" + (if (cg.position > 1) cg.position else "")
case sg: Sequence => "s" + (if (sg.position > 1) sg.position else "")
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 d412c1a..65f4564 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
@@ -73,8 +73,6 @@ abstract class SequenceTermBase(
def maybeLayerTransformerEv: Maybe[LayerTransformerEv]
- def checkHiddenSequenceIsDefaultableOrOVC: Unit
-
}
/**
@@ -211,16 +209,6 @@ abstract class SequenceGroupTermBase(
}
}
- lazy val checkHiddenSequenceIsDefaultableOrOVC: Unit = {
- if (this.isHidden) {
- val nonDefaultableOrOVC =
- this.childrenInHiddenGroupNotDefaultableOrOVC
- if (nonDefaultableOrOVC.length > 0) {
- this.SDE("Element(s) of hidden group must define
dfdl:outputValueCalc:\n%s", nonDefaultableOrOVC.mkString("\n"))
- }
- }
- }
-
final lazy val isOrdered: Boolean = this.sequenceKind match {
case SequenceKind.Ordered => true
case SequenceKind.Unordered => false
@@ -361,8 +349,6 @@ final class ChoiceBranchImpliedSequence(rawGM: Term)
override def maybeLayerTransformerEv: Maybe[LayerTransformerEv] = Maybe.Nope
- override def checkHiddenSequenceIsDefaultableOrOVC: Unit = ()
-
override def findPropertyOption(pname: String): PropertyLookupResult =
rawGM.findPropertyOption(pname)
/**
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 e842ea9..8531c27 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
@@ -496,7 +496,6 @@ trait Term
case sq: SequenceTermBase if !sq.isOrdered =>
sq.groupMembers.filter { _.isRepresented }
case sq: SequenceDefMixin => {
- // ??? Didin' check for ordered/unordered here.
val psibs = priorSiblings
val representedPriorSiblings = psibs.filter { _.isRepresented }
val (optionalPotentialPriorReversed, requiredPotentialPriorReversed)
=
@@ -512,52 +511,38 @@ trait Term
val firstNonOptional = requiredPotentialPriorReversed.headOption
optionalPotentialPrior ++ firstNonOptional
}
- case _ => Nil // ?? potentially wrong
+ case _ => Nil
}
}
}
/*
- * This function returns at list of simple elements that are descendents of
- * this term that are not defaultable or OVC. This is a requirement for terms
- * inside a hidden group. Note that there is an exception for choices, in
- * which only a single branch be all defaultable or OVC. If any elements in a
- * hidden group are not defaultable or OVC, then it is an SDE. This function
- * assumes it is only called on elements inside of a hidden group.
+ * This function returns a boolean if the values of the term can be figured
+ * out during unparsing or if they don't need to appear in the infoset at
all.
*
- * Note that this currently only requires OVC since default's aren't
- * implemented. This function may need to change when we support defaults.
+ * Usually this means the term/its descendants have a default value (i.e
defaultable),
+ * have defined dfdl:outputValueCalc, or are optional (minOccurs=0)
+ *
+ * Note that this currently only requires OVC and Optionality since defaults
+ * aren't fully implemented everywhere. This function may need to change when
+ * defaults are fully implemented.
*/
- lazy val childrenInHiddenGroupNotDefaultableOrOVC: Seq[ElementBase] = {
- // this should only be called on hidden elements
- val isH = isHidden
- Assert.invariant(isH)
-
+ lazy val canUnparseIfHidden: Boolean = {
val res = this match {
case s: SequenceTermBase => {
- s.groupMembers.flatMap { member =>
- val res = member.childrenInHiddenGroupNotDefaultableOrOVC
+ s.groupMembers.forall { member =>
+ val res = member.canUnparseIfHidden
res
}
}
case c: ChoiceTermBase => {
- val branches = c.groupMembers.map {
_.childrenInHiddenGroupNotDefaultableOrOVC }
- val countFullyDefaultableOrOVCBranches = branches.count { _.length ==
0 }
- if (countFullyDefaultableOrOVCBranches == 0) {
- c.SDE("xs:choice inside a hidden group must contain a branch with
all children having the dfdl:outputValueCalc property set.")
- // TODO: Diagnostics to display which branches contained
non-defaultable elements, and what those elements were
- }
- Nil
+ c.groupMembers.exists { _.canUnparseIfHidden }
}
case e: ElementBase if e.isComplexType => {
- e.complexType.group.childrenInHiddenGroupNotDefaultableOrOVC
+ e.complexType.group.canUnparseIfHidden
}
case e: ElementBase => {
- if (!e.canBeAbsentFromUnparseInfoset) {
- Seq(e)
- } else {
- Nil
- }
+ e.canBeAbsentFromUnparseInfoset
}
}
res
@@ -578,14 +563,13 @@ trait Term
protected def possibleFirstChildTerms: Seq[Term]
/*
- * Returns list of Elements that could be the first child in the infoset
of this model group or element.
- */
+ * Returns list of Elements that could be the first child in the infoset of
this model group or element.
+ */
final lazy val possibleFirstChildElementsInInfoset: Seq[ElementBase] =
LV('possibleFirstChildElementsInInfoset) {
val pfct = possibleFirstChildTerms
val firstChildren = pfct.flatMap {
- case e: ElementBase if e.isHidden => Nil
case e: ElementBase => Seq(e)
- case s: SequenceTermBase if s.isHidden => Nil
+ case gr: GroupRef if gr.isHidden => Nil
case mg: ModelGroup => mg.possibleFirstChildElementsInInfoset
}
firstChildren.distinct
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
index 59145a3..46b6291 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
@@ -102,8 +102,9 @@ abstract class Gram(contextArg: SchemaComponent)
if (q.isEmpty)
EmptyGram
else q
- } else if (q.isEmpty) self
- else {
+ } else if (q.isEmpty) {
+ self
+ } else {
Assert.invariant(!self.isEmpty)
Assert.invariant(!q.isEmpty)
SeqComp(context, self, q)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
index a5fdf10..5ad9835 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ModelGroupGrammarMixin.scala
@@ -18,20 +18,15 @@
package org.apache.daffodil.grammar
import org.apache.daffodil.schema.annotation.props.gen._
-import org.apache.daffodil.dsom.InitiatedTerminatedMixin
-import org.apache.daffodil.dsom.ModelGroup
import org.apache.daffodil.dsom.SharedFactory
+import org.apache.daffodil.dsom.{ChoiceTermBase, GroupRef,
InitiatedTerminatedMixin, ModelGroup, SequenceTermBase, SchemaSet}
import org.apache.daffodil.grammar.primitives.TrailingSkipRegion
import org.apache.daffodil.grammar.primitives.LeadingSkipRegion
import org.apache.daffodil.grammar.primitives.AlignmentFill
import org.apache.daffodil.grammar.primitives.DelimiterStackCombinatorSequence
import org.apache.daffodil.grammar.primitives.DelimiterStackCombinatorChoice
-import org.apache.daffodil.dsom.SequenceTermBase
-import org.apache.daffodil.dsom.ChoiceTermBase
-import org.apache.daffodil.grammar.primitives.DelimiterStackCombinatorChoice
import org.apache.daffodil.runtime1.ModelGroupRuntime1Mixin
-import org.apache.daffodil.grammar.primitives.LeadingSkipRegion
-import org.apache.daffodil.dsom.SchemaSet
+import org.apache.daffodil.grammar.primitives.HiddenGroupCombinator
trait ModelGroupGrammarMixin
extends InitiatedTerminatedMixin
@@ -51,7 +46,7 @@ trait ModelGroupGrammarMixin
}
private lazy val groupContentWithInitiatorTerminator =
prod("groupContentWithInitiatorTerminator") {
- val finalContent =
+ val finalContent = {
if (hasDelimiters ||
immediatelyEnclosingModelGroup.map(_.hasDelimiters).getOrElse(false) //
// The above reference to the delimiters of the enclosing term,
@@ -68,9 +63,15 @@ trait ModelGroupGrammarMixin
case c: ChoiceTermBase => DelimiterStackCombinatorChoice(c, content)
case s: SequenceTermBase => DelimiterStackCombinatorSequence(s,
content)
}
- } else { groupContentDef }
+ } else {
+ groupContent
+ }
+ }
- finalContent
+ this match {
+ case gr: GroupRef if gr.isHidden => new HiddenGroupCombinator(self,
finalContent)
+ case _ => finalContent
+ }
}
/**
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
index 8fd8cb5..abab995 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ChoiceCombinator.scala
@@ -242,58 +242,66 @@ case class ChoiceCombinator(ch: ChoiceTermBase,
alternatives: Seq[Gram])
}
override lazy val unparser: Unparser = {
- if (!ch.isHiddenGroupRef) {
- val (eventRDMap, optDefaultBranch) = ch.choiceBranchMap
- val optDefaultUnparser: Option[Unparser] = optDefaultBranch.map {
defaultBranch =>
- val defaultBranchGram = defaultBranch.termContentBody
- val defaultBranchUnparser = defaultBranchGram.unparser
- if (defaultBranchUnparser.isEmpty) {
- // This is a NadaUnparser, likely caused by a default choice branch
- // that is just an empty sequence. NadaUnparsers throw an assertion
- // when unparsed, but the ChoiceCombinatorUnparser still expects to
- // have a something to unparse, so we have an unparser that just does
- // nothing for this special case
- new ChoiceBranchEmptyUnparser(defaultBranch.runtimeData)
- } else {
- defaultBranchUnparser
- }
+ val (eventRDMap, optDefaultBranch) = ch.choiceBranchMap
+ /*
+ * Since it's impossible to know the hiddenness for terms at this level
(unless
+ * they're a hiddenGroupRef), we always attempt to find a defaultable
unparser.
+ * If we find one, and at runtime, we're in a hidden state, we can use
that. If we
+ * are not in a hidden state, it doesn't get used. If we don't find a
defaultable branch
+ * for a hidden group ref, we SDE because required elements must have a
default value
+ * or dfdl:outputValueCalc defined during unparsing,
+ */
+ val optDefaultUnparser: Option[Unparser] = optDefaultBranch.map {
defaultBranch =>
+ val defaultBranchGram = defaultBranch.termContentBody
+ val defaultBranchUnparser = defaultBranchGram.unparser
+ if (defaultBranchUnparser.isEmpty) {
+ // This is a NadaUnparser, likely caused by a default choice branch
+ // that is just an empty sequence. NadaUnparsers throw an assertion
+ // when unparsed, but the ChoiceCombinatorUnparser still expects to
+ // have a something to unparse, so we have an unparser that just does
+ // nothing for this special case
+ new ChoiceBranchEmptyUnparser(defaultBranch.runtimeData)
+ } else {
+ defaultBranchUnparser
}
+ }
- val eventUnparserMap = eventRDMap.map {
- case (cbe, branchTerm) => (cbe, branchTerm.termContentBody.unparser)
- }
- val mapValues = eventUnparserMap.map { case (k, v) => v
}.toSeq.filterNot(_.isEmpty)
- if (mapValues.isEmpty)
- if (optDefaultBranch.isEmpty)
- new NadaUnparser(null)
- else {
- // just a default branch.
- Assert.invariant(optDefaultUnparser.isDefined)
- optDefaultUnparser.get
+ val branchForUnparse = if (optDefaultUnparser.isEmpty) {
+ ch match {
+ case cgr: ChoiceGroupRef if cgr.isHidden => {
+ /*
+ * This is a requirement for at least one term inside a hidden
choice, we
+ * SDE if there is no descendant that is fully defaultable, optional
or OVC.
+ */
+ cgr.SDE(
+ "At least one branch of hidden choice must be fully defaultable or
define dfdl:outputValueCalc:\n%s",
+ ch.groupMembers.mkString("\n"))
}
- else {
- val cbm = ChoiceBranchMap(eventUnparserMap, optDefaultUnparser)
- new ChoiceCombinatorUnparser(ch.modelGroupRuntimeData, cbm,
choiceLengthInBits)
+ /*
+ * empty unparser is fine as we have no expectations of hiddenness
during
+ * compile time if it's not a hiddenGroupRef
+ */
+ case _ => optDefaultUnparser
}
} else {
- // Choices inside a hidden group ref are slightly different because we
- // will never see events for any of the branches. Instead, we will just
- // always pick the branch in which every thing is defaultble or OVC. It
- // is a warning if more than one of those branches exist. It is an SDE if
- // such a branch does not exist, which is detected elsewhere
+ optDefaultUnparser
+ }
- // this call is necessary since it will throw an SDE if no choice branch
- // was defaultable
- ch.childrenInHiddenGroupNotDefaultableOrOVC
- val defaultableBranches = ch.groupMembers.filter {
_.childrenInHiddenGroupNotDefaultableOrOVC.length == 0 }
- Assert.invariant(defaultableBranches.length > 0)
- if (defaultableBranches.length > 1) {
- SDW(WarnID.ChoiceInsideHiddenGroup, "xs:choice inside a hidden group
has unparse ambiguity: multiple branches exist with all children either
defaulable or have the dfdl:outputValueCalc property set. The first branch will
be chosen during unparse. Defaultable branches are:\n%s",
- defaultableBranches.mkString("\n"))
+ val eventUnparserMap = eventRDMap.map {
+ case (cbe, branchTerm) => (cbe, branchTerm.termContentBody.unparser)
+ }
+ val mapValues = eventUnparserMap.map { case (k, v) => v
}.toSeq.filterNot(_.isEmpty)
+ if (mapValues.isEmpty) {
+ if (branchForUnparse.isEmpty) {
+ new NadaUnparser(null)
+ } else {
+ // just a default branch.
+ Assert.invariant(branchForUnparse.isDefined)
+ branchForUnparse.get
}
- val defaultableBranchRD = defaultableBranches(0).runtimeData
- val defaultableBranchUnparser = alternatives.find(_.context.runtimeData
=:= defaultableBranchRD).get.unparser
- new HiddenChoiceCombinatorUnparser(ch.modelGroupRuntimeData,
defaultableBranchUnparser)
+ } else {
+ val cbm = ChoiceBranchMap(eventUnparserMap, branchForUnparse)
+ new ChoiceCombinatorUnparser(ch.modelGroupRuntimeData, cbm,
choiceLengthInBits)
}
}
}
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/HiddenGroupCombinator.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/HiddenGroupCombinator.scala
new file mode 100644
index 0000000..d5b7f49
--- /dev/null
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/HiddenGroupCombinator.scala
@@ -0,0 +1,37 @@
+/*
+ * 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.grammar.primitives
+
+import org.apache.daffodil.dsom.ModelGroup
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.processors.parsers.Parser
+import org.apache.daffodil.processors.unparsers.Unparser
+import org.apache.daffodil.processors.parsers.HiddenGroupCombinatorParser
+import org.apache.daffodil.processors.unparsers.HiddenGroupCombinatorUnparser
+
+final class HiddenGroupCombinator(
+ ctxt: ModelGroup,
+ body: Gram)
+ extends Terminal(ctxt, !body.isEmpty) {
+
+ lazy val parser: Parser = new
HiddenGroupCombinatorParser(ctxt.modelGroupRuntimeData, body.parser)
+
+ override lazy val unparser: Unparser = new
HiddenGroupCombinatorUnparser(ctxt.modelGroupRuntimeData, body.unparser)
+
+}
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
index 73801fd..59f23ed 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
@@ -61,7 +61,21 @@ class OrderedSequence(sq: SequenceTermBase,
sequenceChildrenArg: Seq[SequenceChi
sequenceChildren.flatMap { _.optSequenceChildParser })
}
override lazy val unparser: Unparser = {
- sq.checkHiddenSequenceIsDefaultableOrOVC
+ sq match {
+ case sgr: SequenceGroupRef if sgr.isHidden =>
+ /*
+ * This is a requirement for all descendants of a hidden sequence, so
we
+ * SDE if all descendants are not fully defaultable, optional or OVC.
+ */
+ val nonUnparseableIfHidden =
sq.groupMembers.filter(!_.canUnparseIfHidden)
+ if (nonUnparseableIfHidden.nonEmpty) {
+ SDE("Element(s) of hidden group must define dfdl:outputValueCalc, be
defaultable or be optional:\n%s",
+ nonUnparseableIfHidden.mkString("\n"))
+ }
+ case _ => {
+ //do nothing as only GroupRefs have the concept of hiddenness at
compile time
+ }
+ }
val childUnparsers = sequenceChildren.flatMap { _.optSequenceChildUnparser
}
if (childUnparsers.isEmpty) new NadaUnparser(null)
else {
@@ -138,7 +152,21 @@ class UnorderedSequence(sq: SequenceTermBase,
sequenceChildrenArg: Seq[SequenceC
}
override lazy val unparser: Unparser = {
- sq.checkHiddenSequenceIsDefaultableOrOVC
+ sq match {
+ case sgr: SequenceGroupRef if sgr.isHidden =>
+ /*
+ * This is a requirement for all descendants of a hidden sequence, so
we
+ * SDE if all descendants are not fully defaultable, optional or OVC.
+ */
+ val nonUnparseableIfHidden = sq.groupMembers.filter(
!_.canUnparseIfHidden)
+ if (nonUnparseableIfHidden.nonEmpty) {
+ SDE("Element(s) of hidden group must define dfdl:outputValueCalc, be
defaultable or be optional:\n%s",
+ nonUnparseableIfHidden.mkString("\n"))
+ }
+ case _ => {
+ //do nothing as only GroupRefs have the concept of hiddenness at
compile state
+ }
+ }
val childUnparsers = sequenceChildren.flatMap { _.optSequenceChildUnparser
}
if (childUnparsers.isEmpty) new NadaUnparser(null)
else {
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ChoiceTermRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ChoiceTermRuntime1Mixin.scala
index 5fe80b0..4c59342 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ChoiceTermRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ChoiceTermRuntime1Mixin.scala
@@ -17,26 +17,21 @@
package org.apache.daffodil.runtime1
-import org.apache.daffodil.dsom.ChoiceTermBase
-import org.apache.daffodil.dsom.ModelGroup
+import org.apache.daffodil.dsom.{ChoiceGroupRef, ChoiceTermBase, ElementBase,
ExpressionCompilers, ModelGroup, SequenceTermBase, Term}
import org.apache.daffodil.infoset.ChoiceBranchStartEvent
import org.apache.daffodil.processors.RuntimeData
import org.apache.daffodil.processors.ChoiceRuntimeData
-import org.apache.daffodil.dsom.ElementBase
import org.apache.daffodil.infoset.ChoiceBranchEvent
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.infoset.ChoiceBranchEndEvent
-import org.apache.daffodil.dsom.SequenceTermBase
import org.apache.daffodil.api.WarnID
import org.apache.daffodil.processors.ChoiceDispatchKeyEv
-import org.apache.daffodil.dsom.ExpressionCompilers
import org.apache.daffodil.dpath.NodeInfo
import org.apache.daffodil.grammar.Gram
import org.apache.daffodil.processors.TermRuntimeData
import org.apache.daffodil.processors.SequenceRuntimeData
import org.apache.daffodil.processors.ElementRuntimeData
import org.apache.daffodil.processors.unparsers.ChoiceBranchMap
-import org.apache.daffodil.dsom.Term
import org.apache.daffodil.grammar.Gram
trait ChoiceTermRuntime1Mixin { self: ChoiceTermBase =>
@@ -97,19 +92,22 @@ trait ChoiceTermRuntime1Mixin { self: ChoiceTermBase =>
// in the arriving infoset for unparse.
//
val optDefaultBranch = {
-
val optEmpty: Option[Term] =
groupMembers.find { gm =>
val ies = gm.identifyingEventsForChoiceBranch
ies.pnes.isEmpty // empty event list makes it the default, not
simply isOpen
- }
- val optDefault: Option[Term] =
+ }
+ val optOpen: Option[Term] =
optEmpty.orElse {
groupMembers.find { gm =>
val ies = gm.identifyingEventsForChoiceBranch
ies.isOpen // first open one is used if there is no branch that
has empty event list. (test ptg_1u)
}
}
+ val optDefault: Option[Term] =
+ optOpen.orElse {
+ groupMembers.find { _.canUnparseIfHidden } //optional, defaultable
or OVC
+ }
optDefault
}
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ElementBaseRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ElementBaseRuntime1Mixin.scala
index a66bc97..4a38540 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ElementBaseRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/ElementBaseRuntime1Mixin.scala
@@ -189,7 +189,6 @@ trait ElementBaseRuntime1Mixin { self: ElementBase =>
name,
targetNamespacePrefix,
thisElementsNamespacePrefix,
- isHidden,
isNillable,
isArray, // can have more than 1 occurrence
isOptional, // can have exactly 0 or 1 occurrence
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/TermRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/TermRuntime1Mixin.scala
index 4a1f0d1..3ed3012 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/TermRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/TermRuntime1Mixin.scala
@@ -122,9 +122,9 @@ trait TermRuntime1Mixin { self: Term =>
Closed(Seq(PNE(eb, true)))
case eb: ElementBase =>
Open(Seq(PNE(eb, false)))
- case stb: SequenceTermBase if stb.isHiddenGroupRef =>
+ case sgr: SequenceGroupRef if sgr.isHidden =>
Open(Nil)
- case ctb: ChoiceTermBase if ctb.isHiddenGroupRef =>
+ case cgr: ChoiceGroupRef if cgr.isHidden =>
Open(Nil)
case ctb: ChoiceTermBase => {
val gms = ctb.groupMembers
@@ -276,7 +276,8 @@ trait TermRuntime1Mixin { self: Term =>
}
res
}
- case stb: SequenceTermBase if !stb.isHidden => {
+ case gr: GroupRef if gr.isHidden => Open(Nil)
+ case stb: SequenceTermBase => {
//
// This case only applies to when we are analyzing a sequence, but
it is
// being considered as contributing possible elements that are after
the
@@ -289,8 +290,6 @@ trait TermRuntime1Mixin { self: Term =>
subTerms.headOption.map {
_.possibleSelfPlusNextLexicalSiblingStreamingUnparserElements }
res.getOrElse(Open(Nil))
}
- case stb: SequenceTermBase if stb.isHidden =>
- Open(Nil)
}
val res = thisItself match {
//
diff --git
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ChoiceAndOtherVariousUnparsers.scala
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ChoiceAndOtherVariousUnparsers.scala
index 160eea8..47cd220 100644
---
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ChoiceAndOtherVariousUnparsers.scala
+++
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ChoiceAndOtherVariousUnparsers.scala
@@ -59,6 +59,8 @@ case class ChoiceBranchMap(
res
}
+ def defaultUnparser = unmappedDefault
+
def childProcessors = lookupTable.values.toSeq ++ unmappedDefault
def keys = lookupTable.keys
@@ -82,7 +84,7 @@ class ChoiceBranchEmptyUnparser(val context: RuntimeData)
class ChoiceCombinatorUnparser(
mgrd: ModelGroupRuntimeData,
- eventUnparserMap: ChoiceBranchMap,
+ choiceBranchMap: ChoiceBranchMap,
choiceLengthInBits: MaybeInt)
extends CombinatorUnparser(mgrd)
with ToBriefXMLImpl {
@@ -90,64 +92,52 @@ class ChoiceCombinatorUnparser(
override val runtimeDependencies = Vector()
- override val childProcessors = eventUnparserMap.childProcessors.toVector
+ override val childProcessors = choiceBranchMap.childProcessors.toVector
def unparse(state: UState): Unit = {
- state.pushTRD(mgrd)
- val event: InfosetAccessor = state.inspectOrError
- val key: ChoiceBranchEvent = event match {
- //
- // The ChoiceBranchStartEvent(...) is not a case class constructor. It
is a
- // hash-table lookup for a cached value. This avoids constructing these
- // objects over and over again.
- //
- case e if e.isStart && e.isElement =>
ChoiceBranchStartEvent(e.erd.namedQName)
- case e if e.isEnd && e.isElement =>
ChoiceBranchEndEvent(e.erd.namedQName)
- case e if e.isStart && e.isArray =>
ChoiceBranchStartEvent(e.erd.namedQName)
- case e if e.isEnd && e.isArray => ChoiceBranchEndEvent(e.erd.namedQName)
- }
-
- val maybeChildUnparser = eventUnparserMap.get(key)
- if (maybeChildUnparser.isEmpty) {
- UnparseError(One(mgrd.schemaFileLocation), One(state.currentLocation),
- "Found next element %s, but expected one of %s.",
- key.qname.toExtendedSyntax,
- eventUnparserMap.keys.map { _.qname.toExtendedSyntax }.mkString(", "))
- }
- val childUnparser = maybeChildUnparser.get
- state.popTRD(mgrd)
- state.pushTRD(childUnparser.context.asInstanceOf[TermRuntimeData])
- if (choiceLengthInBits.isDefined) {
- val suspendableOp = new ChoiceUnusedUnparserSuspendableOperation(mgrd,
choiceLengthInBits.get)
- val choiceUnusedUnparser = new ChoiceUnusedUnparser(mgrd,
choiceLengthInBits.get, suspendableOp)
-
- suspendableOp.captureDOSStartForChoiceUnused(state)
- childUnparser.unparse1(state)
- suspendableOp.captureDOSEndForChoiceUnused(state)
- choiceUnusedUnparser.unparse(state)
+ if (state.withinHiddenNest) {
+ val branchForUnparseIfHidden = choiceBranchMap.defaultUnparser
+ branchForUnparseIfHidden.get.unparse1(state)
} else {
- childUnparser.unparse1(state)
- }
- state.popTRD(childUnparser.context.asInstanceOf[TermRuntimeData])
- }
-}
-
-// Choices inside a hidden group ref (i.e. Hidden Choices) are slightly
-// different because we will never see events for any of the branches. Instead,
-// we will just always pick the branch in which every thing is defaultble or
-// OVC, so we can calculated exactly which branch to take in a hidden choice
-// statically at compile time. That logic is in ChoiceCombinator, and the
-// branch to take is passed into this HiddenChoiceCombinatorUnparser.
-class HiddenChoiceCombinatorUnparser(mgrd: ModelGroupRuntimeData,
branchUnparser: Unparser)
- extends CombinatorUnparser(mgrd)
- with ToBriefXMLImpl {
- override def nom = "HiddenChoice"
- override lazy val runtimeDependencies = Vector()
-
- override lazy val childProcessors = Vector(branchUnparser)
+ state.pushTRD(mgrd)
+ val event: InfosetAccessor = state.inspectOrError
+ val key: ChoiceBranchEvent = event match {
+ //
+ // The ChoiceBranchStartEvent(...) is not a case class constructor. It
is a
+ // hash-table lookup for a cached value. This avoids constructing these
+ // objects over and over again.
+ //
+ case e if e.isStart && e.isElement =>
ChoiceBranchStartEvent(e.erd.namedQName)
+ case e if e.isEnd && e.isElement =>
ChoiceBranchEndEvent(e.erd.namedQName)
+ case e if e.isStart && e.isArray =>
ChoiceBranchStartEvent(e.erd.namedQName)
+ case e if e.isEnd && e.isArray =>
ChoiceBranchEndEvent(e.erd.namedQName)
+ }
- def unparse(state: UState): Unit = {
- branchUnparser.unparse1(state)
+ val maybeChildUnparser = choiceBranchMap.get(key)
+ if (maybeChildUnparser.isEmpty) {
+ UnparseError(One(mgrd.schemaFileLocation), One(state.currentLocation),
+ "Found next element %s, but expected one of %s.",
+ key.qname.toExtendedSyntax,
+ choiceBranchMap.keys.map {
+ _.qname.toExtendedSyntax
+ }.mkString(", "))
+ }
+ val childUnparser = maybeChildUnparser.get
+ state.popTRD(mgrd)
+ state.pushTRD(childUnparser.context.asInstanceOf[TermRuntimeData])
+ if (choiceLengthInBits.isDefined) {
+ val suspendableOp = new ChoiceUnusedUnparserSuspendableOperation(mgrd,
choiceLengthInBits.get)
+ val choiceUnusedUnparser = new ChoiceUnusedUnparser(mgrd,
choiceLengthInBits.get, suspendableOp)
+
+ suspendableOp.captureDOSStartForChoiceUnused(state)
+ childUnparser.unparse1(state)
+ suspendableOp.captureDOSEndForChoiceUnused(state)
+ choiceUnusedUnparser.unparse(state)
+ } else {
+ childUnparser.unparse1(state)
+ }
+ state.popTRD(childUnparser.context.asInstanceOf[TermRuntimeData])
+ }
}
}
diff --git
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
index 2bd7785..06072c8 100644
---
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
+++
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ElementUnparser.scala
@@ -408,8 +408,8 @@ sealed trait RegularElementUnparserStartEndStrategy
()
} else {
val elem =
- if (!erd.isHidden) {
- // Hidden elements are not in the infoset, so we will never get an
event
+ if (!state.withinHiddenNest) {
+ // Elements in a hidden context are not in the infoset, so we will
never get an event
// for them. Only try to consume start events for non-hidden elements
val event = state.advanceOrError
if (!event.isStart || event.erd != erd) {
@@ -437,10 +437,11 @@ sealed trait RegularElementUnparserStartEndStrategy
}
res
} else {
- Assert.invariant(erd.isHidden)
- // Since we never get events for hidden elements, their infoset
elements
+ Assert.invariant(state.withinHiddenNest)
+ // Since we never get events for elements in hidden contexts, their
infoset elements
// will have never been created. This means we need to manually
create them
val e = if (erd.isComplexType) new DIComplex(erd) else new
DISimple(erd)
+ e.setHidden()
state.currentInfosetNode.asComplex.addChild(e, state.tunable)
e
}
@@ -464,7 +465,7 @@ sealed trait RegularElementUnparserStartEndStrategy
Assert.invariant(state.currentInfosetNode.asSimple.erd eq erd)
()
} else {
- if (!erd.isHidden) {
+ if (!state.withinHiddenNest) {
// Hidden elements are not in the infoset, so we will never get an
event
// for them. Only try to consume end events for non-hidden elements
val event = state.advanceOrError
@@ -496,7 +497,7 @@ trait OVCStartEndStrategy
*/
protected final override def unparseBegin(state: UState) {
val elem =
- if (!erd.isHidden) {
+ if (!state.withinHiddenNest) {
// outputValueCalc elements are optional in the infoset. If the next
event
// is for this OVC element, then consume the start/end events.
// Otherwise, the next event is for a following element, and we do not
want
@@ -525,6 +526,7 @@ trait OVCStartEndStrategy
} else {
// Event was hidden and will never exist, create a new InfosetElement
and add it
val e = new DISimple(erd)
+ e.setHidden()
state.currentInfosetNode.asComplex.addChild(e, state.tunable)
e
}
diff --git
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
index 62cb5b4..7906e77 100644
---
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
+++
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala
@@ -135,6 +135,9 @@ class TypeValueCalcUnparser(typeCalculator: TypeCalculator,
repTypeUnparser: Unp
val origInfosetElement = ustate.currentInfosetNode
val tmpInfosetElement =
Infoset.newElement(repTypeRuntimeData).asInstanceOf[DISimple]
+ if (ustate.withinHiddenNest)
+ tmpInfosetElement.setHidden()
+
if (ustate.processorStatus == Success) {
diff --git
a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HiddenGroupCombinatorUnparser.scala
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HiddenGroupCombinatorUnparser.scala
new file mode 100644
index 0000000..5ba81bf
--- /dev/null
+++
b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/HiddenGroupCombinatorUnparser.scala
@@ -0,0 +1,45 @@
+/*
+ * 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.processors.unparsers
+
+import org.apache.daffodil.processors.ModelGroupRuntimeData
+
+/**
+ * The purpose of this combinator is to increment/decrement the depth counter
+ * for hidden groups, and call the group's unparser. As we get deeper into the
+ * hiddenGroupRefs, we'll increment the counter, call the group's unparser,
and as
+ * we unwind from the refs, we'll decrement.
+ */
+class HiddenGroupCombinatorUnparser(
+ ctxt: ModelGroupRuntimeData, bodyUnparser: Unparser)
+ extends CombinatorUnparser(ctxt) {
+
+ override lazy val childProcessors = Vector(bodyUnparser)
+
+ override lazy val runtimeDependencies = Vector()
+
+ def unparse(start: UState): Unit = {
+ try {
+ start.incrementHiddenDef
+ // unparse
+ bodyUnparser.unparse1(start)
+ } finally {
+ start.decrementHiddenDef
+ }
+ }
+}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
index 84380d7..0d9cba0 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/debugger/InteractiveDebugger.scala
@@ -1191,7 +1191,25 @@ class InteractiveDebugger(runner:
InteractiveDebuggerRunner, eCompilers: Express
|multiple times to display multiple pieces of
information.
|
|Example: info data infoset""".stripMargin
- override val subcommands = Seq(InfoBitLimit, InfoBitPosition,
InfoBreakpoints, InfoChildIndex, InfoData, InfoDelimiterStack, InfoDiff,
InfoDiscriminator, InfoDisplays, InfoFoundDelimiter, InfoGroupIndex,
InfoInfoset, InfoOccursIndex, InfoParser, InfoUnparser, InfoPath)
+ override val subcommands =
+ Seq(
+ InfoBitLimit,
+ InfoBitPosition,
+ InfoBreakpoints,
+ InfoChildIndex,
+ InfoData,
+ InfoDelimiterStack,
+ InfoDiff,
+ InfoDiscriminator,
+ InfoDisplays,
+ InfoFoundDelimiter,
+ InfoGroupIndex,
+ InfoHidden,
+ InfoInfoset,
+ InfoOccursIndex,
+ InfoPath,
+ InfoParser,
+ InfoUnparser)
override def validate(args: Seq[String]) {
if (args.size == 0) {
@@ -1231,21 +1249,6 @@ class InteractiveDebugger(runner:
InteractiveDebuggerRunner, eCompilers: Express
}
}
- object InfoOccursIndex extends DebugCommand with
DebugCommandValidateZeroArgs {
- val name = "occursIndex"
- override lazy val short = "oi"
- val desc = "display the current array limit"
- val longDesc = desc
- def act(args: Seq[String], prestate: StateForDebugger, state:
ParseOrUnparseState, processor: Processor): DebugState.Type = {
- if (state.arrayPos != -1) {
- debugPrintln("%s: %d".format(name, state.arrayPos))
- } else {
- debugPrintln("%s: not in an array".format(name))
- }
- DebugState.Pause
- }
- }
-
object InfoBitLimit extends DebugCommand with
DebugCommandValidateZeroArgs {
val name = "bitLimit"
override lazy val short = "bl"
@@ -1497,6 +1500,17 @@ class InteractiveDebugger(runner:
InteractiveDebuggerRunner, eCompilers: Express
}
}
+ object InfoHidden extends DebugCommand with DebugCommandValidateZeroArgs
{
+ val name = "hidden"
+ override lazy val short = "h"
+ val desc = "display whether or not we're within the nesting context of
a hidden group"
+ val longDesc = desc
+ def act(args: Seq[String], prestate: StateForDebugger, state:
ParseOrUnparseState, processor: Processor): DebugState.Type = {
+ debugPrintln("%s: %b".format(name, state.withinHiddenNest))
+ DebugState.Pause
+ }
+ }
+
object InfoInfoset extends DebugCommand with
DebugCommandValidateZeroArgs {
val name = "infoset"
val desc = "display the current infoset"
@@ -1545,23 +1559,21 @@ class InteractiveDebugger(runner:
InteractiveDebuggerRunner, eCompilers: Express
}
}
- abstract class InfoProcessorBase extends DebugCommand with
DebugCommandValidateZeroArgs {
- val desc = "display the current Daffodil " + name
+ object InfoOccursIndex extends DebugCommand with
DebugCommandValidateZeroArgs {
+ val name = "occursIndex"
+ override lazy val short = "oi"
+ val desc = "display the current array limit"
val longDesc = desc
def act(args: Seq[String], prestate: StateForDebugger, state:
ParseOrUnparseState, processor: Processor): DebugState.Type = {
- debugPrintln("%s: %s".format(name, processor.toBriefXML(2))) // only
2 levels of output, please!
+ if (state.arrayPos != -1) {
+ debugPrintln("%s: %d".format(name, state.arrayPos))
+ } else {
+ debugPrintln("%s: not in an array".format(name))
+ }
DebugState.Pause
}
}
- object InfoParser extends {
- override val name = "parser" // scala -xcheckinit reported this was
uninitialized
- } with InfoProcessorBase
-
- object InfoUnparser extends {
- override val name = "unparser"
- } with InfoProcessorBase
-
object InfoPath extends DebugCommand with DebugCommandValidateZeroArgs {
val name = "path"
override lazy val short = "path"
@@ -1572,6 +1584,23 @@ class InteractiveDebugger(runner:
InteractiveDebuggerRunner, eCompilers: Express
DebugState.Pause
}
}
+
+ abstract class InfoProcessorBase extends DebugCommand with
DebugCommandValidateZeroArgs {
+ val desc = "display the current Daffodil " + name
+ val longDesc = desc
+ def act(args: Seq[String], prestate: StateForDebugger, state:
ParseOrUnparseState, processor: Processor): DebugState.Type = {
+ debugPrintln("%s: %s".format(name, processor.toBriefXML(2))) // only
2 levels of output, please!
+ DebugState.Pause
+ }
+ }
+
+ object InfoParser extends {
+ override val name = "parser" // scala -xcheckinit reported this was
uninitialized
+ } with InfoProcessorBase
+
+ object InfoUnparser extends {
+ override val name = "unparser"
+ } with InfoProcessorBase
}
object Quit extends DebugCommand with DebugCommandValidateZeroArgs {
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
index 17b31d9..e07aba7 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/Infoset.scala
@@ -62,6 +62,8 @@ trait InfosetElement extends InfosetItem {
def namespace: NS
def name: String
def isHidden: Boolean
+ def setHidden(): Unit
+
}
trait InfosetComplexElement extends InfosetElement {
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 b314faa..d335481 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
@@ -863,18 +863,16 @@ sealed trait DIElement
}
/**
- * Note: there is no infoset data member for isHidden. A hidden group is
- * a DFDL schema characteristic for a model group. Elements inside it will
- * have (their element base) isHidden statically on the schema. So there is
- * no notion of creating an infoset element then making it hidden by marking
- * it in some way. Rather, the corresponding elementRuntimeData tells you
whether
- * it is hidden or not.
- *
- * When we convert to XML, then if we want to preserve information about
- * things being hidden (for inspection by looking at the XML) then we
- * need to add an attribute. But for the infoset itself, we don't need it.
+ * If we are in a hidden context, isHidden should be true for the infoset
+ * data member. Therefore, when a new element is created in a hidden context
+ * we set isHidden to true.
*/
- final def isHidden: Boolean = erd.isHidden
+ protected final var _isHidden = false
+ final def isHidden: Boolean = _isHidden
+
+ override def setHidden: Unit = {
+ _isHidden = true
+ }
final def runtimeData = erd
protected final var _parent: InfosetComplexElement = null
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/PartialNextElementResolver.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/PartialNextElementResolver.scala
index f7c51ce..c7962ac 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/PartialNextElementResolver.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/infoset/PartialNextElementResolver.scala
@@ -76,12 +76,8 @@ trait NextElementResolver { self: InfosetInputter =>
// set of possible elements.
//
maybeERD = resolver.maybeNextElement(name, nameSpace, hasNamespace)
- //
- // If the ERD is marked hidden, then we never expect any events
corresponding
- // to its elements.
- //
- if (maybeERD.isDefined && maybeERD.get.isHidden)
- maybeERD = Nope // clobber it back to Nope
+ // The cases where ERD is in a hidden context are addressed where the
elements
+ // are assigned their value i.e ElementUnparser
}
} // end while
//
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
index 5aeabbb..3adc8ac 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
@@ -437,6 +437,7 @@ class DataProcessor(
Assert.invariant(state.currentInfosetNodeMaybe.isEmpty)
Assert.invariant(state.escapeSchemeEVCache.isEmpty)
Assert.invariant(state.maybeTopTRD().isEmpty) // dynamic TRD stack is empty
+ Assert.invariant(!state.withinHiddenNest) //ensure we are not in hidden
nest
//
// All the DOS that precede the last one
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
index c7e737e..2e226e4 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/ProcessorStateBases.scala
@@ -480,6 +480,17 @@ abstract class ParseOrUnparseState protected (
res
}
+ private var _hiddenDepth = 0
+
+ def incrementHiddenDef = {
+ _hiddenDepth += 1
+ }
+ def decrementHiddenDef = {
+ _hiddenDepth -= 1
+ }
+
+ def withinHiddenNest: Boolean = _hiddenDepth > 0
+
/**
* The User API sets the debugger and debug on/off flag on the DataProcessor
object.
* When a PState or UState is created by the DataProcessor, the DataProcessor
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
index ed0c6b7..1387a90 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala
@@ -631,7 +631,6 @@ sealed class ElementRuntimeData(
@TransientParam nameArg: => String,
@TransientParam targetNamespacePrefixArg: => String,
@TransientParam thisElementsNamespacePrefixArg: => String,
- @TransientParam isHiddenArg: => Boolean,
@TransientParam isNillableArg: => Boolean,
@TransientParam isArrayArg: => Boolean, // can have more than 1 occurrence
@TransientParam isOptionalArg: => Boolean, // can have only 0 or 1 occurrence
@@ -691,7 +690,6 @@ sealed class ElementRuntimeData(
lazy val name = nameArg
lazy val targetNamespacePrefix = targetNamespacePrefixArg
lazy val thisElementsNamespacePrefix = thisElementsNamespacePrefixArg
- lazy val isHidden = isHiddenArg
lazy val isNillable = isNillableArg
override lazy val isArray = isArrayArg
lazy val isOptional = isOptionalArg
@@ -727,7 +725,6 @@ sealed class ElementRuntimeData(
name
targetNamespacePrefix
thisElementsNamespacePrefix
- isHidden
isNillable
isArray
isOptional
@@ -825,7 +822,6 @@ sealed abstract class ErrorERD(local: String, namespaceURI:
String)
local, // nameArg: => String,
null, // targetNamespacePrefixArg: => String,
null, // thisElementsNamespacePrefixArg: => String,
- false, // isHiddenArg: => Boolean,
false, // isNillableArg: => Boolean,
false, // isArrayArg: => Boolean, // can have more than 1 occurrence
false, // isOptionalArg: => Boolean, // can have only 0 or 1 occurrence
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
index f63e466..646ccae 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ElementCombinator1.scala
@@ -29,6 +29,7 @@ import org.apache.daffodil.processors.ElementRuntimeData
import org.apache.daffodil.processors.Processor
import org.apache.daffodil.processors.Success
import org.apache.daffodil.processors.TermRuntimeData
+import org.apache.daffodil.processors.ModelGroupRuntimeData
abstract class ElementParserBase(
rd: TermRuntimeData,
@@ -244,6 +245,8 @@ class ElementParser(
def parseBegin(pstate: PState): Unit = {
val currentElement = Infoset.newElement(erd).asInstanceOf[DIElement]
+ if (pstate.withinHiddenNest)
+ currentElement.setHidden()
log(LogLevel.Debug, "currentElement = %s", currentElement)
val priorElement = pstate.infoset
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/HiddenGroupCombinatorParser.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/HiddenGroupCombinatorParser.scala
new file mode 100644
index 0000000..5566531
--- /dev/null
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/HiddenGroupCombinatorParser.scala
@@ -0,0 +1,45 @@
+/*
+ * 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.processors.parsers
+
+import org.apache.daffodil.processors.ModelGroupRuntimeData
+
+/**
+ * The purpose of this combinator is to increment/decrement the depth counter
+ * for hidden groups, call the group's parser. As we get deeper into the
+ * hiddenGroupRefs, we'll increment the counter, call the group's parser, and
as
+ * we unwind from the refs, we'll decrement.
+ */
+class HiddenGroupCombinatorParser(
+ ctxt: ModelGroupRuntimeData, bodyParser: Parser)
+ extends CombinatorParser(ctxt) {
+
+ override lazy val childProcessors = Vector(bodyParser)
+
+ override lazy val runtimeDependencies = Vector()
+
+ def parse(start: PState): Unit = {
+ try {
+ start.incrementHiddenDef
+ // parse
+ bodyParser.parse1(start)
+ } finally {
+ start.decrementHiddenDef
+ }
+ }
+}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
index 1e8f6b6..463b8d2 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala
@@ -215,7 +215,8 @@ final class PState private (
override def toString() = {
// threadCheck()
- "PState( bitPos=%s status=%s )".format(bitPos0b, processorStatus)
+ val hidden = if (withinHiddenNest) "hidden " else ""
+ "PState( bitPos=%s status=%s %s)".format(bitPos0b, processorStatus, hidden)
}
def currentLocation: DataLocation = {
@@ -360,6 +361,7 @@ final class PState private (
try {
if (optThrown.isEmpty) {
Assert.invariant(this.discriminatorStack.length == 1)
+ Assert.invariant(!this.withinHiddenNest) //ensure we are not in hidden
nest
mpstate.verifyFinalState()
}
// These we check regardless of throw or not.
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
index 5f5d86a..978015b 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/Parser.scala
@@ -42,6 +42,7 @@ import org.apache.daffodil.processors.CombinatorProcessor
import org.apache.daffodil.processors.PrimProcessor
import org.apache.daffodil.processors.TextProcessor
import org.apache.daffodil.processors.PrimProcessorNoData
+import org.apache.daffodil.processors.ModelGroupRuntimeData
/**
* Encapsulates lower-level parsing with a uniform interface
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
index adf52e3..d45e08b 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala
@@ -423,6 +423,10 @@ final class UStateForSuspension(
override def documentElement = mainUState.documentElement
+ override def incrementHiddenDef = Assert.usageError("Unparser suspended
UStates need not be aware of hidden contexts")
+ override def decrementHiddenDef = Assert.usageError("Unparser suspended
UStates need not be aware of hidden contexts")
+ override def withinHiddenNest = Assert.usageError("Unparser suspended
UStates need not be aware of hidden contexts")
+
}
final class UStateMain private (
@@ -649,6 +653,12 @@ final class UStateMain private (
}
final override def documentElement = inputter.documentElement
+
+ override def toString = {
+ val elt = if (this.currentInfosetNodeMaybe.isDefined) "node=" +
this.currentInfosetNode.toString else ""
+ val hidden = if (withinHiddenNest) " hidden" else ""
+ "UState(" + elt + hidden + " DOS=" + dataOutputStream.toString() + ")"
+ }
}
class SuspensionDeadlockException(suspExprs: Seq[Suspension])
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/HiddenSequences.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/HiddenSequences.tdml
new file mode 100644
index 0000000..ae2d344
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/HiddenSequences.tdml
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<tdml:testSuite xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://example.com"
+ xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions" defaultRoundTrip="none">
+
+ <tdml:parserTestCase name="parseHiddenGroupRef" root="e1"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[2,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e1>
+ <g>3</g>
+ </e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseRegularGroupRef" root="e2"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[2,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <f>2</f>
+ <g>3</g>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseSeqOfHiddenAndRegularRef" root="e3"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[2,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <g>
+ <f>3</f>
+ </g>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseNestedHiddenAndRegularRef" root="e4"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[6~9]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e4>
+ <f>
+ <h>
+ <f>9</f>
+ </h>
+ </f>
+ </e4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseNestedRegularAndHiddenRef" root="e5"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[6~9]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e5>
+ <f>
+ <h>
+ <f>6</f>
+ </h>
+ </f>
+ </e5>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseNestedHiddenGroupRefs" root="e6"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[6~9]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e6>
+ <q>
+ <h />
+ </q>
+ </e6>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:unparserTestCase name="unparseHiddenGroupRef" root="e1"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <g>7</g>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1,7]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseRegularGroupRef" root="e2"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e2>
+ <f>17</f>
+ <g>12</g>
+ </ex:e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1,12]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseSeqOfHiddenAndRegularRef" root="e3"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e3>
+ <g>
+ <f>3</f>
+ </g>
+ </ex:e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1,1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedHiddenAndRegularRef" root="e4"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e4>
+ <f>
+ <h>
+ <f>9</f>
+ </h>
+ </f>
+ </ex:e4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1~1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedRegularAndHiddenRef" root="e5"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e5>
+ <f>
+ <h>
+ <f>9</f>
+ </h>
+ </f>
+ </ex:e5>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1~1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedHiddenGroupRefs" root="e6"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e6>
+ <q>
+ <h />
+ </q>
+ </ex:e6>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1~1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="noOVCinHiddenContext" root="e7"
+ model="SequencesWithHiddenRefs.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e7 />
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>hidden group</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>dfdl:outputValueCalc</tdml:error>
+ <tdml:error>optional</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="nestedNoOVCinHiddenContext" root="e8"
+ model="SequencesWithHiddenRefs.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e8>
+ <g>7</g>
+ </ex:e8>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>hidden group</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>dfdl:outputValueCalc</tdml:error>
+ <tdml:error>optional</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="ignoredHiddenGroupRefWithNoSequenceParent"
root="e9"
+ model="SequencesWithHiddenRefs.dfdl.xsd"
+ description="the hiddenGroupRef is not wrapped in a sequence and is
ignored by daffodil">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e9>
+ <g>7</g>
+ </ex:e9>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:warnings>
+ <tdml:warning>Schema Definition Warning</tdml:warning>
+ <tdml:warning>DFDL property was ignored: hiddenGroupRef</tdml:warning>
+ </tdml:warnings>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[7]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
index 05805ba..3e6b4e7 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
@@ -1406,9 +1406,10 @@
<tdml:documentPart type="text"><![CDATA[145,2]]></tdml:documentPart>
</tdml:document>
<tdml:errors>
- <tdml:error>choice</tdml:error>
- <tdml:error>hidden group</tdml:error>
- <tdml:error>outputValueCalc</tdml:error>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>hidden choice</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>dfdl:outputValueCalc</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequencesWithHiddenRefs.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequencesWithHiddenRefs.dfdl.xsd
new file mode 100644
index 0000000..3b43fd3
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequencesWithHiddenRefs.dfdl.xsd
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ex="http://example.com"
+ targetNamespace="http://example.com" elementFormDefault="unqualified">
+ <xs:include
+ schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited" />
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:group name="s1">
+ <xs:sequence>
+ <xs:element name="f" type="xs:int" dfdl:outputValueCalc="{ 1 }" />
+ </xs:sequence>
+ </xs:group>
+ <xs:element name="e1" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s1" />
+ <xs:element name="g" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:group ref="ex:s1" />
+ <xs:element name="g" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s1" />
+ <xs:element name="g">
+ <xs:complexType>
+ <xs:group ref="ex:s1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:group name="s2">
+ <xs:sequence>
+ <xs:element name="f">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:group ref="ex:s1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="s3">
+ <xs:sequence>
+ <xs:element name="q">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:sequence dfdl:hiddenGroupRef="ex:s1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:group>
+ <xs:element name="e4" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s2" />
+ <xs:group ref="ex:s2" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e5" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:group ref="ex:s2" />
+ <xs:sequence dfdl:hiddenGroupRef="ex:s2" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e6" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:group ref="ex:s3" />
+ <xs:sequence dfdl:hiddenGroupRef="ex:s3" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:group name="s4">
+ <xs:sequence>
+ <xs:element name="f" type="xs:int" />
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="s5">
+ <xs:sequence>
+ <xs:sequence dfdl:hiddenGroupRef="ex:s4" />
+ </xs:sequence>
+ </xs:group>
+ <xs:group name="s6">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s4" />
+ </xs:group>
+ <xs:element name="e7" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s4" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e8" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s5" />
+ <xs:element name="g" type="xs:int"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e9" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:s6" />
+ <xs:element name="g" type="xs:int"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
new file mode 100644
index 0000000..1fe0c0f
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/ChoicesInHiddenContexts.dfdl.xsd
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ex="http://example.com"
+ targetNamespace="http://example.com" elementFormDefault="unqualified">
+ <xs:include
+ schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited" />
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:group name="c1">
+ <xs:choice>
+ <xs:element name="e" type="xs:string" dfdl:initiator="["
+ dfdl:outputValueCalc="{ 'hello' }" />
+ <xs:element name="f" type="xs:int" dfdl:outputValueCalc="{ 1 }" />
+ </xs:choice>
+ </xs:group>
+ <xs:group name="c3">
+ <xs:choice>
+ <xs:element name="e" type="xs:string" dfdl:initiator="[" />
+ <xs:element name="f" type="xs:int" />
+ </xs:choice>
+ </xs:group>
+ <xs:element name="e1" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c1" />
+ <xs:element name="g" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e2" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:group ref="ex:c1" />
+ <xs:element name="g" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e3" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c1" />
+ <xs:element name="g">
+ <xs:complexType>
+ <xs:group ref="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:group name="c2">
+ <xs:choice>
+ <xs:element name="f" dfdl:initiator="[">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="i" type="xs:int" dfdl:initiator="["
+ dfdl:outputValueCalc="{ 1 }" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:group ref="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="g" dfdl:initiator="]">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="i" dfdl:initiator="]" type="xs:string"
+ dfdl:outputValueCalc="{ 'hello' }" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:group ref="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:group>
+ <xs:group name="c4">
+ <xs:choice>
+ <xs:element name="f" dfdl:initiator="[">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="i" type="xs:int" dfdl:initiator="["
+ dfdl:outputValueCalc="{ 1 }" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:sequence dfdl:hiddenGroupRef="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="g" dfdl:initiator="]">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="i" dfdl:initiator="]" type="xs:string"
+ dfdl:outputValueCalc="{ 'hello' }" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:sequence dfdl:hiddenGroupRef="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ </xs:group>
+ <xs:element name="e4" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c2" />
+ <xs:group ref="ex:c2" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e5" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:group ref="ex:c2" />
+ <xs:sequence dfdl:hiddenGroupRef="ex:c2" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e6" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c3" />
+ <xs:element name="g" type="xs:int" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e7" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:element name="a" type="xs:int" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="g">
+ <xs:complexType>
+ <xs:sequence dfdl:hiddenGroupRef="ex:c3" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e8" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator=",">
+ <xs:element name="a" type="xs:int" />
+ <xs:element name="h">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="g">
+ <xs:complexType>
+ <xs:sequence dfdl:hiddenGroupRef="ex:c1" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="e9" dfdl:lengthKind="delimited">
+ <xs:complexType>
+ <xs:sequence dfdl:separator="~">
+ <xs:sequence dfdl:hiddenGroupRef="ex:c4" />
+ <xs:group ref="ex:c4" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
new file mode 100644
index 0000000..e4094ac
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/HiddenChoices.tdml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<tdml:testSuite xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://example.com"
+ xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions" defaultRoundTrip="none">
+
+ <tdml:parserTestCase name="parseHiddenGroupRef" root="e1"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[string,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e1>
+ <g>3</g>
+ </e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseRegularGroupRef" root="e2"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[string,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e2>
+ <e>string</e>
+ <g>3</g>
+ </e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseSeqOfHiddenAndRegularRef" root="e3"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[2,3]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e3>
+ <g>
+ <f>3</f>
+ </g>
+ </e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseNestedHiddenAndRegularRef" root="e4"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[6~]9]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e4>
+ <g>
+ <h>
+ <f>9</f>
+ </h>
+ </g>
+ </e4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="parseNestedHiddenGroupRefs" root="e9"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[6~]9]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <e9>
+ <g>
+ <h />
+ </g>
+ </e9>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:unparserTestCase name="unparseHiddenGroupRef" root="e1"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e1>
+ <g>3</g>
+ </ex:e1>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[hello,3]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseRegularGroupRef" root="e2"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e2>
+ <f>4</f>
+ <g>3</g>
+ </ex:e2>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[1,3]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseSeqOfHiddenAndRegularRef" root="e3"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e3>
+ <g>
+ <e>testing</e>
+ </g>
+ </ex:e3>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart
type="text"><![CDATA[[hello,[hello]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedHiddenAndRegularRef" root="e4"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e4>
+ <g>
+ <h>
+ <f>3</f>
+ </h>
+ </g>
+ </ex:e4>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[[[1~]1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedRegularAndHiddenRef"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e5>
+ <g>
+ <h>
+ <f>3</f>
+ </h>
+ </g>
+ </ex:e5>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[]1~[[1]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="unparseNestedHiddenGroupRefs"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e9>
+ <g>
+ <h />
+ </g>
+ </ex:e9>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:document>
+ <tdml:documentPart
type="text"><![CDATA[[[1~][hello]]></tdml:documentPart>
+ </tdml:document>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="noOVCinHiddenContext" root="e6"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e6/>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>hidden choice</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>dfdl:outputValueCalc</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+ <tdml:unparserTestCase name="nestedNoOVCinHiddenContext" root="e7"
+ model="ChoicesInHiddenContexts.dfdl.xsd" description="hidden group ref">
+ <tdml:infoset>
+ <tdml:dfdlInfoset>)
+ <ex:e7/>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:errors>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>hidden choice</tdml:error>
+ <tdml:error>defaultable</tdml:error>
+ <tdml:error>dfdl:outputValueCalc</tdml:error>
+ </tdml:errors>
+ </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestHiddenSequences.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestHiddenSequences.scala
new file mode 100644
index 0000000..9903dcf
--- /dev/null
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestHiddenSequences.scala
@@ -0,0 +1,63 @@
+/*
+ * 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.section14.sequence_groups
+
+import org.junit.Test
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+
+object TestHiddenSequences {
+
+ val testDir = "/org/apache/daffodil/section14/sequence_groups/"
+
+ val runner = Runner(testDir, "HiddenSequences.tdml", validateTDMLFile = true)
+
+ @AfterClass def shutDown {
+ runner.reset
+ }
+
+}
+
+class TestHiddenSequences {
+
+ import TestHiddenSequences._
+
+
+ @Test def test_parseHiddenGroupRef() {
runner.runOneTest("parseHiddenGroupRef") }
+ @Test def test_parseRegularGroupRef() {
runner.runOneTest("parseRegularGroupRef") }
+ @Test def test_parseSeqOfHiddenAndRegularRef() {
runner.runOneTest("parseSeqOfHiddenAndRegularRef") }
+ @Test def test_parseNestedHiddenAndRegularRef() {
runner.runOneTest("parseNestedHiddenAndRegularRef") }
+ @Test def test_parseNestedRegularAndHiddenRef() {
runner.runOneTest("parseNestedRegularAndHiddenRef") }
+ @Test def test_parseNestedHiddenGroupRefs() {
runner.runOneTest("parseNestedHiddenGroupRefs") }
+
+ @Test def test_unparseHiddenGroupRef() {
runner.runOneTest("unparseHiddenGroupRef") }
+ @Test def test_unparseRegularGroupRef() {
runner.runOneTest("unparseRegularGroupRef") }
+ @Test def test_unparseSeqOfHiddenAndRegularRef() {
runner.runOneTest("unparseSeqOfHiddenAndRegularRef") }
+ @Test def test_unparseNestedHiddenAndRegularRef() {
runner.runOneTest("unparseNestedHiddenAndRegularRef") }
+ @Test def test_unparseNestedRegularAndHiddenRef() {
runner.runOneTest("unparseNestedRegularAndHiddenRef") }
+ @Test def test_unparseNestedHiddenGroupRefs() {
runner.runOneTest("unparseNestedHiddenGroupRefs") }
+ @Test def test_noOVCinHiddenContext() {
runner.runOneTest("noOVCinHiddenContext") }
+ @Test def test_nestedNoOVCinHiddenContext() {
runner.runOneTest("nestedNoOVCinHiddenContext") }
+
+ /*
+ * FIXME DAFFODIL-2304; Dropped hiddenGroupRef
+ * This will fail once fixed, as no warrning will be generated and the
output data will changed
+ */
+ @Test def test_ignoredHiddenGroupRefWithNoSequenceParent() {
runner.runOneTest("ignoredHiddenGroupRefWithNoSequenceParent") }
+
+}
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
new file mode 100644
index 0000000..51c0e69
--- /dev/null
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestHiddenChoices.scala
@@ -0,0 +1,56 @@
+/*
+ * 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.section15.choice_groups
+
+import org.junit.Test
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+
+object TestHiddenChoices {
+
+ val testDir = "/org/apache/daffodil/section15/choice_groups/"
+
+ val runner = Runner(testDir, "HiddenChoices.tdml", validateTDMLFile = true)
+
+ @AfterClass def shutDown {
+ runner.reset
+ }
+
+}
+
+class TestHiddenChoices {
+
+ import TestHiddenChoices._
+
+
+ @Test def test_parseHiddenGroupRef() {
runner.runOneTest("parseHiddenGroupRef") }
+ @Test def test_parseRegularGroupRef() {
runner.runOneTest("parseRegularGroupRef") }
+ @Test def test_parseSeqOfHiddenAndRegularRef() {
runner.runOneTest("parseSeqOfHiddenAndRegularRef") }
+ @Test def test_parseNestedHiddenAndRegularRef() {
runner.runOneTest("parseNestedHiddenAndRegularRef") }
+ @Test def test_parseNestedHiddenGroupRefs() {
runner.runOneTest("parseNestedHiddenGroupRefs") }
+
+ @Test def test_unparseHiddenGroupRef() {
runner.runOneTest("unparseHiddenGroupRef") }
+ @Test def test_unparseRegularGroupRef() {
runner.runOneTest("unparseRegularGroupRef") }
+ @Test def test_unparseSeqOfHiddenAndRegularRef() {
runner.runOneTest("unparseSeqOfHiddenAndRegularRef") }
+ @Test def test_unparseNestedHiddenAndRegularRef() {
runner.runOneTest("unparseNestedHiddenAndRegularRef") }
+ @Test def test_unparseNestedRegularAndHiddenRef() {
runner.runOneTest("unparseNestedRegularAndHiddenRef") }
+ @Test def test_unparseNestedHiddenGroupRefs() {
runner.runOneTest("unparseNestedHiddenGroupRefs") }
+ @Test def test_noOVCinHiddenContext() {
runner.runOneTest("noOVCinHiddenContext") }
+ @Test def test_nestedNoOVCinHiddenContext() {
runner.runOneTest("nestedNoOVCinHiddenContext") }
+
+}