You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ja...@apache.org on 2019/10/02 20:14:16 UTC
[incubator-daffodil] branch master updated: Implemented unordered
sequences
This is an automated email from the ASF dual-hosted git repository.
jadams 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 e23ed92 Implemented unordered sequences
e23ed92 is described below
commit e23ed924e1aab5a378c6b6686064577befceb82c
Author: Josh Adams <ja...@tresys.com>
AuthorDate: Thu Jul 11 09:52:34 2019 -0400
Implemented unordered sequences
Unordered sequences are now ipmlemented using a choice of the sequence
member parsers. This choice is then looped over until we either consume
all the data or hit a failure. The parsed infoset is then sorted into
schema definition order, and unparsing is identical to ordered
sequences.
DAFFODIL-1159
---
.../org/apache/daffodil/dsom/ElementBase.scala | 1 +
.../org/apache/daffodil/dsom/SequenceGroup.scala | 1 -
.../main/scala/org/apache/daffodil/dsom/Term.scala | 10 +-
.../org/apache/daffodil/grammar/AlignedMixin.scala | 30 +-
.../daffodil/grammar/SequenceGrammarMixin.scala | 18 +-
.../grammar/primitives/ElementCombinator.scala | 33 +-
.../grammar/primitives/SequenceChild.scala | 4 +-
.../grammar/primitives/SequenceCombinator.scala | 79 +++
.../apache/daffodil/dsom/TestDsomCompiler.scala | 2 +-
.../daffodil/dsom/TestMiddleEndAttributes.scala | 14 +-
.../org/apache/daffodil/infoset/InfosetImpl.scala | 62 ++-
.../apache/daffodil/processors/RuntimeData.scala | 3 +
.../processors/parsers/ElementCombinator1.scala | 56 --
.../SeparatedSequenceChildParseResultHelper.scala | 20 +-
.../parsers/SeparatedSequenceParsers.scala | 32 +-
.../processors/parsers/SequenceChildBases.scala | 9 +
.../processors/parsers/SequenceParserBases.scala | 32 +-
.../parsers/UnorderedSequenceParser.scala | 168 ------
.../parsers/UnseparatedSequenceParsers.scala | 14 +-
.../unordered_sequences/UnorderedSequences.tdml | 610 ++++++++++-----------
.../TestUnorderedSequencesNew.scala | 57 +-
21 files changed, 617 insertions(+), 638 deletions(-)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index 09d98a7..e2c635a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -541,6 +541,7 @@ trait ElementBase
elementChildren.map { _.elementRuntimeData }
val newERD: ElementRuntimeData = new ElementRuntimeData(
+ position,
childrenERDs,
schemaSet.variableMap,
nextElementResolver,
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 9ed2d58..76a9196 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
@@ -275,7 +275,6 @@ abstract class SequenceGroupTermBase(
}
final def isLayered = maybeLayerTransformerEv.isDefined
-
}
/**
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 8b73566..cf2cd41 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
@@ -282,6 +282,8 @@ trait Term
case Some(_) => enclosingTerm.get.nearestEnclosingUnorderedSequence
}
+ final lazy val isInUnorderedSequence: Boolean = !nearestEnclosingUnorderedSequence.isEmpty
+
final lazy val nearestEnclosingUnorderedSequenceBeforeSequence: Option[SequenceTermBase] = enclosingTerm match {
case None => None
case Some(s: SequenceTermBase) if !s.isOrdered => Some(s)
@@ -564,13 +566,15 @@ trait Term
* terms that could appear before this. The second item in the tuple is a
* One(enclosingParent) if all prior siblings are optional or this element has no prior siblings
*/
- lazy val potentialPriorTerms: (Seq[Term], Option[Term]) = {
+ lazy val potentialPriorTerms: (Seq[Term], Option[Term]) = LV('potentialPriorTerms) {
val et = enclosingTerm
val (potentialPrior, optEnclosingParent) = et match {
case None => (Seq(), None)
case Some(eb: ElementBase) => (Seq(), Some(eb))
case Some(ch: ChoiceTermBase) => (Seq(), Some(ch))
- case Some(sq: SequenceTermBase) if !sq.isOrdered => (sq.groupMembers, Some(sq))
+ case Some(sq: SequenceTermBase) if !sq.isOrdered => {
+ (sq.groupMembers, Some(sq))
+ }
case Some(sq: SequenceTermBase) if sq.isOrdered => {
val previousTerms = sq.groupMembers.takeWhile { _ != this }
if (previousTerms.isEmpty) {
@@ -600,7 +604,7 @@ trait Term
}
}
(potentialPriorRepresented, optEnclosingParent)
- }
+ }.value
/*
* This function returns at list of simple elements that are descendents of
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
index 92d1ebe..d3d1244 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/AlignedMixin.scala
@@ -52,7 +52,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
* will be properly aligned by where the prior thing left us positioned.
* Hence we are guaranteed to be properly aligned.
*/
- final def isKnownToBeAligned: Boolean = LV('isKnownToBeAligned) {
+ final lazy val isKnownToBeAligned: Boolean = LV('isKnownToBeAligned) {
if (!isRepresented) {
true
} else {
@@ -71,7 +71,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
* This goes further TermEncodingMixin.hasTextAlignment because it
* considers the surrounding context meeting the alignment needs.
*/
- final lazy val isKnownToBeTextAligned: Boolean = {
+ final lazy val isKnownToBeTextAligned: Boolean = LV('isKnownToBeTextAligned) {
if (self.encodingInfo.isKnownEncoding) {
if (self.encodingInfo.knownEncodingAlignmentInBits == 1)
true
@@ -83,7 +83,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
true
else
false
- }
+ }.value
final lazy val isDelimiterKnownToBeTextAligned: Boolean = {
if (self.encodingInfo.isKnownEncoding) {
@@ -123,13 +123,13 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
}
}
- private lazy val trailingSkipApprox: LengthApprox = {
+ protected lazy val trailingSkipApprox: LengthApprox = {
LengthExact(trailingSkipInBits)
}
private lazy val unaligned = AlignmentMultipleOf(1)
- private lazy val priorAlignmentApprox: AlignmentMultipleOf = {
+ private lazy val priorAlignmentApprox: AlignmentMultipleOf = LV('priorAlignmentApprox) {
if (this.isInstanceOf[Root] || this.isInstanceOf[QuasiElementDeclBase]) {
AlignmentMultipleOf(0) // root and quasi elements are aligned with anything
} else {
@@ -172,10 +172,21 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
Seq()
}
+ val unorderedSequenceSelfAlignment =
+ if (isInUnorderedSequence) {
+ Seq(alignmentApprox + (elementSpecifiedLengthApprox + trailingSkipApprox))
+ } else {
+ Seq()
+ }
+
val priorSibsAlignmentsApprox = priorSibs.map { ps =>
- val eaa = ps.endingAlignmentApprox
+ val eaa = if (isInUnorderedSequence) {
+ alignmentApprox + (ps.elementSpecifiedLengthApprox + ps.trailingSkipApprox)
+ } else {
+ ps.endingAlignmentApprox
+ }
eaa
- }
+ }.toSeq
val parentAlignmentApprox = optEnclosingParent.map { p =>
val csa = p.contentStartAlignment
csa
@@ -186,7 +197,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
else
priorAlignmentsApprox.reduce(_ * _)
}
- }
+ }.value
private lazy val priorAlignmentWithLeadingSkipApprox: AlignmentMultipleOf = {
priorAlignmentApprox + leadingSkipApprox
@@ -233,7 +244,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
}
}
- private lazy val elementSpecifiedLengthApprox: LengthApprox = {
+ protected lazy val elementSpecifiedLengthApprox: LengthApprox = {
this match {
case eb: ElementBase => {
eb.lengthKind match {
@@ -265,6 +276,7 @@ trait AlignedMixin extends GrammarMixin { self: Term =>
case LengthKind.Prefixed => LengthMultipleOf(1) // NYI
}
}
+ case mg: ModelGroup => Assert.usageError("Only for elements")
}
}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
index 9901baf..2717e7a 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/SequenceGrammarMixin.scala
@@ -22,6 +22,7 @@ import org.apache.daffodil.dsom._
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.grammar.primitives._
import org.apache.daffodil.grammar.primitives.OrderedSequence
+import org.apache.daffodil.grammar.primitives.UnorderedSequence
trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
@@ -34,7 +35,7 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
import columnConstants._
self.sequenceKind match {
case Ordered__ => orderedSequence
- case Unordered => subsetError("Unordered sequences are not supported.") // unorderedSequenceContent
+ case Unordered => unorderedSequence
}
}
@@ -58,6 +59,12 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
res
}
+ private lazy val unorderedSequence = {
+ val alternatives = groupMembers.map { _.termContentBody }
+ val res = new UnorderedSequence(this, seqChildren, alternatives)
+ res
+ }
+
/**
* Constants to make the lookup tables below more readable without using fragile whitespace
*/
@@ -117,9 +124,8 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
separatorSuppressionPolicy
val res = (child, sequenceKind, ssp, ock, min, max) match {
- case (e: EB, Ordered__, ___________, _________, ONE, ONE) => new ScalarOrderedSequenceChild(this, e, groupIndex)
+ case (e: EB, Ordered__, ___________, __________, ONE, ONE) => new ScalarOrderedSequenceChild(this, e, groupIndex)
case (e: EB, _________, ___________, StopValue_, ___, __2) => e.subsetError("dfdl:occursCountKind 'stopValue' is not supported.")
- case (_____, Unordered, ___________, __________, ___, __2) => this.subsetError("Unordered sequences are not supported.")
case (e: EB, Ordered__, ___________, Parsed____, ___, __2) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
case (e: EB, Ordered__, ___________, Fixed_____, ___, UNB) => e.SDE("occursCountKind='fixed' not allowed with unbounded maxOccurs")
case (e: EB, Ordered__, Never______, Implicit__, ___, UNB) if !e.isLastDeclaredRepresentedInSequence => unboundedPositionalError(e)
@@ -135,7 +141,11 @@ trait SequenceGrammarMixin extends GrammarMixin { self: SequenceTermBase =>
case (e: EB, Ordered__, TrailingStr, Implicit__, ___, UNB) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
case (e: EB, Ordered__, TrailingStr, Implicit__, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
case (e: EB, Ordered__, Always_____, Implicit__, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
- case (m: MG, Ordered__, ___________, __________, ___, __2) => new ScalarOrderedSequenceChild(this, m, groupIndex)
+ case (e: EB, Unordered, ___________, __________, ___, ONE) => new ScalarOrderedSequenceChild(this, e, groupIndex)
+ case (e: EB, Unordered, ___________, Parsed____, ___, max) => new RepOrderedWithMinMaxSequenceChild(this, e, groupIndex)
+ case (e: EB, Unordered, ___________, __________, ___, __2) => e.SDE("When sequenceKind='unordered', occursCountKind must be 'parsed'")
+ case (m: MG, Unordered, ___________, __________, ___, __2) => child.SDE("All memebers of an unordered sequence must be Element or ElemenntRef")
+ case (m: MG, _________, ___________, __________, ___, __2) => new ScalarOrderedSequenceChild(this, m, groupIndex)
case (_____, _________, policy /**/ , ock /**/ , ___, __2) => child.SDE("separatorSuppressionPolicy='" + policy + "' not allowed with occursCountKind='" + ock + "'.")
}
res
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
index 0bafdf9..91254b2 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
@@ -23,7 +23,6 @@ import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.grammar.Gram
import org.apache.daffodil.grammar.NamedGram
import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.processors.parsers.ChoiceElementParser
import org.apache.daffodil.processors.parsers.ElementParser
import org.apache.daffodil.processors.parsers.ElementParserNoRep
import org.apache.daffodil.processors.parsers.Parser
@@ -79,17 +78,10 @@ class ElementCombinator(
extends NamedGram(context)
with Padded {
- override def toString = subComb.toString() // parse centric view of the world. Unparser doesn't use subComb at all.
+ override def toString = subComb.toString()
- private lazy val subComb = {
- if (context.isParentUnorderedSequence) {
- new ChoiceElementCombinator(context, eBeforeContent,
- eValue, eAfterValue)
- } else {
- new ElementParseAndUnspecifiedLength(context, eBeforeContent,
- eValue, eAfterValue, repTypeElementGram)
- }
- }
+ private lazy val subComb = new ElementParseAndUnspecifiedLength(context, eBeforeContent,
+ eValue, eAfterValue, repTypeElementGram)
override lazy val parser: Parser = {
//
@@ -340,25 +332,6 @@ class ElementParseAndUnspecifiedLength(context: ElementBase, eBeforeGram: Gram,
}
}
-class ChoiceElementCombinator(context: ElementBase, eGramBefore: Gram, eGram: Gram, eAfterGram: Gram)
- extends ElementCombinatorBase(context, eGramBefore, eGram, eAfterGram, EmptyGram) {
-
- lazy val parser: Parser = new ChoiceElementParser(
- context.erd,
- context.name,
- patDiscrim,
- patAssert,
- pSetVar,
- testDiscrim,
- testAssert,
- eBeforeParser,
- eParser,
- eAfterParser)
-
- lazy val unparser = hasNoUnparser
-
-}
-
abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eGram: Gram, eGramAfter: Gram, repTypeElementGram:Gram)
extends NamedGram(context) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
index d62c56f..abbb239 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
@@ -407,7 +407,7 @@ class ScalarOrderedSequenceChild(sq: SequenceTermBase, term: Term, groupIndex: I
}
res
}
- lazy val sequenceChildUnparser: SequenceChildUnparser = {
+ override lazy val sequenceChildUnparser: SequenceChildUnparser = {
val res =
if (sq.hasSeparator) {
new ScalarOrderedSeparatedSequenceChildUnparser(
@@ -487,7 +487,7 @@ sealed abstract class RepElementSequenceChild(
Assert.usage(!e.isScalar)
- lazy val sequenceChildUnparser: SequenceChildUnparser =
+ override lazy val sequenceChildUnparser: SequenceChildUnparser =
sq.hasSeparator match {
case true => {
new RepOrderedSeparatedSequenceChildUnparser(
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 7d33820..0b84621 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
@@ -18,8 +18,10 @@
package org.apache.daffodil.grammar.primitives
import org.apache.daffodil.grammar.Terminal
+import org.apache.daffodil.grammar.Gram
import org.apache.daffodil.dsom._
import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
import org.apache.daffodil.processors.unparsers._
import org.apache.daffodil.util.Misc
@@ -76,3 +78,80 @@ class OrderedSequence(sq: SequenceTermBase, sequenceChildrenArg: Seq[SequenceChi
}
}
}
+
+class UnorderedSequence(sq: SequenceTermBase, sequenceChildrenArg: Seq[SequenceChild], alternatives: Seq[Gram])
+ extends SequenceCombinator(sq, sequenceChildrenArg) {
+
+ import SeparatedSequenceChildBehavior._
+
+ private lazy val sepGram = sq.sequenceSeparator
+ private lazy val sepParser = sepGram.parser
+ private lazy val sepUnparser = sepGram.unparser
+
+ private lazy val sequenceChildren = sequenceChildrenArg.toVector
+
+
+ private lazy val parsers = alternatives.map(_.parser)
+
+
+ override lazy val parser: Parser = {
+
+ lazy val choiceParser = new ChoiceParser(srd, parsers.toVector)
+
+ sq.hasSeparator match {
+ case true => {
+ lazy val groupHelper = new NonPositionalGroupSeparatedSequenceChildParseResultHelper(
+ srd,
+ NonPositional,
+ true, // Due to the nature of UOSeqs, could potentially be empty
+ false) // and does not have required syntax
+
+ lazy val groupParser = new GroupSeparatedUnorderedSequenceChildParser(
+ choiceParser,
+ srd,
+ srd, // Won't actually be used
+ sepParser,
+ sq.separatorPosition,
+ groupHelper)
+
+ new UnorderedSeparatedSequenceParser(
+ srd, sq.separatorPosition, sepParser,
+ Vector(groupParser))
+ }
+ case false => {
+ lazy val groupHelper = new GroupUnseparatedSequenceChildParseResultHelper(
+ srd,
+ true, // Due to the nature of UOSeqs, could potentially be empty
+ false) // and does not have required syntax
+
+ lazy val groupParser = new ScalarUnorderedUnseparatedSequenceChildParser(
+ choiceParser,
+ srd,
+ srd, // Won't actually be used
+ groupHelper)
+
+ new UnorderedUnseparatedSequenceParser(
+ srd,
+ Vector(groupParser))
+ }
+ }
+ }
+
+ override lazy val unparser: Unparser = {
+ sq.checkHiddenSequenceIsDefaultableOrOVC
+ val childUnparsers = sequenceChildren.flatMap { _.optSequenceChildUnparser }
+ if (childUnparsers.isEmpty) new NadaUnparser(null)
+ else {
+ sq.hasSeparator match {
+ case true => new OrderedSeparatedSequenceUnparser(
+ srd,
+ SeparatorSuppressionPolicy.AnyEmpty, sq.separatorPosition, sepUnparser,
+ childUnparsers)
+ case false =>
+ new OrderedUnseparatedSequenceUnparser(
+ srd,
+ childUnparsers)
+ }
+ }
+ }
+}
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
index b717009..ee0df4e 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestDsomCompiler.scala
@@ -588,7 +588,7 @@ class TestDsomCompiler extends Logging {
</dfdl:defineEscapeScheme>,
<xs:element name="list">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="character" type="xsd:string" maxOccurs="unbounded" dfdl:representation="text" dfdl:separator="," dfdl:terminator="%NL;"/>
<xs:element name="block" type="xsd:string" maxOccurs="unbounded" dfdl:representation="text" dfdl:separator="," dfdl:terminator="%NL;" dfdl:escapeSchemeRef="cStyleComment"/>
</xs:sequence>
diff --git a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestMiddleEndAttributes.scala b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestMiddleEndAttributes.scala
index a26e7c4..b65f8ce 100644
--- a/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestMiddleEndAttributes.scala
+++ b/daffodil-core/src/test/scala/org/apache/daffodil/dsom/TestMiddleEndAttributes.scala
@@ -35,7 +35,7 @@ class TestMiddleEndAttributes {
<dfdl:format representation="text" lengthUnits="bytes" encoding="US-ASCII" initiator="" terminator="" separator="" ignoreCase="no"/>,
<xs:element name="e1" dfdl:lengthKind="implicit">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="s1" type="xs:string" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="s2" type="xs:string" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
</xs:sequence>
@@ -65,7 +65,7 @@ class TestMiddleEndAttributes {
<dfdl:format representation="text" occursCountKind="parsed" lengthUnits="bytes" encoding="US-ASCII" initiator="" terminator="" separator="" ignoreCase="no"/>,
<xs:element name="e1" dfdl:lengthKind="implicit">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="s1" type="xs:string" minOccurs="0" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="s2" type="xs:string" minOccurs="0" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
</xs:sequence>
@@ -95,7 +95,7 @@ class TestMiddleEndAttributes {
<dfdl:format representation="text" occursCountKind="parsed" lengthUnits="bytes" encoding="US-ASCII" initiator="" terminator="" separator="" ignoreCase="no"/>,
<xs:element name="e1" dfdl:lengthKind="implicit">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="s1" type="xs:string" minOccurs="0" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="s2" type="xs:string" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="s3" type="xs:string" minOccurs="0" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
@@ -138,7 +138,7 @@ class TestMiddleEndAttributes {
<dfdl:format representation="text" occursCountKind="parsed" lengthUnits="bytes" encoding="US-ASCII" initiator="" terminator="" separator="" ignoreCase="no"/>,
<xs:element name="e1" dfdl:lengthKind="implicit">
<xs:complexType>
- <xs:sequence dfdl:separator="," dfdl:separatorPosition="infix">
+ <xs:sequence dfdl:sequenceKind="ordered" dfdl:separator="," dfdl:separatorPosition="infix">
<xs:choice>
<xs:element name="s1" type="xs:int" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="s2" type="xs:string" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
@@ -180,7 +180,7 @@ class TestMiddleEndAttributes {
<xs:element name="e1" dfdl:lengthKind="explicit" dfdl:length="{ 1 }"/>
<xs:element name="e2" dfdl:lengthKind="implicit">
<xs:complexType>
- <xs:sequence dfdl:separator="," dfdl:separatorPosition="infix">
+ <xs:sequence dfdl:sequenceKind="ordered" dfdl:separator="," dfdl:separatorPosition="infix">
<xs:element ref="e1"/>
</xs:sequence>
</xs:complexType>
@@ -214,7 +214,7 @@ class TestMiddleEndAttributes {
<xs:element name="doc">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="msg" type="ex:msgType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
@@ -227,7 +227,7 @@ class TestMiddleEndAttributes {
</xs:complexType>
<xs:element name="fWithInitiator" dfdl:initiator="$">
<xs:complexType>
- <xs:sequence>
+ <xs:sequence dfdl:sequenceKind="ordered">
<xs:element name="f" type="xs:string"/>
</xs:sequence>
</xs:complexType>
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 4b2b6e1..eacbe2b 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
@@ -207,6 +207,9 @@ case class InfosetContentLengthUnknownException(lengthState: LengthState, overri
case class InfosetValueLengthUnknownException(lengthState: LengthState, override val diElement: DIElement, override val erd: ElementRuntimeData)
extends InfosetLengthUnknownException(lengthState, "Value", diElement, erd)
+case class InfosetMultipleScalarError(val erd: ElementRuntimeData)
+ extends ProcessingError("Scalar Element", Nope, Nope, "Multiple instances detected for scalar element %s", erd.namedQName)
+
/**
* Used to determine if expressions can be evaluated without any nodes.
* They all save/restore the current node, so this is the placeholder
@@ -886,7 +889,6 @@ sealed trait DIElement
private var _array: Maybe[InfosetArray] = Nope
override def array = _array
override def setArray(a: InfosetArray) = {
- Assert.invariant(_array == Nope)
_array = One(a)
}
@@ -1004,6 +1006,14 @@ final class DIArray(
ie.setArray(this)
}
+ def concat(array: DIArray) = {
+ val newContents = array.contents
+ newContents.foreach( ie => {
+ ie.asInstanceOf[InfosetElement].setArray(this)
+ append(ie.asInstanceOf[InfosetElement])
+ })
+ }
+
final def length: Long = _contents.length
final def maybeMostRecentlyAddedChild(): Maybe[DIElement] = {
@@ -1431,6 +1441,56 @@ sealed class DIComplex(override val erd: ElementRuntimeData, val tunable: Daffod
}
}
+ /*
+ * When parsing unordered sequences it is possible to have non-contiguous arrays.
+ * When parsed, these arrays show up as separate DIArrays in the infoset. We need
+ * to combine these separate arrays and sort the child nodes into schema definition
+ * order.
+ * */
+ final def flattenAndValidateChildNodes(pstate: ParseOrUnparseState, start: Int): Unit = {
+ val (ordered, unordered) = childNodes.splitAt(start)
+ childNodes.clear()
+ childNodes ++= ordered
+ val groups = unordered.groupBy(_.erd)
+ unordered.clear()
+ groups foreach {
+ case (erd, nodes) => {
+ // Check min/maxOccurs validity while iterating over childNodes
+ val min = erd.minOccurs
+ val max = erd.maxOccurs
+ val isUnbounded = max == -1
+
+ // Flatten multiple DIArrays into the first one
+ if (erd.isArray) {
+ val a = nodes(0).asInstanceOf[DIArray]
+ nodes.tail.foreach( b => a.concat(b.asInstanceOf[DIArray]))
+ nodes.reduceToSize(1)
+
+ // Need to also remove duplicates from fastLookup
+ val fastSeq = nameToChildNodeLookup.get(a.namedQName)
+ if (fastSeq != null)
+ fastSeq.reduceToSize(1)
+
+ // Validate min/maxOccurs for array
+ val occurrence = nodes(0).contents.length
+ if (isUnbounded && occurrence < min)
+ pstate.validationError("Element %s failed check of minOccurs='%s' and maxOccurs='unbounded', actual number of occurrences: %s", erd.namedQName, min, occurrence)
+ else if (!isUnbounded && (occurrence < min || occurrence > max))
+ pstate.validationError("Element %s failed check of minOccurs='%s' and maxOccurs='%s', actual number of occurrences: %s", erd.namedQName, min, max, occurrence)
+
+ } else {
+ if (nodes.length > 1) {
+ val diag = new InfosetMultipleScalarError(erd)
+ pstate.setFailed(diag)
+ }
+ }
+
+ unordered ++= nodes
+ }
+ }
+ childNodes ++= unordered.sortBy(_.erd.position)
+ }
+
override def addChild(e: InfosetElement): Unit = {
if (!e.isHidden && !hasVisibleChildren) hasVisibleChildren = true
if (e.runtimeData.isArray) {
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 080681f..90cb6b5 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
@@ -603,6 +603,7 @@ final class ElementRuntimeData(
* all transient elements must be added to the preSerialization method below
* to allow parser serialization/deserialization to work.
*/
+ @TransientParam positionArg: => Int,
@TransientParam childrenArg: => Seq[ElementRuntimeData],
@TransientParam variableMapArg: => VariableMap,
@TransientParam nextElementResolverArg: => NextElementResolver,
@@ -664,6 +665,7 @@ final class ElementRuntimeData(
override def isRequiredScalar = !isArray && isRequiredOrOptional
+ lazy val position = positionArg
lazy val children = childrenArg
lazy val variableMap = variableMapArg
lazy val nextElementResolver = nextElementResolverArg
@@ -701,6 +703,7 @@ final class ElementRuntimeData(
override def preSerialization: Unit = {
super.preSerialization
+ position
children
variableMap
nextElementResolver
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 af0e39c..4eba42d 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
@@ -323,59 +323,3 @@ class ElementParserNoRep(
state.mpstate.moveOverOneElementChildOnly
}
}
-
-class ChoiceElementParser(
- erd: ElementRuntimeData,
- name: String,
- patDiscrim: Maybe[Parser],
- patAssert: Array[Parser],
- setVar: Array[Parser],
- testDiscrim: Maybe[Parser],
- testAssert: Array[Parser],
- eBeforeParser: Maybe[Parser],
- eParser: Maybe[Parser],
- eAfterParser: Maybe[Parser])
- extends ElementParserBase(
- erd,
- name,
- patDiscrim,
- patAssert,
- setVar,
- testDiscrim,
- testAssert,
- eBeforeParser,
- eParser,
- eAfterParser,
- Maybe.Nope
- ) {
-
- def move(state: PState) = {}
-
- /**
- * ElementBegin just adds the element we are constructing to the infoset and changes
- * the state to be referring to this new element as what we're parsing data into.
- */
- def parseBegin(pstate: PState): Unit = {
- val currentElement = Infoset.newElement(erd, pstate.tunable)
- log(LogLevel.Debug, "currentElement = %s", currentElement)
- }
-
- // We don't want to modify the state here except
- // for validation.
- def parseEnd(pstate: PState): Unit = {
- val currentElement = pstate.thisElement
-
- val shouldValidate =
- (pstate.dataProc.isDefined) && pstate.dataProc.value.getValidationMode != ValidationMode.Off
- if (shouldValidate && erd.isSimpleType) {
- // Execute checkConstraints
- validate(pstate)
- }
-
- val priorElement = currentElement.parent
- // Note: interaction of unboxed Maybe[T] with pass by name args of log method
- // require us to call toScalaOption here.
- log(LogLevel.Debug, "priorElement = %s", Maybe.WithNulls.toScalaOption(priorElement))
- move(pstate)
- }
-}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
index 3e7a0ac..b1fc8ff 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
@@ -312,10 +312,22 @@ class NonPositionalGroupSeparatedSequenceChildParseResultHelper(
isZL: Boolean,
mgrd: ModelGroupRuntimeData,
requiredOptional: RequiredOptionalStatus): ParseAttemptStatus = {
- if (isZL)
- ParseAttemptStatus.MissingItem // it is an error if ZL in NonPositional
- else
- ParseAttemptStatus.NormalRep
+ if (pstate.isSuccess) {
+ val maybeElem = pstate.infoset.asComplex.maybeMostRecentlyAddedChild()
+ Assert.invariant(maybeElem.isDefined)
+ val elem = maybeElem.get
+ val maybeIsNilled = elem.maybeIsNilled // can't just call isNilled because that throws exceptions on not defined
+ if (maybeIsNilled.isDefined && maybeIsNilled.get) {
+ ParseAttemptStatus.NilRep
+ } else {
+ ParseAttemptStatus.NormalRep
+ }
+ } else {
+ if (isZL)
+ ParseAttemptStatus.MissingItem // it is an error if ZL in NonPositional
+ else
+ ParseAttemptStatus.NormalRep
+ }
}
}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala
index 288dc07..8b5c575 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SeparatedSequenceParsers.scala
@@ -65,6 +65,17 @@ sealed abstract class ScalarOrderedSeparatedSequenceChildParser(
with Separated
with NonRepeatingSequenceChildParser
+sealed abstract class ScalarUnorderedSeparatedSequenceChildParser(
+ childParser: Parser,
+ srd: SequenceRuntimeData,
+ trd: TermRuntimeData,
+ override val sep: Parser,
+ override val spos: SeparatorPosition,
+ override val parseResultHelper: SeparatedSequenceChildParseResultHelper)
+ extends SequenceChildParser(childParser, srd, trd)
+ with Separated
+ with NonRepeatingUnorderedSequenceChildParser
+
final class ScalarOrderedElementSeparatedSequenceChildParser(
childParser: Parser,
srd: SequenceRuntimeData,
@@ -83,6 +94,15 @@ final class GroupSeparatedSequenceChildParser(
prh: SeparatedSequenceChildParseResultHelper)
extends ScalarOrderedSeparatedSequenceChildParser(childParser, srd, mrd, sep, spos, prh)
+final class GroupSeparatedUnorderedSequenceChildParser(
+ childParser: Parser,
+ srd: SequenceRuntimeData,
+ val mrd: ModelGroupRuntimeData,
+ sep: Parser,
+ spos: SeparatorPosition,
+ prh: SeparatedSequenceChildParseResultHelper)
+ extends ScalarUnorderedSeparatedSequenceChildParser(childParser, srd, mrd, sep, spos, prh)
+
final class RepOrderedExactlyNSeparatedSequenceChildParser(
childParser: Parser,
srd: SequenceRuntimeData,
@@ -119,7 +139,17 @@ final class OrderedSeparatedSequenceParser(
spos: SeparatorPosition,
sep: Parser,
childrenArg: Vector[SequenceChildParser])
- extends OrderedSequenceParserBase(rd, childrenArg) {
+ extends SequenceParserBase(rd, childrenArg) {
override lazy val childProcessors = (sep +: childrenArg.asInstanceOf[Seq[Parser]]).toVector
}
+
+final class UnorderedSeparatedSequenceParser(
+ rd: SequenceRuntimeData,
+ spos: SeparatorPosition,
+ sep: Parser,
+ choiceParser: Vector[SequenceChildParser])
+ extends SequenceParserBase(rd, choiceParser, false) {
+
+ override lazy val childProcessors = sep +: choiceParser
+}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala
index 610f0c1..bea2c67 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceChildBases.scala
@@ -223,6 +223,15 @@ trait NonRepeatingSequenceChildParser { self: SequenceChildParser =>
}
+trait NonRepeatingUnorderedSequenceChildParser { self: SequenceChildParser =>
+
+ def pouStatus: PoUStatus = PoUStatus.HasPoU
+
+ def maybeStaticRequiredOptionalStatus: Maybe[RequiredOptionalStatus] =
+ Maybe(RequiredOptionalStatus.Optional)
+
+}
+
/**
* For computed elements, and for groups (which commonly will be sequences)
* which contain only other non-represented entities, or executable
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
index 2b360f5..7cb6d92 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/SequenceParserBases.scala
@@ -16,12 +16,18 @@
*/
package org.apache.daffodil.processors.parsers
+import scala.collection.mutable.ArrayBuffer
+
import org.apache.daffodil.processors.Evaluatable
-import java.io.PrintWriter
import org.apache.daffodil.exceptions.UnsuppressableException
+import java.io.PrintWriter
import java.io.StringWriter
+import java.util.Comparator
+import java.util.Arrays
import org.apache.daffodil.dsom.SchemaDefinitionDiagnosticBase
import org.apache.daffodil.dsom.TunableLimitExceededError
+import org.apache.daffodil.infoset.DIComplex
+import org.apache.daffodil.infoset.DIArray
import org.apache.daffodil.exceptions.Assert
import org.apache.daffodil.processors.Success
import org.apache.daffodil.processors.SequenceRuntimeData
@@ -36,18 +42,13 @@ import org.apache.daffodil.processors.ModelGroupRuntimeData
*/
abstract class SequenceParserBase(
srd: SequenceRuntimeData,
- protected val childParsers: Vector[Parser])
+ childParsers: Vector[Parser],
+ isOrdered: Boolean = true)
extends CombinatorParser(srd) {
override def nom = "Sequence"
override lazy val runtimeDependencies: Vector[Evaluatable[AnyRef]] = Vector()
override lazy val childProcessors = childParsers
-}
-
-abstract class OrderedSequenceParserBase(
- srd: SequenceRuntimeData,
- childParsersArg: Vector[Parser])
- extends SequenceParserBase(srd, childParsersArg) {
import ParseAttemptStatus._
import ArrayIndexStatus._
@@ -86,6 +87,8 @@ abstract class OrderedSequenceParserBase(
var resultOfTry: ParseAttemptStatus = ParseAttemptStatus.Uninitialized
+ val infosetIndexStart = pstate.infoset.asInstanceOf[DIComplex].childNodes.size
+
/**
* On exit from the sequence loop, if the last thing was Missing, we
* want to look back one prior to see if that followed a EmptyRep or AbsentRep,
@@ -224,12 +227,23 @@ abstract class OrderedSequenceParserBase(
pstate.setSuccess()
isDone = true
}
+ case (MissingItem | MissingSeparator | FailureUnspecified) if (!isOrdered) => {
+ // We have hit the end of an unordered sequence, mask the failure and exit
+ // the sequence succesfully.
+ pstate.setSuccess()
+ isDone = true
+ }
case _ => // ok.
}
pstate.mpstate.moveOverOneGroupIndexOnly()
} // end case scalarParser
} // end match case parser
- scpIndex += 1
+ if (isOrdered)
+ scpIndex += 1
+ else if (isDone) {
+ val infoset = pstate.infoset.asInstanceOf[DIComplex]
+ infoset.flattenAndValidateChildNodes(pstate, infosetIndexStart)
+ }
} // end while for each sequence child parser
if (child ne null) child.finalChecks(pstate, resultOfTry, priorResultOfTry)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnorderedSequenceParser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnorderedSequenceParser.scala
deleted file mode 100644
index 0a666a6..0000000
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnorderedSequenceParser.scala
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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
-
-class UnorderedSequenceParser(
- override val context: ModelGroupRuntimeData,
- sortOrder: Seq[(String, org.jdom2.Namespace)],
- scalarMembers: Seq[(String, String, org.jdom2.Namespace)],
- uoSeqParser: Parser)
- extends CombinatorParser(context) {
-
- override lazy val runtimeDependencies = Vector()
-
- override def nom = "UnorderedSequence"
- override lazy val childProcessors = Vector(uoSeqParser)
-
- // def sort(elt: org.jdom2.Element, pstate: PState): Unit = {
- // val childrenDetached = elt.removeContent().toList.asInstanceOf[List[org.jdom2.Element]]
- //
- // println("Children Detached: " + childrenDetached)
- //
- // println("Sort Order: " + sortOrder)
- // sortOrder.foreach {
- // case (name, ns) => {
- //
- // val newContent = childrenDetached.filter(child => {
- // val infoSetElem = Infoset.newElement(child)
- // val rd = infoSetElem.schemaComponent
- // val isMatch = rd.name == name && rd.targetNamespace == ns
- // isMatch
- // })
- //
- // println("New Content: " + newContent)
- // if (newContent.size > 0)
- // elt.addContent(newContent)
- // }
- // }
- // }
- //
- // def checkScalarsOccurExactlyOnce(elt: org.jdom2.Element, pstate: PState): Unit = {
- // // Always occurs, does not depend on validation
- // val children = elt.getChildren().toList.asInstanceOf[List[org.jdom2.Element]]
- // scalarMembers.foreach {
- // case (name, path, ns) => {
- // val scalarChildren = children.filter(e => {
- // e.getName() == name && e.getNamespace() == ns
- // })
- // val numScalarChildren = scalarChildren.length
- // if (numScalarChildren > 1 || numScalarChildren == 0)
- // pstate.SDE("%s is scalar but occurred %s times.\nPath: %s\nOffending children: %s",
- // name, scalarChildren.length, path, scalarChildren.mkString(", "))
- // }
- // }
- // }
- //
- // /**
- // * We want to check that we met he expected occurrence values
- // * but we don't want to SDE, instead we issue a PE (ProcessingError).
- // */
- // def checkOccurrence(elt: org.jdom2.Element): Unit = {
- // val childrenList = elt.getContent().toList.asInstanceOf[List[org.jdom2.Element]]
- //
- // val erds =
- // context.groupMembers.collect { case erd: ElementRuntimeData => erd }
- // erds.foreach(erd => {
- // val minOccurs = erd.minOccurs
- // val maxOccurs = erd.maxOccurs
- // val ns = erd.targetNamespace
- // val name = erd.name
- //
- // val children = childrenList.filter(c => {
- // val childName = c.getName()
- // val childNS = c.getNamespace()
- // name == childName && ns == childNS
- // })
- //
- // val numChildren = children.length
- //
- // minOccurs.foreach { minOccurs =>
- // if (numChildren < minOccurs) {
- // PE("UnorderedSequence.checkOccurrence - %s failed minOccurs check. Expected at least %s but found %s.",
- // erd, minOccurs, numChildren)
- // }
- // }
- // maxOccurs.foreach { maxOccurs =>
- // if (numChildren > maxOccurs) {
- // PE("UnorderedSequence.checkOccurrence - %s failed maxOccurs check. Expected at most %s but found %s.",
- // erd, maxOccurs, numChildren)
- // }
- // }
- // })
- // }
- //
- // def dropDefaulted(elt: org.jdom2.Element, pstate: PState): Unit = {
- // // Always occurs, does not depend on validation
- //
- // // RequiredElement, index in its array <= minOccurs
- // // If empty rep, a required element that has a default value will be defaulted.
- //
- // // Drop anything after the minOccurs that was defaulted.
- //
- // // So we need the original minOccurs for each element.
- // val childrenDetached = elt.removeContent().toList.asInstanceOf[List[org.jdom2.Element]]
- // val erds = childrenDetached.map(c => {
- // val infoSetElem = Infoset.newElement(c)
- // val rd = infoSetElem.schemaComponent
- // rd
- // }).distinct
- //
- // erds.foreach(erd => {
- // val minOccurs = erd.minOccurs.get
- // val ns = erd.targetNamespace
- // val name = erd.name
- //
- // val children = childrenDetached.filter(c => {
- // val childName = c.getName()
- // val childNS = c.getNamespace()
- // name == childName && ns == childNS
- // })
- //
- // val numChildren = children.length
- //
- // if (numChildren >= minOccurs) {
- // val firstChild = children.head
- // val restOfChildren = children.tail
- // val restOfNonDefaultedChildren = restOfChildren.filterNot(c => c.getAttribute("defaulted", XMLUtils.INT_NS_OBJECT).getBooleanValue())
- // val newContent = firstChild :: restOfNonDefaultedChildren
- // if (newContent.length > 0)
- // elt.addContent(newContent)
- // } else {
- // // Nothing to do here, reattach children.
- // elt.addContent(childrenDetached)
- // }
- // })
- // }
-
- override def parse(start: PState): Unit = {
- ???
- // val end = uoSeqParser.parse1(start)
- // val currentElemAfter = end.parentElement.jdomElt.get
-
- // checkScalarsOccurExactlyOnce(currentElemAfter, end)
- // dropDefaulted(currentElemAfter, end)
- // checkOccurrence(currentElemAfter)
- //
- // // Sort so that the contents are in the expected order.
- // sort(currentElemAfter, end)
-
- // end
- }
-}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala
index f4f8102..9a5f153 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/UnseparatedSequenceParsers.scala
@@ -45,6 +45,15 @@ class ScalarOrderedUnseparatedSequenceChildParser(
with Unseparated
with NonRepeatingSequenceChildParser
+class ScalarUnorderedUnseparatedSequenceChildParser(
+ override val childParser: Parser,
+ override val srd: SequenceRuntimeData,
+ override val trd: TermRuntimeData,
+ override val parseResultHelper: UnseparatedSequenceChildParseResultHelper)
+ extends SequenceChildParser(childParser, srd, trd)
+ with Unseparated
+ with NonRepeatingUnorderedSequenceChildParser
+
class RepOrderedExactlyNUnseparatedSequenceChildParser(
childParser: Parser,
srd: SequenceRuntimeData,
@@ -72,4 +81,7 @@ class RepOrderedWithMinMaxUnseparatedSequenceChildParser(
with Unseparated
class OrderedUnseparatedSequenceParser(rd: SequenceRuntimeData, childParsersArg: Vector[SequenceChildParser])
- extends OrderedSequenceParserBase(rd, childParsersArg)
+ extends SequenceParserBase(rd, childParsersArg)
+
+class UnorderedUnseparatedSequenceParser(rd: SequenceRuntimeData, choiceParser: Vector[SequenceChildParser])
+ extends SequenceParserBase(rd, choiceParser, false)
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
index d78931a..cdd6c65 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section14/unordered_sequences/UnorderedSequences.tdml
@@ -18,12 +18,13 @@
<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:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://example.com"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions">
<tdml:defineSchema name="simple">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="implicit" />
+ lengthKind="implicit" occursCountKind="parsed" />
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="unordered">
@@ -71,7 +72,6 @@
</tdml:defineSchema>
<tdml:parserTestCase name="test_simple" model="simple"
- description="Section 14 Sequence group with left over data - DFDL-14-001R"
root="USG_01">
<tdml:document><![CDATA[veba00]]></tdml:document>
<tdml:infoset>
@@ -86,26 +86,25 @@
</tdml:parserTestCase>
<tdml:parserTestCase name="test_simple_fail_scalar"
- model="simple" description="Section 14 Sequence group with left over data - DFDL-14-001R"
- root="USG_01">
+ model="simple" root="USG_01" validation="limited">
<tdml:document><![CDATA[verybadf00d222]]></tdml:document>
- <tdml:errors>
- <tdml:error>e1</tdml:error>
- <tdml:error>is scalar but occurred 2 times</tdml:error>
- </tdml:errors>
+ <tdml:errors>
+ <tdml:error>Scalar Element Error</tdml:error>
+ <tdml:error>Multiple instances detected for scalar element</tdml:error>
+ </tdml:errors>
</tdml:parserTestCase>
<tdml:defineSchema name="simple_min_max_occurs">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="implicit" />
+ lengthKind="implicit" occursCountKind="parsed" />
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="unordered">
<xs:element name="e1" type="ex:stNumStr"
dfdl:lengthKind="explicit" dfdl:length="2" minOccurs="1"
- maxOccurs="2" dfdl:occursCountKind="parsed">
+ maxOccurs="2">
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
<dfdl:assert test="{ dfdl:checkConstraints(.) }"
@@ -147,8 +146,7 @@
</tdml:defineSchema>
<tdml:parserTestCase name="test_simple_min_max_occurs"
- model="simple_min_max_occurs" description="Section 14 Sequence group with left over data - DFDL-14-001R"
- root="USG_01" validation="on">
+ model="simple_min_max_occurs" root="USG_01" validation="on">
<tdml:document><![CDATA[veba0022]]></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
@@ -163,18 +161,106 @@
</tdml:parserTestCase>
<tdml:parserTestCase name="test_simple_min_max_occurs_fail"
- model="simple_min_max_occurs" description="Section 14 Sequence group with left over data - DFDL-14-001R"
- root="USG_01" validation="on">
- <tdml:document><![CDATA[verybadf00d222]]></tdml:document>
- <tdml:errors>
- <tdml:error>e2 is scalar but occurred 3 times</tdml:error>
- </tdml:errors>
+ model="simple_min_max_occurs" root="USG_01" validation="limited" roundTrip="false">
+ <tdml:document><![CDATA[ve00ba2233]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <USG_01>
+ <e1>00</e1>
+ <e1>22</e1>
+ <e1>33</e1>
+ <e2>ba</e2>
+ <e3>ve</e3>
+ </USG_01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ <tdml:validationErrors>
+ <tdml:error>Element ex:e1 failed check</tdml:error>
+ </tdml:validationErrors>
+ </tdml:parserTestCase>
+
+ <tdml:defineSchema name="array_reference">
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
+ lengthKind="implicit" occursCountKind="parsed" />
+ <xs:element name="USG_01">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="uoseq">
+ <xs:complexType>
+ <xs:sequence dfdl:sequenceKind="unordered">
+
+ <xs:element name="e1" type="ex:stNumStr"
+ dfdl:lengthKind="explicit" dfdl:length="2" minOccurs="1"
+ maxOccurs="2">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert test="{ dfdl:checkConstraints(.) }"
+ message="Assertion failed for dfdl:checkConstraints(.)" />
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="e2" type="ex:stHexStr"
+ dfdl:lengthKind="explicit" dfdl:length="2">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert test="{ dfdl:checkConstraints(.) }"
+ message="Assertion failed for dfdl:checkConstraints(.)" />
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="e3" type="xs:string" dfdl:lengthKind="explicit"
+ dfdl:length="2">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert test="{ dfdl:checkConstraints(.) }"
+ message="Assertion failed for dfdl:checkConstraints(.)" />
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="testRef" type="ex:stNumStr"
+ dfdl:lengthKind="explicit" dfdl:length="2"
+ dfdl:inputValueCalc="{ ../ex:uoseq/ex:e1[2] }" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:simpleType name="stHexStr">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[a-fA-F0-9]+"></xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="stNumStr">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]+"></xs:pattern>
+ </xs:restriction>
+ </xs:simpleType>
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="test_array_reference"
+ model="array_reference" root="USG_01" validation="on">
+ <tdml:document><![CDATA[ve00ba22]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <USG_01>
+ <uoseq>
+ <e1>00</e1>
+ <e1>22</e1>
+ <e2>ba</e2>
+ <e3>ve</e3>
+ </uoseq>
+ <testRef>22</testRef>
+ </USG_01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
</tdml:parserTestCase>
<tdml:defineSchema name="simple_delimited">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="delimited" />
+ lengthKind="delimited" occursCountKind="parsed" />
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="unordered"
@@ -198,8 +284,7 @@
</tdml:defineSchema>
<tdml:parserTestCase name="test_simple_delimited"
- model="simple_delimited" description="Section 14 Sequence group with left over data - DFDL-14-001R"
- root="USG_01">
+ model="simple_delimited" root="USG_01">
<tdml:document><![CDATA[b2,a1,c3]]></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
@@ -215,7 +300,7 @@
<tdml:defineSchema name="simple_nil">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="implicit" nilValueDelimiterPolicy="none"/>
+ lengthKind="implicit" nilValueDelimiterPolicy="none" occursCountKind="parsed"/>
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="unordered"
@@ -239,8 +324,7 @@
</tdml:defineSchema>
<tdml:parserTestCase name="test_simple_nil"
- model="simple_nil" description="Section 14 Sequence group with left over data - DFDL-14-001R"
- root="USG_01">
+ model="simple_nil" root="USG_01">
<tdml:document><![CDATA[b2,,c3]]></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
@@ -251,13 +335,54 @@
</USG_01>
</tdml:dfdlInfoset>
</tdml:infoset>
+ </tdml:parserTestCase>
+
+
+ <tdml:defineSchema name="simple_optional">
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
+ lengthKind="implicit" nilValueDelimiterPolicy="none" occursCountKind="parsed"/>
+ <xs:element name="USG_01">
+ <xs:complexType>
+ <xs:sequence dfdl:sequenceKind="unordered"
+ dfdl:separator=",">
+
+ <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="a" minOccurs="0">
+ </xs:element>
+
+ <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="b">
+ </xs:element>
+
+ <xs:element name="e3" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="c">
+ </xs:element>
+
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="test_simple_optional_elem"
+ model="simple_optional" description="Verify that optional elements are handled correctly in unordered sequences"
+ root="USG_01">
+ <tdml:document><![CDATA[b2,c3]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <USG_01>
+ <e2>2</e2>
+ <e3>3</e3>
+ </USG_01>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
</tdml:parserTestCase>
<tdml:defineSchema name="simple_invalid_path_to_branch">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="delimited" />
+ lengthKind="delimited" occursCountKind="parsed" />
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="unordered"
@@ -315,10 +440,7 @@
<tdml:document><![CDATA[b2,a1,a4,c3,ruh-oh!]]></tdml:document>
<tdml:errors>
<tdml:error>Schema Definition Error</tdml:error>
- <tdml:error>Expression</tdml:error>
- <tdml:error>../e3</tdml:error>
- <tdml:error>navigates to another branch</tdml:error>
- <tdml:error>e3</tdml:error>
+ <tdml:error>No element corresponding</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
@@ -337,7 +459,7 @@
<tdml:defineSchema name="nested_paths">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="delimited" />
+ lengthKind="delimited" occursCountKind="parsed" />
<xs:element name="USG_01">
<xs:complexType>
<xs:sequence dfdl:sequenceKind="ordered" dfdl:separator=",">
@@ -345,99 +467,21 @@
<xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
dfdl:initiator="a" />
- <xs:element name="uoSeq" dfdl:lengthKind="implicit"
- dfdl:initiator="b">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=":">
- <xs:element name="uoMember1" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="x" />
- <xs:element name="uoMember2" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="y" />
- <xs:element name="uoMember3" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="z">
- <xs:annotation>
- <xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ ../../e1 }" message="Assertion failed for ../../e1" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="c" />
-
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="USG_02">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="ordered" dfdl:separator=",">
-
- <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="a" />
-
- <xs:element name="uoSeq" dfdl:lengthKind="implicit"
- dfdl:initiator="b">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=":">
- <xs:element name="uoMember1" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="x" />
- <xs:element name="uoMember2" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="y" />
- <xs:element name="uoMember3" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="z">
- <xs:annotation>
- <xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ ../uoMember1 }"
- message="Assertion failed for ../uoMember1" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="c" />
-
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="USG_03">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=",">
-
- <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="a" />
-
- <xs:element name="uoSeq" dfdl:lengthKind="implicit"
- dfdl:initiator="b">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=":">
- <xs:element name="uoMember1" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="x" />
- <xs:element name="uoMember2" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="y" />
- <xs:element name="uoMember3" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="z">
- <xs:annotation>
- <xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ ../../e1 eq 1 }"
- message="Assertion failed for xs:int(../../e1) eq 1" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
+ <xs:sequence dfdl:sequenceKind="unordered"
+ dfdl:separator=":">
+ <xs:element name="uoMember1" type="xs:int"
+ dfdl:lengthKind="delimited" dfdl:initiator="x" />
+ <xs:element name="uoMember2" type="xs:int"
+ dfdl:lengthKind="delimited" dfdl:initiator="y" />
+ <xs:element name="uoMember3" type="xs:int"
+ dfdl:lengthKind="delimited" dfdl:initiator="z">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:assert test="{ ../ex:e1 }" message="Assertion failed for ../ex:e1" />
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
<xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
dfdl:initiator="c" />
@@ -446,49 +490,6 @@
</xs:complexType>
</xs:element>
- <xs:element name="USG_04">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="ordered" dfdl:separator=",">
-
- <xs:element name="choice" dfdl:lengthKind="implicit"
- minOccurs="1" maxOccurs="unbounded">
- <xs:complexType>
- <xs:choice dfdl:choiceLengthKind="implicit">
- <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="a" />
-
- <xs:element name="uoSeq" dfdl:lengthKind="implicit"
- dfdl:initiator="b">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=":">
- <xs:element name="uoMember1" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="x" />
- <xs:element name="uoMember2" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="y" />
- <xs:element name="uoMember3" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="z">
- <xs:annotation>
- <xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ ../../../choice[1]/e1 eq 1 }"
- message="Assertion failed for xs:int(../../../choice[1]/e1) eq 1" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="c" />
- </xs:choice>
- </xs:complexType>
- </xs:element>
-
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
<!-- Test multiple valid paths in single expression -->
<xs:element name="USG_05">
<xs:complexType>
@@ -513,8 +514,8 @@
dfdl:lengthKind="delimited" dfdl:initiator="z">
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ (../../e1 * ../../e2) eq 2 }"
- message="Assertion failed for ../../e1" />
+ <dfdl:assert test="{ (../../ex:e1 * ../../ex:e2) eq 2 }"
+ message="Assertion failed for ../../ex:e1" />
</xs:appinfo>
</xs:annotation>
</xs:element>
@@ -550,58 +551,8 @@
dfdl:lengthKind="delimited" dfdl:initiator="z">
<xs:annotation>
<xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ (../uoMember1[1] * ../uoMember2[1]) eq 2 }"
- message="Assertion failed for (../uoMember1 * ../uoMember2) eq 2" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <!-- Testing that the wildcard character in DFDLExpression works and that
- we can successfully retrieve and test the nodeset to see if it navigates
- to an invalid location -->
- <xs:element name="USG_07">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="ordered" dfdl:separator=",">
-
- <xs:element name="e1" dfdl:lengthKind="implicit"
- dfdl:initiator="a">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="c1" type="xs:int" dfdl:lengthKind="explicit"
- dfdl:lengthUnits="characters" dfdl:length="1" />
- <xs:element name="c2" type="xs:int" dfdl:lengthKind="explicit"
- dfdl:lengthUnits="characters" dfdl:length="1" />
- <xs:element name="c3" type="xs:int" dfdl:lengthKind="explicit"
- dfdl:lengthUnits="characters" dfdl:length="1" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
- dfdl:initiator="b" />
-
- <xs:element name="uoSeq" dfdl:lengthKind="implicit"
- dfdl:initiator="c">
- <xs:complexType>
- <xs:sequence dfdl:sequenceKind="unordered"
- dfdl:separator=":">
- <xs:element name="uoMember1" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="x" />
- <xs:element name="uoMember2" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="y" />
- <xs:element name="uoMember3" type="xs:int"
- dfdl:lengthKind="delimited" dfdl:initiator="z">
- <xs:annotation>
- <xs:appinfo source="http://www.ogf.org/dfdl/">
- <dfdl:assert test="{ fn:count( ../../e1 ) eq 3 }"
- message="Assertion failed for fn:count( ../../e1 ) eq 3" />
+ <dfdl:assert test="{ (../ex:uoMember1[1] * ../ex:uoMember2[1]) eq 2 }"
+ message="Assertion failed for (../ex:uoMember1 * ../ex:uoMember2) eq 2" />
</xs:appinfo>
</xs:annotation>
</xs:element>
@@ -619,16 +570,14 @@
model="nested_paths"
description="navigate from unordered branch to an element of an enclosing ordered sequence"
root="USG_01">
- <tdml:document><![CDATA[a1,bz10:x20:y99,c55]]></tdml:document>
+ <tdml:document><![CDATA[a1,z10:y77:x20,c55]]></tdml:document>
<tdml:infoset>
<tdml:dfdlInfoset>
<USG_01>
<e1>1</e1>
- <uoSeq>
<uoMember1>20</uoMember1>
- <uoMember2>99</uoMember2>
+ <uoMember2>77</uoMember2>
<uoMember3>10</uoMember3>
- </uoSeq>
<e2>55</e2>
</USG_01>
</tdml:dfdlInfoset>
@@ -664,96 +613,15 @@
root="USG_06">
<tdml:document><![CDATA[a1,b2,cy99:x20:z10]]></tdml:document>
<tdml:errors>
- <tdml:error>Expression</tdml:error>
- <tdml:error>(../uoMember1[1] * ../uoMember2[1]) eq 2</tdml:error>
- <tdml:error>contains a path</tdml:error>
- <tdml:error>../uoMember1[1]</tdml:error>
- <tdml:error>navigates to another branch</tdml:error>
- <tdml:error>of the same choice</tdml:error>
- </tdml:errors>
- </tdml:parserTestCase>
-
- <tdml:parserTestCase name="test_nested_path_evaluates_to_nodelist"
- model="nested_paths"
- description="navigate from unordered branch to element of an enclosing
- ordered sequence using function that expects nodeset"
- root="USG_07">
- <tdml:document><![CDATA[a123,b2,cz10:x20:y99]]></tdml:document>
- <tdml:infoset>
- <tdml:dfdlInfoset>
- <USG_07>
- <e1>
- <c1>1</c1>
- <c2>2</c2>
- <c3>3</c3>
- </e1>
- <e2>2</e2>
- <uoSeq>
- <uoMember1>20</uoMember1>
- <uoMember2>99</uoMember2>
- <uoMember3>10</uoMember3>
- </uoSeq>
- </USG_07>
- </tdml:dfdlInfoset>
- </tdml:infoset>
- </tdml:parserTestCase>
-
- <tdml:parserTestCase name="test_nested_invalid_path_to_branch"
- model="nested_paths"
- description="navigate from unordered sequence to another branch of same unordered sequence"
- root="USG_02">
- <tdml:document><![CDATA[a1,bx20:y99:z10,c55]]></tdml:document>
- <tdml:errors>
- <tdml:error>../uoMember1</tdml:error>
- <tdml:error>navigates</tdml:error>
- <tdml:error>to</tdml:error>
- <tdml:error>another</tdml:error>
- <tdml:error>branch</tdml:error>
- <tdml:error>uoMember1</tdml:error>
- <tdml:error>of</tdml:error>
- <tdml:error>same</tdml:error>
- <tdml:error>choice</tdml:error>
- </tdml:errors>
- </tdml:parserTestCase>
-
- <tdml:parserTestCase name="test_nested_invalid_path_to_branch_2"
- model="nested_paths"
- description="navigate from unordered sequence to enclosing unordered sequence"
- root="USG_03">
- <tdml:document><![CDATA[a1,bx20:y99:z10,c55]]></tdml:document>
- <tdml:errors>
- <tdml:error>Expression</tdml:error>
- <tdml:error>../../e1 eq 1</tdml:error>
- <tdml:error>navigates</tdml:error>
- <tdml:error>to</tdml:error>
- <tdml:error>branch</tdml:error>
- <tdml:error>another</tdml:error>
- <tdml:error>choice</tdml:error>
- <tdml:error>USG_03::LocalComplexTypeDef::sequence::element.choiceElement::LocalComplexTypeDef::choice</tdml:error>
- </tdml:errors>
- </tdml:parserTestCase>
-
- <tdml:parserTestCase name="test_nested_invalid_path_to_branch_3"
- model="nested_paths"
- description="navigate from unordered sequence to choice branch of enclosing ordered sequence"
- root="USG_04">
- <tdml:document><![CDATA[a1,bx20:y99:z10,c55]]></tdml:document>
- <tdml:errors>
- <tdml:error>Expression</tdml:error>
- <tdml:error>../../../choice[1]/e1 eq 1</tdml:error>
- <tdml:error>navigates</tdml:error>
- <tdml:error>to</tdml:error>
- <tdml:error>branch</tdml:error>
- <tdml:error>another</tdml:error>
- <tdml:error>choice</tdml:error>
- <tdml:error>USG_04::LocalComplexTypeDef::sequence::element.choice::LocalComplexTypeDef::choice</tdml:error>
+ <tdml:error>Schema Definition Error</tdml:error>
+ <tdml:error>Subset Indexing is only allowed on arrays</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
<tdml:defineSchema name="simple_sdes_1">
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
<dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
- lengthKind="delimited" />
+ lengthKind="delimited" occursCountKind="parsed" />
<!-- Immediate children of unordered sequence must be Element or ElementRef -->
<xs:element name="SDE_01">
@@ -845,9 +713,8 @@
root="SDE_01">
<tdml:document><![CDATA[a1,bx20:y99:z,c55]]></tdml:document>
<tdml:errors>
- <tdml:error>Members of an unordered sequence (element.SDE_01::LocalComplexTypeDef::sequence)</tdml:error>
- <tdml:error>must be Element or ElementRef.</tdml:error>
- <tdml:error>The offending members: choice.</tdml:error>
+ <tdml:error>Members of an unordered sequence</tdml:error>
+ <tdml:error>must be Element or ElementRef</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
@@ -857,9 +724,8 @@
root="SDE_02">
<tdml:document><![CDATA[a1,bx20:y99:z,c55]]></tdml:document>
<tdml:errors>
- <tdml:error>Members of an unordered sequence (element.SDE_02::LocalComplexTypeDef::sequence)</tdml:error>
+ <tdml:error>Members of an unordered sequence</tdml:error>
<tdml:error>that are optional or array elements must have dfdl:occursCountKind='parsed'.</tdml:error>
- <tdml:error>The offending members: ruh-oh.</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
@@ -869,10 +735,120 @@
root="SDE_03">
<tdml:document><![CDATA[a1,bx20:y99:z,c55]]></tdml:document>
<tdml:errors>
- <tdml:error>Two or more members of the unordered sequence (element.SDE_03::LocalComplexTypeDef::sequence)</tdml:error>
+ <tdml:error>Two or more members of the unordered sequence</tdml:error>
<tdml:error>have the same name and the same namespace.</tdml:error>
- <tdml:error>[Namespace: prefix "" is mapped to URI "http://example.com"] Name: e2.</tdml:error>
</tdml:errors>
- </tdml:parserTestCase>
+ </tdml:parserTestCase>
+
+ <tdml:defineSchema name="separated">
+ <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat" lengthUnits="characters"
+ lengthKind="delimited" occursCountKind="parsed" />
+ <xs:element name="infix">
+ <xs:complexType>
+ <xs:sequence dfdl:sequenceKind="unordered"
+ dfdl:separator="," dfdl:separatorPosition="infix">
+
+ <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="a">
+ </xs:element>
+
+ <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="b">
+ </xs:element>
+
+ <xs:element name="e3" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="c">
+ </xs:element>
+
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="prefix">
+ <xs:complexType>
+ <xs:sequence dfdl:sequenceKind="unordered"
+ dfdl:separator="," dfdl:separatorPosition="prefix">
+
+ <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="a">
+ </xs:element>
+
+ <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="b">
+ </xs:element>
+
+ <xs:element name="e3" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="c">
+ </xs:element>
+
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="postfix">
+ <xs:complexType>
+ <xs:sequence dfdl:sequenceKind="unordered"
+ dfdl:separator="," dfdl:separatorPosition="postfix">
+
+ <xs:element name="e1" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="a">
+ </xs:element>
+
+ <xs:element name="e2" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="b">
+ </xs:element>
+
+ <xs:element name="e3" type="xs:int" dfdl:lengthKind="delimited"
+ dfdl:initiator="c">
+ </xs:element>
+
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="test_separated_infix"
+ model="separated" root="infix">
+ <tdml:document><![CDATA[b2,a1,c3]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <infix>
+ <e1>1</e1>
+ <e2>2</e2>
+ <e3>3</e3>
+ </infix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="test_separated_prefix"
+ model="separated" root="prefix">
+ <tdml:document><![CDATA[,b2,a1,c3]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <prefix>
+ <e1>1</e1>
+ <e2>2</e2>
+ <e3>3</e3>
+ </prefix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
+ <tdml:parserTestCase name="test_separated_postfix"
+ model="separated" root="postfix">
+ <tdml:document><![CDATA[b2,a1,c3,]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <postfix>
+ <e1>1</e1>
+ <e2>2</e2>
+ <e3>3</e3>
+ </postfix>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
</tdml:testSuite>
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
index 8c7818c..363aac3 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section14/unordered_sequences/TestUnorderedSequencesNew.scala
@@ -17,33 +17,42 @@
package org.apache.daffodil.section14.unordered_sequences
-import org.apache.daffodil.util.Misc
-import org.apache.daffodil.tdml.DFDLTestSuite
+import org.junit.Test
+import org.junit.AfterClass
+import org.apache.daffodil.tdml.Runner
-class TestUnorderedSequencesNew {
+object TestUnorderedSequencesNew {
val testDir = "/org/apache/daffodil/section14/unordered_sequences/"
- val uos = testDir + "UnorderedSequences.tdml"
- val res = Misc.getRequiredResource(uos)
- lazy val runner = new DFDLTestSuite(res)
+ val runner = Runner(testDir, "UnorderedSequences.tdml")
+
+ @AfterClass def shutDown {
+ runner.reset
+ }
+}
+
+class TestUnorderedSequencesNew {
+
+ import TestUnorderedSequencesNew._
//DFDL-1010
- //@Test def test_simple = { runner.runOneTest("test_simple") }
- //@Test def test_simple_fail_scalar = { runner.runOneTest("test_simple_fail_scalar") }
- //@Test def test_simple_min_max_occurs = { runner.runOneTest("test_simple_min_max_occurs") }
- //@Test def test_simple_min_max_occurs_fail = { runner.runOneTest("test_simple_min_max_occurs_fail") }
- //@Test def test_simple_delimited = { runner.runOneTest("test_simple_delimited") }
- //@Test def test_simple_nil = { runner.runOneTest("test_simple_nil") }
- //@Test def test_simple_invalid_path_to_branch = { runner.runOneTest("test_simple_invalid_path_to_branch") }
- //@Test def test_simple_invalid_path_to_branch_does_not_exist = { runner.runOneTest("test_simple_invalid_path_to_branch_does_not_exist") }
- //@Test def test_nested_valid_path_to_branch = { runner.runOneTest("test_nested_valid_path_to_branch") }
- //@Test def test_nested_multiple_valid_paths_to_branch = { runner.runOneTest("test_nested_multiple_valid_paths_to_branch") }
- //@Test def test_nested_multiple_invalid_paths_to_branch = { runner.runOneTest("test_nested_multiple_invalid_paths_to_branch") }
- //@Test def test_nested_path_evaluates_to_nodelist = { runner.runOneTest("test_nested_path_evaluates_to_nodelist") }
- //@Test def test_nested_invalid_path_to_branch = { runner.runOneTest("test_nested_invalid_path_to_branch") }
- //@Test def test_nested_invalid_path_to_branch_2 = { runner.runOneTest("test_nested_invalid_path_to_branch_2") }
- //@Test def test_nested_invalid_path_to_branch_3 = { runner.runOneTest("test_nested_invalid_path_to_branch_3") }
- //@Test def test_sde_element_element_ref = { runner.runOneTest("test_sde_element_element_ref") }
- //@Test def test_sde_optional_array_ock_parsed = { runner.runOneTest("test_sde_optional_array_ock_parsed") }
- //@Test def test_sde_unique_names_in_ns = { runner.runOneTest("test_sde_unique_names_in_ns") }
+ @Test def test_simple = { runner.runOneTest("test_simple") }
+ @Test def test_simple_fail_scalar = { runner.runOneTest("test_simple_fail_scalar") }
+ @Test def test_simple_min_max_occurs = { runner.runOneTest("test_simple_min_max_occurs") }
+ @Test def test_simple_min_max_occurs_fail = { runner.runOneTest("test_simple_min_max_occurs_fail") }
+ @Test def test_array_reference = { runner.runOneTest("test_array_reference") }
+ @Test def test_simple_delimited = { runner.runOneTest("test_simple_delimited") }
+ @Test def test_separated_infix = { runner.runOneTest("test_separated_infix") }
+ @Test def test_separated_prefix = { runner.runOneTest("test_separated_prefix") }
+ @Test def test_separated_postfix = { runner.runOneTest("test_separated_postfix") }
+ @Test def test_simple_nil = { runner.runOneTest("test_simple_nil") }
+ @Test def test_simple_optional_elem = { runner.runOneTest("test_simple_optional_elem") }
+ @Test def test_simple_invalid_path_to_branch = { runner.runOneTest("test_simple_invalid_path_to_branch") }
+ @Test def test_simple_invalid_path_to_branch_does_not_exist = { runner.runOneTest("test_simple_invalid_path_to_branch_does_not_exist") }
+ @Test def test_nested_valid_path_to_branch = { runner.runOneTest("test_nested_valid_path_to_branch") }
+ @Test def test_nested_multiple_valid_paths_to_branch = { runner.runOneTest("test_nested_multiple_valid_paths_to_branch") }
+ @Test def test_nested_multiple_invalid_paths_to_branch = { runner.runOneTest("test_nested_multiple_invalid_paths_to_branch") }
+ @Test def test_sde_element_element_ref = { runner.runOneTest("test_sde_element_element_ref") }
+ @Test def test_sde_optional_array_ock_parsed = { runner.runOneTest("test_sde_optional_array_ock_parsed") }
+ @Test def test_sde_unique_names_in_ns = { runner.runOneTest("test_sde_unique_names_in_ns") }
}