diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ModelGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ModelGroup.scala index 2e4db8b3f4..b97efb1e5c 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ModelGroup.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ModelGroup.scala @@ -341,6 +341,22 @@ abstract class ModelGroup protected (index: Int) } } + final lazy val elementChildrenInNonHiddenContext: Seq[ElementBase] = + LV('elementChildrenInNonHiddenContext) { + val ebs = groupMembers + .filter { + case gr: GroupRef => !gr.isHidden + case _ => true + } + .flatMap { gm => + gm match { + case eb: ElementBase => Seq(eb) + case gb: ModelGroup => gb.elementChildren + } + } + ebs + }.value + final lazy val elementChildren: Seq[ElementBase] = LV('elementChildren) { val gms = groupMembers val echls = gms.flatMap { gm => diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala index 5defef394c..68978d5bf6 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SequenceGroup.scala @@ -103,6 +103,7 @@ abstract class SequenceGroupTermBase(xml: Node, lexicalParent: SchemaComponent, requiredEvaluationsIfActivated(checkIfValidUnorderedSequence) requiredEvaluationsIfActivated(checkIfNonEmptyAndDiscrimsOrAsserts) + requiredEvaluationsIfActivated(checkIfMultipleChildrenWithSameName) protected def apparentXMLChildren: Seq[Node] @@ -181,7 +182,7 @@ abstract class SequenceGroupTermBase(xml: Node, lexicalParent: SchemaComponent, if (!isOrdered) { checkMembersAreAllElementOrElementRef checkMembersHaveValidOccursCountKind - checkMembersHaveUniqueNamesInNamespaces + checkUnorderedSequenceMembersHaveUniqueNamesInNamespaces } } @@ -215,20 +216,34 @@ abstract class SequenceGroupTermBase(xml: Node, lexicalParent: SchemaComponent, } } - private lazy val checkMembersHaveUniqueNamesInNamespaces: Unit = { - val childrenGroupedByQName = groupMembers.groupBy { gm => - // previous checks should ensure that all group members are either local - // elements or element references - Assert.invariant(gm.isInstanceOf[ElementBase]) - gm.asInstanceOf[ElementBase].namedQName - } - childrenGroupedByQName.foreach { case (qname, children) => - if (children.length > 1) { + private lazy val checkUnorderedSequenceMembersHaveUniqueNamesInNamespaces: Unit = { + // previous checks should ensure that all element children for unordered sequences are either local + // elements or element references + elementChildrenInNonHiddenContext + .groupBy(_.namedQName) + .filter(_._2.length > 1) + .values + .foreach { children => children.head.SDE( "Two or more members of an unordered sequence have the same name and the same namespace" ) } - } + } + + private lazy val checkIfMultipleChildrenWithSameName: Unit = { + elementChildrenInNonHiddenContext + .groupBy(_.name) + .filter(_._2.length > 1) + .values + .foreach { children => + children.head.SDW( + WarnID.MultipleChildElementsWithSameName, + "Two or more members of the sequence have the same name. " + + "Since not all infosets support namespaces or siblings with the same name, " + + "this could cause issues. QNames are: %s", + children.map(c => c.namedQName).mkString(", ") + ) + } } final lazy val isOrdered: Boolean = this.sequenceKind match { diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd index 69ea3fdbb5..befb240b68 100644 --- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd +++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd @@ -736,6 +736,7 @@ + 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 7707d14547..1b809da886 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 @@ -1237,6 +1237,7 @@ + @@ -1353,6 +1354,12 @@ + + Two or more members + same name + ex:inty + + + + Two or more members + same name + ex:inty + + + + Two or more members + same name + ex:inty + + @@ -1651,4 +1670,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + 3 + 4 + + + + + + Schema Definition Warning + same name + AmbigElt + + + + + + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + + 6 + + + 7 + + + 8 + + + + + + + + Schema Definition Warning + same name + {}e1 + u:e1 + + + + diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice2736.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice2736.tdml new file mode 100644 index 0000000000..a3e90a6a80 --- /dev/null +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice2736.tdml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Schema Definition Error + AmbigElt + Unique Particle Attribution + + + + + diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups.scala index 873eb6e7b9..56d47d8056 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups.scala @@ -147,4 +147,12 @@ class TestSequenceGroups { // @Test def test_delimiterScanning_03() { runner_01.runOneTest("delimiterScanning_03") } @Test def test_hiddenGroupIVC(): Unit = { runner_02.runOneTest("hiddenGroupIVC") } + + // DAFFODIL-2736 + @Test def test_multipleElemSameName() = { + runner_02.runOneTest("multipleElemSameName") + } + @Test def test_multipleElemSameNameDifferentNamespaces() = { + runner_02.runOneTest("multipleElemSameNameDifferentNamespaces") + } } diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice2.scala index 647ddec52a..3cd9025302 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice2.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section15/choice_groups/TestChoice2.scala @@ -28,11 +28,13 @@ object TestChoice2 { val runner = Runner(testDir, "choice1765.tdml") val runner1773 = Runner(testDir, "choice1773.tdml") val runner2162 = Runner(testDir, "choice2162.tdml") + val runner2736 = Runner(testDir, "choice2736.tdml") @AfterClass def shutDown(): Unit = { runner.reset runner1773.reset runner2162.reset + runner2736.reset } } @@ -63,4 +65,8 @@ class TestChoice2 { runner2162.runOneTest("choiceArrayDirectDispatch1") } + // DAFFODIL-2736 + @Test def test_choiceAmbiguousUPA() = { + runner2736.runOneTest("choiceAmbiguousUPA") + } }