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") }