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

slawrence 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 be6058009 Remove support for dfdlx:repType/Values from unions
be6058009 is described below

commit be6058009172af19ddddc52570dc1ceff20043f9
Author: Steve Lawrence <[email protected]>
AuthorDate: Tue Aug 29 08:45:14 2023 -0400

    Remove support for dfdlx:repType/Values from unions
    
    dfdlx:repTypex on simpleTypes references from unions are now ignored.
    Likewise, dfdlx:repValues and dfdlx:repValueRanges are also ignored.
    Unions are now only used for combining restrictions from their simple
    types.
    
    Deprecation/Compatibility:
    
    dfdlx:repType, dfdlx:repValues, and dfdlx:repValueRanges are now ignored
    if references on xs:simpleTypes that are referenced from xs:unions.
    Instead, unions should be combined into a single simple type with the
    combined representation type and values properties.
    
    DAFFODIL-2211
---
 .../apache/daffodil/core/dsom/SimpleTypes.scala    | 117 ++++-----------------
 .../runtime1/processors/TypeCalculator.scala       |  65 ------------
 .../extensions/type_calc/inputTypeCalc.tdml        |  84 ---------------
 .../extensions/TestInputTypeValueCalc.scala        |   7 --
 4 files changed, 23 insertions(+), 250 deletions(-)

diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala 
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala
index 838c9e4be..e102e2999 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SimpleTypes.scala
@@ -317,7 +317,7 @@ abstract class SimpleTypeDefBase(xml: Node, lexicalParent: 
SchemaComponent)
    * multiple elements and input/outputValueCalc, but using repType allows it 
to be done by
    * Daffodil. The task to convert a physical type to a logical type during 
parse (or in reverse
    * during unparse) is done via a TypeCalculator. The goal of this 
optTypeCalculator is to
-   * inspect the various properties (e.g. repType, enumeration, unions, 
repValues,
+   * inspect the various properties (e.g. repType, enumeration, repValues,
    * repValueRanges) and create a TypeCalculator that does the necessary 
conversions. This type
    * calculator will later be provided to a parser/unparser to be evaluated at 
runtime after the
    * physical representation is parsed or prior to being unparsed.
@@ -364,32 +364,13 @@ abstract class SimpleTypeDefBase(xml: Node, 
lexicalParent: SchemaComponent)
         }
       }
 
-      val fromUnion: Option[TypeCalculator] = optUnion.map { union =>
-        val subCalculators: Seq[(RepValueSet, RepValueSet, TypeCalculator)] =
-          union.unionMemberTypes.map(subType =>
-            (
-              subType.optRepValueSet.get,
-              subType.optLogicalValueSet.get,
-              subType.optTypeCalculator.get,
-            ),
-          )
-        TypeCalculatorCompiler.compileUnion(subCalculators)
-      }
-
-      val ans = (fromRestriction, fromUnion) match {
-        case (Some(x), None) => Some(x)
-        case (None, Some(x)) => Some(x)
-        case (None, None) => {
-          SDE(
-            "dfdlx:repType (%s) requires an enumeration or union with defined 
dfdlx:repValues",
-            repType.namedQName,
-          )
-        }
-        case (Some(_), Some(_)) =>
-          Assert.invariantFailed("Cannot combine an enumeration with a union")
-      }
+      schemaDefinitionUnless(
+        fromRestriction.isDefined,
+        "dfdlx:repType (%s) requires an enumeration with defined 
dfdlx:repValues",
+        repType.namedQName,
+      )
 
-      ans
+      fromRestriction
     })
   }.value
 
@@ -405,90 +386,38 @@ abstract class SimpleTypeDefBase(xml: Node, 
lexicalParent: SchemaComponent)
       })
   }.value
 
-  private lazy val optRepTypeFromSelf: Option[SimpleTypeBase with NamedMixin] =
-    LV('optRepTypeFromSelf) {
-      val optRepTypeDef = 
optRepTypeQName.flatMap(schemaSet.getGlobalSimpleTypeDef(_))
-      val optRepPrimType = 
optRepTypeQName.flatMap(schemaSet.getPrimitiveType(_))
-      Assert.invariant(!(optRepPrimType.isDefined && optRepTypeDef.isDefined))
-      if (optRepTypeQName.isDefined) {
-        schemaDefinitionUnless(
-          optRepTypeDef.isDefined || optRepPrimType.isDefined,
-          s"Cannot find reptype ${optRepTypeQNameString.get}",
-        )
-      }
-      optRepTypeDef.orElse(optRepPrimType)
-    }.value
-
-  private lazy val optRepTypeFromUnion: Option[SimpleTypeBase with NamedMixin] 
=
-    LV('optRepTypeFromUnion) {
-      optUnion.flatMap(union => {
-        val repTypes = union.unionMemberTypes.map(_.optRepType)
-        // check that all repTypes are the same
-        // Because of how we inline types, we do not expect to see structural 
equality,
-        // so we rely on the xml qname instead
-        val numRepTypes = repTypes.map(_.map(_.namedQName)).toSet.size
-        if (numRepTypes > 1) {
-          SDE("If any child type of a union has a repType, they all must have 
the same repType")
-        }
-        if (numRepTypes == 0) {
-          None
-        } else {
-          repTypes.head
-        }
-      })
-    }.value
-
-  /*
-   * We don't really need the NamedMixin. It is only used for detecting 
duplicates
-   * However, since only named types can be a repType, there is no problem
-   * in requiring them to be named
-   */
   override lazy val optRepType: Option[SimpleTypeBase with NamedMixin] = 
LV('optRepType) {
-    /*
-     * Note that there is no fromRestriction option here
-     * In theory, we could consider every restriction type without an explicit 
repType to be
-     * either a restriction or identity transform.
-     * In practice, this would introduce the overhead of a transform to almost 
every derived type.
-     * Instead, when a user needs a restriction transform, they must simply 
provide the reptype explitly,
-     * which is arguably a good design decision from a readability standpoint 
of the schema as well.
-     */
-    optRepTypeFromSelf.orElse(optRepTypeFromUnion)
+    val optRepTypeDef = 
optRepTypeQName.flatMap(schemaSet.getGlobalSimpleTypeDef(_))
+    val optRepPrimType = optRepTypeQName.flatMap(schemaSet.getPrimitiveType(_))
+    Assert.invariant(!(optRepPrimType.isDefined && optRepTypeDef.isDefined))
+    if (optRepTypeQName.isDefined) {
+      schemaDefinitionUnless(
+        optRepTypeDef.isDefined || optRepPrimType.isDefined,
+        s"Cannot find reptype ${optRepTypeQNameString.get}",
+      )
+    }
+    optRepTypeDef.orElse(optRepPrimType)
   }.toOption.flatten
 
   override lazy val optRepValueSet: Option[RepValueSet] = 
optRepTypeDef.flatMap(repType => {
     val primType: PrimType = repType.primType
 
     val fromRestriction: Option[RepValueSet] = 
optRestriction.flatMap(_.optRepValueSet)
-    val fromUnion: Option[RepValueSet] = {
-      val componentTypes = optUnion.map(_.unionMemberTypes).getOrElse(Seq())
-      val componentValueSets = componentTypes.flatMap(_.optRepValueSet)
-      val ans = componentValueSets.fold(RepValueSetCompiler.empty)((a, b) => 
a.merge(b))
-      if (ans.isEmpty) None else Some(ans)
-    }
     val fromSelf: Option[RepValueSet] = optRepValueSetFromAttribute
 
-    (fromRestriction, fromUnion, fromSelf) match {
-      case (None, None, None) => None
-      case (Some(a), None, None) => Some(a)
-      case (None, Some(a), None) => Some(a)
-      case (None, None, Some(a)) => Some(a)
-      case (Some(_), Some(_), _) => throw new IllegalStateException("Can't 
happen")
-      case (Some(_), _, Some(_)) =>
+    (fromRestriction, fromSelf) match {
+      case (None, None) => None
+      case (Some(a), None) => Some(a)
+      case (None, Some(a)) => Some(a)
+      case (Some(_), Some(_)) =>
         SDE("Cannot put repValues or repRangeValues on a simple type defining 
an enumeration")
-      case (_, Some(_), Some(_)) =>
-        SDE("Cannot put repValue or repRangeValues on a simple type defined by 
a union")
     }
 
   })
 
   lazy val optLogicalValueSet: Option[RepValueSet] = {
     val fromRestriction: Option[RepValueSet] = 
optRestriction.map(_.logicalValueSet)
-    val fromUnion: Option[RepValueSet] = optUnion.map(union => {
-      val subsets =
-        
union.unionMemberTypes.map(_.optLogicalValueSet).filter(_.isDefined).map(_.get)
-      subsets.fold(RepValueSetCompiler.empty)((a, b) => a.merge(b))
-    })
-    fromRestriction.orElse(fromUnion)
+    fromRestriction
   }
 
 }
diff --git 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala
 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala
index 7d602d097..b012fbcbb 100644
--- 
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala
+++ 
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/TypeCalculator.scala
@@ -217,43 +217,6 @@ class IdentityTypeCalculator(srcType: NodeInfo.Kind) 
extends TypeCalculator(srcT
   ): Either[Error, DataValuePrimitiveNullable] = Right(x)
 }
 
-class UnionTypeCalculator(
-  subCalculators: Seq[(RepValueSet, RepValueSet, TypeCalculator)],
-  srcType: NodeInfo.Kind,
-  dstType: NodeInfo.Kind,
-) extends TypeCalculator(srcType, dstType) {
-  // TODO, it may be worth it to pre-compute a hash table for direct dispatch,
-  // Similar to how keyset-value works
-  override def inputTypeCalc(
-    x: DataValuePrimitive,
-    xType: NodeInfo.Kind,
-  ): Either[Error, DataValuePrimitiveNullable] = {
-    val subCalcSeq = subCalculators.filter(sub => sub._1.contains(x))
-    Assert.invariant(subCalcSeq.length <= 1)
-    if (subCalcSeq.isEmpty) {
-      Left(s"Key ${x} does not match any component of this simpleType union")
-    } else {
-      val subCalc = subCalcSeq.head._3
-      subCalc.inputTypeCalc(x, xType)
-    }
-  }
-
-  override def outputTypeCalc(
-    x: DataValuePrimitive,
-    xType: NodeInfo.Kind,
-  ): Either[Error, DataValuePrimitiveNullable] = {
-    val subCalcSeq = subCalculators.filter(sub => sub._2.contains(x))
-    Assert.invariant(subCalcSeq.length <= 1)
-    if (subCalcSeq.isEmpty) {
-      Left(s"Key ${x} does not match the logical values from any component of 
this union.")
-    } else {
-      val subCalc = subCalcSeq.head._3
-      subCalc.outputTypeCalc(x, xType)
-    }
-  }
-
-}
-
 /*
  * Since we can inherit the restriction from xsd facets, we also need to be 
able to support an
  * aribitrary subset of: minInclusive, minExclusive, maxInclusive, and 
maxExclusive
@@ -262,18 +225,6 @@ class RepValueSet(
   val valueSet: HashSet[DataValuePrimitive],
   val valueRanges: Set[(RangeBound, RangeBound)],
 ) extends Serializable {
-  def contains(x: DataValuePrimitive): Boolean = {
-    val ans1 = valueSet.contains(x)
-    if (ans1) {
-      ans1
-    } else {
-      valueRanges
-        .map({ case (min, max) =>
-          min.testAsLower(x) && max.testAsUpper(x)
-        })
-        .fold(false)(_ || _)
-    }
-  }
 
   def merge(other: RepValueSet): RepValueSet = {
     val valueSet_ = valueSet ++ other.valueSet
@@ -347,22 +298,6 @@ object TypeCalculatorCompiler {
     srcType,
   )
 
-  // subCalculators: Seq[(repValues, logicalValues, subCalc)]
-  def compileUnion(
-    subCalculators: Seq[(RepValueSet, RepValueSet, TypeCalculator)],
-  ): TypeCalculator = {
-    // TODO, in some cases, it may be possible to merge some subCalculators
-    // It may also be possible to compute a direct dispatch table
-    val types = subCalculators.map(x => (x._3.srcType, x._3.dstType))
-    val srcTypes = types.map(_._1)
-    val dstTypes = types.map(_._2)
-    val srcType = srcTypes.head
-    val dstType = dstTypes.head
-    Assert.invariant(srcTypes.map(_ == srcType).reduce(_ == _))
-    Assert.invariant(dstTypes.map(_ == dstType).reduce(_ == _))
-    new UnionTypeCalculator(subCalculators, srcType, dstType)
-  }
-
 }
 
 object Range {
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/extensions/type_calc/inputTypeCalc.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/extensions/type_calc/inputTypeCalc.tdml
index 73909146a..ab64f6e67 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/extensions/type_calc/inputTypeCalc.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/extensions/type_calc/inputTypeCalc.tdml
@@ -63,56 +63,12 @@
       </xs:restriction>
     </xs:simpleType>
 
-    <xs:simpleType name="_1_to_string" dfdlx:repType="tns:uint8">
-      <xs:restriction base="xs:string">
-        <xs:enumeration value="one" dfdlx:repValues="1"/>
-      </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="_2through100_to_string" dfdlx:repType="tns:uint8">
-      <xs:restriction base="xs:string">
-        <xs:enumeration value="2-100" dfdlx:repValueRanges="2 100"/>
-      </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="_1through100_union_to_string" >
-      <xs:union memberTypes="tns:_1_to_string tns:_2through100_to_string 
tns:unreachableRepTypeuint8" />
-    </xs:simpleType>
-
-    <xs:simpleType name="_2through100_to_int" dfdlx:repType="tns:uint8">
-      <xs:restriction base="xs:unsignedInt">
-        <xs:minInclusive value="2"/>
-        <xs:maxInclusive value="100"/>
-      </xs:restriction>
-    </xs:simpleType>
-
-    <!-- Used to verify that a branch of a choice statement is not considered. 
-->
-    <xs:simpleType name="unreachableRepTypeuint8" dfdlx:repType="tns:uint8">
-      <xs:annotation>
-        <xs:appinfo source="http://www.ogf.org/dfdl/";>
-          <dfdl:discriminator>{ fn:true() }</dfdl:discriminator>
-        </xs:appinfo>
-      </xs:annotation>
-      <xs:restriction base="xs:string">
-        <xs:enumeration value="unreachable" dfdlx:repValues="-1"/>
-      </xs:restriction>
-    </xs:simpleType>
-
     <xs:simpleType name="complexSet_to_string" dfdlx:repType="tns:uint8">
       <xs:restriction base="xs:string">
         <xs:enumeration value="101 103-110 115 120-125" dfdlx:repValues="101 
115" dfdlx:repValueRanges="103 110 120 125"/>
       </xs:restriction>
     </xs:simpleType>
 
-
-    <xs:element name="inputTypeCalc_unionOfKeysetValueCalcs_01">
-      <xs:complexType>
-        <xs:sequence>
-          <xs:element name="byte" type="tns:_1through100_union_to_string" 
maxOccurs="unbounded" dfdl:occursCountKind="parsed"/>
-        </xs:sequence>
-      </xs:complexType>
-    </xs:element>
-
   </tdml:defineSchema>
 
   <tdml:parserTestCase name="InputTypeCalc_keysetValue_00"
@@ -236,46 +192,6 @@
     </tdml:infoset>
   </tdml:unparserTestCase>
 
-  <tdml:parserTestCase name="InputTypeCalc_unionOfKeysetValueCalcs_01"
-    root="inputTypeCalc_unionOfKeysetValueCalcs_01" 
model="inputTypeCalc-Embedded.dfdl.xsd" description="Extensions - repType with 
union of keysetValue types">
-
-    <tdml:document>
-    <tdml:documentPart type="byte">
-    01 02 03 64
-    </tdml:documentPart>
-    </tdml:document>
-    <tdml:infoset>
-      <tdml:dfdlInfoset xmlns:xs="http://www.w3.org/2001/XMLSchema";
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
-        <inputTypeCalc_unionOfKeysetValueCalcs_01>
-          <byte>one</byte>
-          <byte>2-100</byte>
-          <byte>2-100</byte>
-          <byte>2-100</byte>
-        </inputTypeCalc_unionOfKeysetValueCalcs_01>
-      </tdml:dfdlInfoset>
-    </tdml:infoset>
-  </tdml:parserTestCase>
-
-  <tdml:unparserTestCase 
name="InputTypeCalc_unparse_unionOfKeysetValueCalcs_01"
-    root="inputTypeCalc_unionOfKeysetValueCalcs_01" 
model="inputTypeCalc-Embedded.dfdl.xsd" description="Extensions - repType with 
union of keysetValue types">
-
-    <tdml:document>
-    <tdml:documentPart type="byte">
-    01 02
-    </tdml:documentPart>
-    </tdml:document>
-    <tdml:infoset>
-      <tdml:dfdlInfoset xmlns:xs="http://www.w3.org/2001/XMLSchema";
-        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
-        <inputTypeCalc_unionOfKeysetValueCalcs_01>
-          <byte>one</byte>
-          <byte>2-100</byte>
-        </inputTypeCalc_unionOfKeysetValueCalcs_01>
-      </tdml:dfdlInfoset>
-    </tdml:infoset>
-  </tdml:unparserTestCase>
-
   <tdml:defineSchema name="inputTypeCalc-Inherited.dfdl.xsd">
 
     <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/extensions/TestInputTypeValueCalc.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/extensions/TestInputTypeValueCalc.scala
index ab9eb19bf..0be2137c0 100644
--- 
a/daffodil-test/src/test/scala/org/apache/daffodil/extensions/TestInputTypeValueCalc.scala
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/extensions/TestInputTypeValueCalc.scala
@@ -55,13 +55,6 @@ class TestInputTypeValueCalc {
     runner.runOneTest("InputTypeCalc_unparse_keysetValue_02")
   }
 
-  @Test def test_InputTypeCalc_unionOfKeysetValueCalcs_01(): Unit = {
-    runner.runOneTest("InputTypeCalc_unionOfKeysetValueCalcs_01")
-  }
-  @Test def test_InputTypeCalc_unparse_unionOfKeysetValueCalcs_01(): Unit = {
-    runner.runOneTest("InputTypeCalc_unparse_unionOfKeysetValueCalcs_01")
-  }
-
   @Test def test_inherited_LengthKind(): Unit = { 
runner.runOneTest("inherited_LengthKind") }
 
   @Test def test_valueNotFound_1(): Unit = { 
runner.runOneTest("valueNotFound_1") }

Reply via email to