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 d0dcca04e Fix check for trailingEmptyStrict policy validation
d0dcca04e is described below

commit d0dcca04e48e71a59947558f96365a07ba9fd8b1
Author: olabusayoT <[email protected]>
AuthorDate: Fri Oct 3 15:54:12 2025 -0400

    Fix check for trailingEmptyStrict policy validation
    
    - Resolved issues with trailingEmptyStrict violation when maxOccurs is '3' 
by improving checks for empty trailing optional elements.
    - Refactored code to introduce helper functions for condition checks with 
appropriate comments
    
    DAFFODIL-2217
---
 .../SeparatedSequenceChildParseResultHelper.scala  | 56 ++++++++++++++++++----
 .../apache/daffodil/usertests/TestSepTests.scala   |  4 +-
 2 files changed, 48 insertions(+), 12 deletions(-)

diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
index 5c1cc1364..fa170ba5f 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/SeparatedSequenceChildParseResultHelper.scala
@@ -125,18 +125,56 @@ trait SeparatedSequenceChildParseResultHelper extends 
SequenceChildParseResultHe
     priorResultOfTry: ParseAttemptStatus
   ): Unit = {
 
-    if ((sscb eq PositionalTrailingStrict)) {
-      val resultToTest = priorResultOfTry
-      resultToTest match {
-        case ParseAttemptStatus.AbsentRep | ParseAttemptStatus.EmptyRep =>
-          parser.PE(
-            pstate,
-            "Empty trailing optional elements are not allowed when 
dfdl:separatorSuppressionPolicy='trailingEmptyStrict'"
-          )
-        case _ => // ok
+    if (sscb eq PositionalTrailingStrict) {
+      //  We need to check both the last and second to last element for 
missing,
+      //  absent or empty status; depending on the data, the resultOfTry might
+      //  only address the status of the separator.
+      //
+      //  A missing separator for the resultOfTry doesn't tell us enough about
+      //  what is going on, because in the case the priorResultOfTry is normal,
+      //  then a failure due to missing separator may be the normal way
+      //  speculative parsing detects the end of an array. Backtracking will
+      //  suppress the missing separator error.  If however, the case is the
+      //  priorResultOfTry is missing, empty or absent, then
+      //  this detects a trailing empty, and when ssp=trailingEmptyStrict we
+      //  should issue a processing error.
+      //
+      //  Note that in the case of ssp=never we address that in the
+      //  arrayCompleteChecks.
+      //
+      //  We don't need to check sscb=lax since that can have missing, absent
+      //  or empty trailing elements
+      if (
+        checkTrailingOptionalElements(resultOfTry)
+        || checkTrailingOptionalElements(priorResultOfTry)
+      ) {
+        parser.PE(
+          pstate,
+          "Empty trailing optional elements are not allowed when 
dfdl:separatorSuppressionPolicy='trailingEmptyStrict'"
+        )
+      } else {
+        // ok
       }
     }
   }
+
+  /**
+   * Checks if the resultToTest is a missing, absent or empty element.
+   * In essence, this is a check for trailing optional elements with
+   * zero length representation. MissingItem is very similar to AbsentRep, in
+   * that it subsumes it except the difference seems to be AbsentRep is
+   * for zero length optional elements, and MissingItem is for zero length
+   * non-optional elements.
+   */
+  private def checkTrailingOptionalElements(
+    resultToTest: ParseAttemptStatus
+  ): Boolean = {
+    Seq(
+      ParseAttemptStatus.MissingItem,
+      ParseAttemptStatus.AbsentRep,
+      ParseAttemptStatus.EmptyRep
+    ).contains(resultToTest)
+  }
 }
 
 trait ScalarElementSeparatedSequenceChildParseResultHelper
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala 
b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
index 3a074deac..aa7347813 100644
--- 
a/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/usertests/TestSepTests.scala
@@ -20,7 +20,6 @@ package org.apache.daffodil.usertests
 import org.apache.daffodil.junit.tdml.TdmlSuite
 import org.apache.daffodil.junit.tdml.TdmlTests
 
-import org.junit.Ignore
 import org.junit.Test
 
 object TestSepTests extends TdmlSuite {
@@ -36,8 +35,7 @@ class TestSepTests extends TdmlTests {
   // DAFFODIL-2498 anyEmpty with minOccurs '0', and empty as first occurrence.
   @Test def test_sep_anyEmpty_2 = test
 
-  // DAFFODIL-2217 - trailingEmptyStrict violation not detected when maxOccurs 
is '3'
-  @Ignore @Test def test_sep_trailingEmptyStrict_1 = test
+  @Test def test_sep_trailingEmptyStrict_1 = test
   @Test def test_sep_trailingEmptyStrict_2 = test
 
   @Test def test_sep_ssp_never_1 = test

Reply via email to