This is an automated email from the ASF dual-hosted git repository.

olabusayo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git


The following commit(s) were added to refs/heads/main by this push:
     new 75801c140 Add warning for `dfdl:occursCountKind=parsed` without 
`dfdl:separatorSuppressionPolicy=anyEmpty`
75801c140 is described below

commit 75801c1405432433e5db27f465bd87ac335c5b08
Author: olabusayoT <[email protected]>
AuthorDate: Wed Jan 21 15:04:21 2026 -0500

    Add warning for `dfdl:occursCountKind=parsed` without 
`dfdl:separatorSuppressionPolicy=anyEmpty`
    
    - Introduced `TestImplicitvParsed` including TDML tests for 
`occursCountKind=parsed` and `occursCountKind=implicit`.
    - Added "SeparatorSuppressionPolicyError" warning to enforce 
`separatorSuppressionPolicy="anyEmpty"` for `occursCountKind=parsed`.
    - Implicit with SSP=trailingEmpty works as expected, with it looking for 
the prefix / for absent arre1 in e2 in the added implicitvparsed.tdml as per 
the spec (Table 47: RepDef(min) ~ Rep(max - min), which means RepDef(1) 
followed by Rep(2), so it expects the separator for the last empty arre1 
element), so the right thing to do if we don't want the empty trailing / is to 
use anyEmpty
    - Add SSP warning and specify error message in SequenceGroupDelimiters TDML 
test
    - Updated test cases to align with these changes.
    
    DAFFODIL-2801
---
 .../apache/daffodil/core/dsom/SequenceGroup.scala  |  23 +++-
 .../resources/org/apache/daffodil/xsd/dafext.xsd   |   1 +
 .../section14/occursCountKind/implicitvparsed.tdml | 134 +++++++++++++++++++++
 .../sequence_groups/SequenceGroupDelimiters.tdml   |   9 +-
 .../org/apache/daffodil/usertests/SepTests.tdml    |   4 +-
 .../occursCountKind/TestImplicitvParsed.scala      |  35 ++++++
 6 files changed, 201 insertions(+), 5 deletions(-)

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 aa143c092..a6a9bc003 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
@@ -102,6 +102,7 @@ abstract class SequenceGroupTermBase(xml: Node, 
lexicalParent: SchemaComponent,
   with SeparatorSuppressionPolicyMixin {
 
   requiredEvaluationsIfActivated(checkIfValidUnorderedSequence)
+  requiredEvaluationsIfActivated(checkValidityOccursCountKind)
   requiredEvaluationsIfActivated(checkIfNonEmptyAndDiscrimsOrAsserts)
   requiredEvaluationsIfActivated(checkIfMultipleChildrenWithSameName)
 
@@ -160,6 +161,24 @@ abstract class SequenceGroupTermBase(xml: Node, 
lexicalParent: SchemaComponent,
     }
   }.value
 
+  lazy val checkValidityOccursCountKind: Unit = {
+    if (hasSeparator && (separatorSuppressionPolicy ne 
SeparatorSuppressionPolicy.AnyEmpty)) {
+      val optInvalidChild = groupMembers.find {
+        case e: ElementBase => e.occursCountKind == OccursCountKind.Parsed
+        case _ => false
+      }
+      if (optInvalidChild.isDefined) {
+        optInvalidChild.get.SDW(
+          WarnID.SeparatorSuppressionPolicyError,
+          "Member of a sequence with dfdl:occursCountKind='parsed' must have a 
" +
+            "containing sequence with 
dfdl:separatorSuppressionPolicy='anyEmpty', " +
+            "but was %s. This may be changed to an error in a future version 
of Daffodil.",
+          separatorSuppressionPolicy
+        )
+      }
+    }
+  }
+
   /**
    * Provides validation for assert and discriminator placement
    */
@@ -181,12 +200,12 @@ abstract class SequenceGroupTermBase(xml: Node, 
lexicalParent: SchemaComponent,
   protected final lazy val checkIfValidUnorderedSequence: Unit = {
     if (!isOrdered) {
       checkMembersAreAllElementOrElementRef
-      checkMembersHaveValidOccursCountKind
+      checkUnorderedSequenceMembersHaveValidOccursCountKind
       checkUnorderedSequenceMembersHaveUniqueNamesInNamespaces
     }
   }
 
-  private lazy val checkMembersHaveValidOccursCountKind: Unit = {
+  private lazy val checkUnorderedSequenceMembersHaveValidOccursCountKind: Unit 
= {
     val validChildren: Seq[ElementBase] =
       groupMembers
         .filter { m => m.isInstanceOf[LocalElementDecl] || 
m.isInstanceOf[ElementRef] }
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 719870bb2..8e0398c04 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
@@ -755,6 +755,7 @@
           <xs:enumeration value="patternEncodingSlashW" />
           <xs:enumeration value="queryStylePathExpression" />
           <xs:enumeration value="regexPatternZeroLength" />
+          <xs:enumeration value="separatorSuppressionPolicyError" />
           <xs:enumeration value="signedBinaryIntegerLength1Bit" />
           <xs:enumeration value="textBidiError" />
           <xs:enumeration value="textNumberPatternWarning" />
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
new file mode 100644
index 000000000..1a68f470b
--- /dev/null
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml
@@ -0,0 +1,134 @@
+<?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:xs="http://www.w3.org/2001/XMLSchema";
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+  xmlns:ex="http://example.com"; suiteName="rothrsreq" description="testing otg 
gold schemas" defaultRoundTrip="true">
+  <tdml:defineSchema name="otg-schema" elementFormDefault="unqualified" 
useDefaultNamespace="false">
+    <xs:include 
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+    <dfdl:defineFormat name="DefaultPropertiesFormat">
+      <dfdl:format ref="ex:GeneralFormat"
+        emptyValueDelimiterPolicy="none"
+        fillByte="0"
+        lengthKind="delimited"
+        lengthUnits="characters"
+        nilKind="literalValue"
+        nilValue="%ES;"
+        nilValueDelimiterPolicy="none"
+        representation="text"
+        separatorPosition="infix"
+        separatorSuppressionPolicy="anyEmpty"
+        textNumberPadCharacter="0"
+        textNumberPattern="###0.###;-###0.###"
+        textPadKind="none"
+        textStandardZeroRep="" />
+    </dfdl:defineFormat>
+    <dfdl:format ref="ex:DefaultPropertiesFormat"/>
+
+    <xs:element name="e1">
+      <xs:complexType>
+        <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix" 
dfdl:terminator="%NL;">
+          <xs:element name="se1" type="xs:int"/>
+          <xs:element name="se2" type="xs:int"/>
+          <xs:element name="arre1" maxOccurs="3" dfdl:occursCountKind="parsed">
+            <xs:complexType>
+              <xs:sequence dfdl:separator="-">
+                <xs:choice>
+                  <xs:element name="ie1" type="xs:int"/>
+                  <xs:element name="ie2" type="xs:float"/>
+                </xs:choice>
+                <xs:element name="ie3" type="xs:string"/>
+              </xs:sequence>
+            </xs:complexType>
+          </xs:element>
+          <xs:element name="se5" type="xs:string"/>
+          <xs:element name="se6" type="xs:int"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+
+    <xs:element name="e2">
+      <xs:complexType>
+        <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix" 
dfdl:terminator="%NL;">
+          <xs:element name="se1" type="xs:int"/>
+          <xs:element name="se2" type="xs:int"/>
+          <xs:element name="arre1" maxOccurs="3" 
dfdl:occursCountKind="implicit">
+            <xs:complexType>
+              <xs:sequence dfdl:separator="-">
+                <xs:choice>
+                  <xs:element name="ie1" type="xs:int"/>
+                  <xs:element name="ie2" type="xs:float"/>
+                </xs:choice>
+                <xs:element name="ie3" type="xs:string"/>
+              </xs:sequence>
+            </xs:complexType>
+          </xs:element>
+          <xs:element name="se5" type="xs:string"/>
+          <xs:element name="se6" type="xs:int"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>
+  </tdml:defineSchema>
+
+  <tdml:parserTestCase name="test_array_parsed" root="e1" model="otg-schema" 
roundTrip="none">
+    <tdml:document><![CDATA[/1/2/3.5-one/4-two/a/6
+]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:e1>
+          <se1>1</se1>
+          <se2>2</se2>
+          <arre1>
+            <ie2>3.5</ie2>
+            <ie3>one</ie3>
+          </arre1>
+          <arre1>
+            <ie1>4</ie1>
+            <ie3>two</ie3>
+          </arre1>
+          <se5>a</se5>
+          <se6>6</se6>
+        </ex:e1>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="test_array_implicit" root="e2" model="otg-schema" 
roundTrip="none">
+    <tdml:document><![CDATA[/1/2/3.5-one/4-two/a/6
+]]></tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset>
+        <ex:e2>
+          <se1>1</se1>
+          <se2>2</se2>
+          <arre1>
+            <ie2>3.5</ie2>
+            <ie3>one</ie3>
+          </arre1>
+          <arre1>
+            <ie1>4</ie1>
+            <ie3>two</ie3>
+          </arre1>
+          <se5>a</se5>
+          <se6>6</se6>
+        </ex:e2>
+      </tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+</tdml:testSuite>
\ No newline at end of file
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
index d3f10849f..4f9af2023 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupDelimiters.tdml
@@ -296,8 +296,15 @@
 
     <tdml:document><![CDATA[1,2,3,4,5,6
                ]]></tdml:document>
+
+    <tdml:warnings>
+      <tdml:warning>occursCountKind='parsed'</tdml:warning>
+      <tdml:warning>must have</tdml:warning>
+      <tdml:warning>separatorSuppressionPolicy='anyEmpty'</tdml:warning>
+      <tdml:warning>but was never</tdml:warning>
+    </tdml:warnings>
     <tdml:errors>
-      <tdml:error></tdml:error>
+      <tdml:error>left over data</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
 
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml 
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
index 61d08de6b..5878e386f 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/usertests/SepTests.tdml
@@ -456,11 +456,11 @@
 
     <xs:element name="root" dfdl:initiator="RECORD">
       <xs:complexType>
-        <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix" 
dfdl:terminator="%NL;">
+        <xs:sequence dfdl:separator="/" dfdl:separatorPosition="prefix" 
dfdl:terminator="%NL;" dfdl:separatorSuppressionPolicy="anyEmpty">
           <xs:element name="field1" type="xs:string" />
           <xs:element name="field2" type="xs:string" minOccurs="0" />
           <xs:element name="field3" type="xs:string" minOccurs="0" />
-          <xs:element name="groupOfFields" minOccurs="1" maxOccurs="3" 
dfdl:occursCountKind="parsed">
+          <xs:element name="groupOfFields" minOccurs="1" maxOccurs="3">
             <xs:complexType>
               <xs:sequence>
                 <xs:sequence dfdl:separator="/" dfdl:separatorPosition="infix" 
dfdl:separatorSuppressionPolicy="never">
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
new file mode 100644
index 000000000..26a5dc5ba
--- /dev/null
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/occursCountKind/TestImplicitvParsed.scala
@@ -0,0 +1,35 @@
+/*
+ * 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.occursCountKind
+
+import org.apache.daffodil.junit.tdml.TdmlSuite
+import org.apache.daffodil.junit.tdml.TdmlTests
+
+import org.junit.Test
+
+object TestImplicitvParsed extends TdmlSuite {
+  val tdmlResource = 
"org/apache/daffodil/section14/occursCountKind/implicitvparsed.tdml"
+}
+
+class TestImplicitvParsed extends TdmlTests {
+  val tdmlSuite = TestImplicitvParsed
+
+  @Test def test_array_parsed = test
+  @Test def test_array_implicit = test
+
+}

Reply via email to