From 73880165ba6b111e9cf9c2c6fab4dfb26f52df58 Mon Sep 17 00:00:00 2001
From: olabusayoT <50379531+olabusayoT@users.noreply.github.com>
Date: Thu, 26 Sep 2024 12:04:59 -0400
Subject: [PATCH] Warn about Multiple Child Elements with Same Name
- update code to reuse logic for unordered sequences check
- add multipleChildElementsWithSameName warning
- add test to check we get UPA error with choices
- add tests to exercise new warning
DAFFODIL-2736
---
.../daffodil/core/dsom/SequenceGroup.scala | 45 +++++++++----
.../org/apache/daffodil/xsd/dafext.xsd | 1 +
.../sequence_groups/SequenceGroup.tdml | 42 ++++++++++++
.../section15/choice_groups/choice2736.tdml | 66 +++++++++++++++++++
.../sequence_groups/TestSequenceGroups.scala | 5 ++
.../section15/choice_groups/TestChoice2.scala | 6 ++
6 files changed, 153 insertions(+), 12 deletions(-)
create mode 100644 daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice2736.tdml
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..b1213d7416 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,19 +216,39 @@ 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
+ private lazy val checkUnorderedSequenceMembersHaveUniqueNamesInNamespaces: Unit = {
+ val nonUniqueNameChildren =
+ checkMembersHaveUniqueNamesInNamespaces.filter(_._1 == true).values
+ nonUniqueNameChildren.foreach { children =>
+ children.head.SDE(
+ "Two or more members of an unordered sequence have the same name and the same namespace"
+ )
}
- childrenGroupedByQName.foreach { case (qname, children) =>
- if (children.length > 1) {
- children.head.SDE(
- "Two or more members of an unordered sequence have the same name and the same namespace"
- )
+ }
+
+ private lazy val checkMembersHaveUniqueNamesInNamespaces: Map[Boolean, Seq[Term]] = {
+ val childrenGroupedByQName = groupMembers
+ .filter { m => m.isInstanceOf[LocalElementDecl] || m.isInstanceOf[ElementRef] }
+ .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.map { case (qname, children) =>
+ (children.length > 1, children)
+ }
+ }
+
+ private lazy val checkIfMultipleChildrenWithSameName: Unit = {
+ val nonUniqueNameChildren =
+ checkMembersHaveUniqueNamesInNamespaces.filter(_._1 == true).values
+ nonUniqueNameChildren.foreach { children =>
+ children.head.SDW(
+ WarnID.MultipleChildElementsWithSameName,
+ "Two or more members of the sequence have the same name and namespace: %s",
+ children.head.asInstanceOf[ElementBase].namedQName
+ )
}
}
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 3d89c56617..24b90871ed 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
@@ -720,6 +720,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 b4b8d7552c..2770b64f8f 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
@@ -1536,4 +1536,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+
+
+
+ Schema Definition Warning
+ same name and namespace
+ AmbigElt
+
+
+
+
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 819d0fc2ee..70db3a2d1e 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
@@ -144,4 +144,9 @@ 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")
+ }
}
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")
+ }
}