This is an automated email from the ASF dual-hosted git repository. jadams pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
commit e9d240727791964966c14a38dd7008ee8ed4ddd2 Author: Josh Adams <[email protected]> AuthorDate: Fri Oct 23 15:33:58 2020 -0400 Improve newVariableInstace defaultValue expressions This commit enables newVariableInstance's to have non-constant default value expressions. These expressions are evaluated when the newVariableInstance is created. DAFFODIL-2352 --- .../apache/daffodil/dsom/DFDLDefineVariable.scala | 2 +- .../unparsers/ExpressionEvaluatingUnparsers.scala | 3 +- .../apache/daffodil/processors/RuntimeData.scala | 4 +- .../apache/daffodil/processors/VariableMap1.scala | 11 +++- .../parsers/ExpressionEvaluatingParsers.scala | 2 +- .../daffodil/processors/parsers/PState.scala | 4 +- .../daffodil/processors/unparsers/UState.scala | 4 +- .../daffodil/section07/variables/variables.tdml | 67 ++++++++++++++++++++++ .../section07/variables/TestVariables.scala | 3 + 9 files changed, 89 insertions(+), 11 deletions(-) diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala index 41d7b97..a449592 100644 --- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala +++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/DFDLDefineVariable.scala @@ -62,7 +62,7 @@ class DFDLDefineVariable(node: Node, doc: SchemaDocument) final lazy val primType = PrimType.fromNameString(typeQName.local).getOrElse( this.SDE("Variables must have primitive type. Type was '%s'.", typeQName.toPrettyString)) - final def createVariableInstance = variableRuntimeData.createVariableInstance + final def createVariableInstance = variableRuntimeData.createVariableInstance() final override lazy val runtimeData = variableRuntimeData diff --git a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala index 719cc34..855e54c 100644 --- a/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala +++ b/daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/processors/unparsers/ExpressionEvaluatingUnparsers.scala @@ -87,7 +87,8 @@ class NewVariableInstanceStartUnparser(override val context: RuntimeData) override lazy val childProcessors = Vector() override def unparse(state: UState) = { - state.newVariableInstance(context.asInstanceOf[VariableRuntimeData]) + val vrd = context.asInstanceOf[VariableRuntimeData] + state.newVariableInstance(vrd, vrd, state) } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala index da76ce8..c80e2c7 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/RuntimeData.scala @@ -987,6 +987,8 @@ final class VariableRuntimeData( } } - def createVariableInstance: VariableInstance = VariableInstance(state, value, this, maybeDefaultValueExpr) + def createVariableInstance(defaultValue: DataValuePrimitiveNullable = value): VariableInstance = { + VariableInstance(state, defaultValue, this, maybeDefaultValueExpr) + } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala index 3346540..5c31336 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/VariableMap1.scala @@ -173,7 +173,7 @@ class VariableMap private(vTable: Map[GlobalQName, MStackOf[VariableInstance]]) def this(topLevelVRDs: Seq[VariableRuntimeData] = Nil) = this(Map(topLevelVRDs.map { vrd => - val variab = vrd.createVariableInstance + val variab = vrd.createVariableInstance() val stack = new MStackOf[VariableInstance] stack.push(variab) (vrd.globalQName, stack) @@ -286,11 +286,16 @@ class VariableMap private(vTable: Map[GlobalQName, MStackOf[VariableInstance]]) /** * Creates a new instance of a variable */ - def newVariableInstance(vrd: VariableRuntimeData) = { + def newVariableInstance(vrd: VariableRuntimeData, referringContext: ThrowsSDE, state: ParseOrUnparseState) = { val varQName = vrd.globalQName val stack = vTable.get(varQName) Assert.invariant(stack.isDefined) - stack.get.push(vrd.createVariableInstance) + + if (vrd.maybeDefaultValueExpr.isDefined) { + val defaultValue = DataValue.unsafeFromAnyRef(vrd.maybeDefaultValueExpr.get.evaluate(state)) + stack.get.push(vrd.createVariableInstance(VariableUtils.convert(defaultValue.getAnyRef.toString, vrd, referringContext))) + } else + stack.get.push(vrd.createVariableInstance()) } def removeVariableInstance(vrd: VariableRuntimeData): Unit = { diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala index e7c24a1..2dc1c1c 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/ExpressionEvaluatingParsers.scala @@ -165,7 +165,7 @@ class NewVariableInstanceStartParser(override val context: VariableRuntimeData) override lazy val runtimeDependencies = Vector() def parse(start: PState): Unit = { - start.newVariableInstance(context) + start.newVariableInstance(context, context, start) } } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala index 99c7194..09018d0 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/parsers/PState.scala @@ -343,8 +343,8 @@ final class PState private ( changedVariablesStack.top += vrd.globalQName } - def newVariableInstance(vrd: VariableRuntimeData): Unit = { - variableMap.newVariableInstance(vrd) + def newVariableInstance(vrd: VariableRuntimeData, referringContext: VariableRuntimeData, pstate: PState): Unit = { + variableMap.newVariableInstance(vrd, referringContext, pstate) changedVariablesStack.top += vrd.globalQName } diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala index 888dd55..f033e1b 100644 --- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala +++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/unparsers/UState.scala @@ -343,8 +343,8 @@ abstract class UState( def documentElement: DIDocument - def newVariableInstance(vrd: VariableRuntimeData): Unit = { - variableMap.newVariableInstance(vrd) + def newVariableInstance(vrd: VariableRuntimeData, referringContext: VariableRuntimeData, ustate: UState): Unit = { + variableMap.newVariableInstance(vrd, referringContext, ustate) } def removeVariableInstance(vrd: VariableRuntimeData): Unit = { diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml index 37cf970..453c2ec 100644 --- a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml +++ b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables.tdml @@ -33,6 +33,10 @@ defaultValue="16" /> <dfdl:defineVariable name="myVar3" type="xs:int" defaultValue="26" /> + <!--<dfdl:defineVariable name="myVar4" type="xs:int" + defaultValue="36" /> + <dfdl:defineVariable name="nonConstVar" type="xs:int" + defaultValue="{ $ex:myVar4 }" />--> <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/> <dfdl:format ref="ex:GeneralFormat" /> <xs:element name="c"> @@ -408,6 +412,37 @@ </xs:complexType> </xs:element> + <xs:element name="nvi12"> + <xs:complexType> + <xs:sequence> + <xs:element name="oldVarValue" type="xsd:int" dfdl:inputValueCalc="{ $ex:myVar1 }" /> + <xs:element name="newDefaultValue" type="xsd:int" dfdl:lengthKind="explicit" dfdl:length="1" /> + <xs:element name="innerSeq"> + <xs:complexType> + <xs:sequence> + <xs:annotation> + <xs:appinfo source="http://www.ogf.org/dfdl/"> + <dfdl:newVariableInstance ref="ex:myVar1" + defaultValue="{ ../ex:newDefaultValue }" /> + </xs:appinfo> + </xs:annotation> + <xs:element name="newVarValue" type="xs:int" + dfdl:inputValueCalc="{ $ex:myVar1 }" /> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <!--<xs:element name="defNonConst"> + <xs:complexType> + <xs:sequence> + <xs:element name="value" type="xsd:int" dfdl:inputValueCalc="{ $ex:nonConstVar }" /> + </xs:sequence> + </xs:complexType> + </xs:element>--> + <xs:element name="e1"> <xs:complexType> <xs:sequence dfdl:separator="{ $ex:v1_with_default }" @@ -912,6 +947,38 @@ </tdml:errors> </tdml:parserTestCase> + <tdml:parserTestCase name="varInstance_12" root="nvi12" + model="v" + description="newVariablesInstance with a non-constant expression as defaultValue"> + + <tdml:document><![CDATA[7]]></tdml:document> + + <tdml:infoset> + <tdml:dfdlInfoset> + <nvi12 xmlns="http://example.com"> + <oldVarValue xsi:type="xsd:int">6</oldVarValue> + <newDefaultValue xsi:type="xsd:int">7</newDefaultValue> + <innerSeq> + <newVarValue xsi:type="xsd:int">7</newVarValue> + </innerSeq> + </nvi12> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase> + + <!--<tdml:parserTestCase name="defineVariable_nonConstantExpression" root="defNonConst" + model="v" + description="defineVariable with a non-constant expression as defaultValue"> + + <tdml:infoset> + <tdml:dfdlInfoset> + <defNonConst xmlns="http://example.com"> + <value>36</value> + </defNonConst> + </tdml:dfdlInfoset> + </tdml:infoset> + </tdml:parserTestCase>--> + <tdml:parserTestCase name="varAsSeparator" root="e1" model="v" description="variable referenced as a separator; the defineVariable annotation occurs after the element declaration that references it - DFDL-7-107R"> diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala index ff4d01f..9f81647 100644 --- a/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala +++ b/daffodil-test/src/test/scala/org/apache/daffodil/section07/variables/TestVariables.scala @@ -59,6 +59,9 @@ class TestVariables { @Test def test_varInstance_09(): Unit = { runner.runOneTest("varInstance_09") } @Test def test_varInstance_10(): Unit = { runner.runOneTest("varInstance_10") } @Test def test_varInstance_11(): Unit = { runner.runOneTest("varInstance_11") } + @Test def test_varInstance_12(): Unit = { runner.runOneTest("varInstance_12") } + // Causes OOLAG Circular Definition + // @Test def test_defineVariable_nonConstantExpression(): Unit = { runner.runOneTest("defineVariable_nonConstantExpression") } @Test def test_setVarChoice(): Unit = { runner.runOneTest("setVarChoice") } @Test def test_unparse_setVarChoice(): Unit = { runner.runOneTest("unparse_setVarChoice") } @Test def test_setVarOnSeqAndElemRef(): Unit = { runner.runOneTest("setVarOnSeqAndElemRef") }
