Fix daf:trace so you can trace a complex element.
E.g. useful to trace in this context:
fn:exists(daf:trace(/foo/bar, "bar is complex type"))
I needed this fixed to debug jpeg's dfdl:assert expressions.
DFDL-1804
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DAFFunctions.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DAFFunctions.scala
index 39bed7a..4a9b7ca 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DAFFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/DAFFunctions.scala
@@ -35,14 +35,39 @@
import edu.illinois.ncsa.daffodil.processors.unparsers.UnparseError
import edu.illinois.ncsa.daffodil.util.Maybe.Nope
import edu.illinois.ncsa.daffodil.util.Maybe.One
+import edu.illinois.ncsa.daffodil.infoset.DISimple
+import edu.illinois.ncsa.daffodil.infoset.XMLTextInfosetOutputter
+import edu.illinois.ncsa.daffodil.infoset.InfosetCommon
case class DAFTrace(recipe: CompiledDPath, msg: String)
- extends FNOneArg(recipe, NodeInfo.AnyType) {
+ extends RecipeOpWithSubRecipes(recipe) {
- override def computeValue(str: AnyRef, dstate: DState) = {
- System.err.println("trace " + msg + ":" + str.toString)
- str
+ private def asXMLString(ie: InfosetCommon) = {
+ val sw = new java.io.StringWriter()
+ val xml = new XMLTextInfosetOutputter(sw)
+ ie.visit(xml, false)
+ sw.toString()
}
+
+ override def run(dstate: DState): Unit = {
+ recipe.run(dstate)
+ val nodeString: String = dstate.currentNode match {
+ case _: DISimple | null => {
+ // if there is no current node (null case) then there must be a
+ // current value.
+ val v = dstate.currentValue
+ dstate.setCurrentValue(v)
+ v.toString()
+ }
+ case other: InfosetCommon => "\n" + asXMLString(other)
+ }
+ System.err.println("trace " + msg + ":" + nodeString)
+ }
+
+ // This is toXML for the case class object, not the infoset node it is
+ // dealing with.
+ override def toXML = toXML(recipe.toXML)
+
}
case object DAFError extends RecipeOp {
diff --git a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/FNFunctions.scala b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/FNFunctions.scala
index b486de0..b438da5 100644
--- a/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/FNFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/dpath/FNFunctions.scala
@@ -32,7 +32,7 @@
package edu.illinois.ncsa.daffodil.dpath
-import edu.illinois.ncsa.daffodil.processors._ ; import edu.illinois.ncsa.daffodil.infoset._
+import edu.illinois.ncsa.daffodil.processors._; import edu.illinois.ncsa.daffodil.infoset._
import edu.illinois.ncsa.daffodil.processors.unparsers.UnparseError
import edu.illinois.ncsa.daffodil.api.Diagnostic
import edu.illinois.ncsa.daffodil.api.DataLocation
@@ -594,6 +594,11 @@
// if you reach into a child element slot that isn't filled
case e: InfosetNoSuchChildElementException => ifClosedDoesntExist(dstate, th)
case e: InfosetArrayIndexOutOfBoundsException => ifClosedDoesntExist(dstate, th)
+
+ // Note that in debugger, expressions are sometimes evaluated in contexts
+ // where they don't make sense.
+ // But we must rethrow this or it will get suppressed when it is a real error.
+ case e: InfosetWrongNodeType => throw th
//
// other processing errors indicate it doesn't exist
//
@@ -988,8 +993,8 @@
dstate.mode match {
case UnparserNonBlocking | UnparserBlocking =>
UnparseError(maybeSFL, dstate.contextLocation, errorString)
- case _ : ParserMode => {
- val fe = new FNErrorFunctionException(maybeSFL, dstate.contextLocation, errorString)
+ case _: ParserMode => {
+ val fe = new FNErrorFunctionException(maybeSFL, dstate.contextLocation, errorString)
throw fe
}
}
diff --git a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/expressions2.tdml b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/expressions2.tdml
index ef678d2..2baca72 100644
--- a/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/expressions2.tdml
+++ b/daffodil-test/src/test/resources/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/expressions2.tdml
@@ -245,5 +245,42 @@
<tdml:error>String</tdml:error>
</tdml:errors>
</tdml:parserTestCase>
+
+ <tdml:defineSchema name="traceComplex" elementFormDefault="unqualified">
+
+ <dfdl:format ref="ex:daffodilTest1" />
+
+ <xs:element name="e">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="aComplexElement">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="y" type="xs:int" dfdl:inputValueCalc="{ 0 }" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="f" type="xs:string"
+ dfdl:inputValueCalc="{ if (fn:exists(daf:trace(../aComplexElement, 'We can trace a complex element'))) then 'exists' else 'nope' }" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </tdml:defineSchema>
+
+ <tdml:parserTestCase name="traceComplex" model="traceComplex" root="e"
+ description="Test that daf:trace can take as argument a complex element.">
+ <tdml:document />
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <ex:e>
+ <aComplexElement>
+ <y>0</y>
+ </aComplexElement>
+ <f>exists</f>
+ </ex:e>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+
+ </tdml:parserTestCase>
</tdml:testSuite>
diff --git a/daffodil-test/src/test/scala/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala b/daffodil-test/src/test/scala/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
index 310c010..c279faa 100644
--- a/daffodil-test/src/test/scala/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
+++ b/daffodil-test/src/test/scala/edu/illinois/ncsa/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
@@ -1009,4 +1009,8 @@
// DFDL-1771
@Test def test_expr_path_past_root1 { runner7.runOneTest("test_expr_path_past_root1") }
+
+ // DFDL-1804
+ @Test def test_traceComplex { runner7.runOneTest("traceComplex") }
+
}