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 97ea8f75d Support locally suppressing schema definition warnings
97ea8f75d is described below
commit 97ea8f75de522d9d172f94a83f68fb6a7545b72c
Author: Steve Lawrence <[email protected]>
AuthorDate: Tue Sep 17 15:21:25 2024 -0400
Support locally suppressing schema definition warnings
We currently only support supressing schema definition warnings globally
with the use of tunables. However, some uses of Daffodil may not be able
to set tunables. Or in some cases we want to suppress a warning if it is
caused by a specific location in a schema, but all others should not be
suppressed.
Tos support this, this adds support for a new
"daf:suppressSchemaDefinitionWarnings" attribute, where the value is a
whitespace separated list of schema definition warnings to suppress if
the schema component it is placed on leads to a schema definition
warning. Note that this property does not follow morning DFDL property
scoping rules. So for example, you cannot have a default value defined
in a DFDL format that applies globally to a schema.
Additionaly, we need to treat the new property similar to how to treat
dfdl:ref (i.e. exclude it from certain logic), so logic related to
excluding dfdl:ref is made more generic to support the new property,
reduce special cases, and make surrounding code more consistent.
DAFFODIL-2638
---
.../apache/daffodil/core/dpath/Expression.scala | 4 ++
.../daffodil/core/dsom/DFDLFormatAnnotation.scala | 75 ++++++++++++----------
.../daffodil/core/dsom/SchemaComponent.scala | 13 ++++
.../apache/daffodil/core/grammar/GrammarTerm.scala | 2 +
.../core/runtime1/ElementBaseRuntime1Mixin.scala | 3 +-
.../apache/daffodil/propGen/TunableGenerator.scala | 4 --
.../runtime1/debugger/InteractiveDebugger.scala | 3 +
.../org/apache/daffodil/runtime1/dsom/SDE.scala | 7 +-
.../runtime1/processors/ProcessorStateBases.scala | 8 ++-
.../daffodil/runtime1/processors/RuntimeData.scala | 9 ++-
.../SchemaDefinitionErrors.tdml | 27 ++++++++
.../schema_definition_errors/TestSDE.scala | 4 ++
12 files changed, 115 insertions(+), 44 deletions(-)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala
index b3c0a127d..a0ae36b50 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala
@@ -54,6 +54,8 @@ abstract class Expression extends OOLAGHostImpl() with
BasicComponent {
override lazy val tunable: DaffodilTunables = parent.tunable
override lazy val unqualifiedPathStepPolicy: UnqualifiedPathStepPolicy =
parent.unqualifiedPathStepPolicy
+ override lazy val localSuppressSchemaDefinitionWarnings: Seq[WarnID] =
+ parent.localSuppressSchemaDefinitionWarnings
/**
* Override where we traverse/access elements.
@@ -463,6 +465,8 @@ case class WholeExpression(
final override lazy val tunable: DaffodilTunables = host.tunable
final override lazy val unqualifiedPathStepPolicy: UnqualifiedPathStepPolicy
=
host.unqualifiedPathStepPolicy
+ final override lazy val localSuppressSchemaDefinitionWarnings: Seq[WarnID] =
+ host.localSuppressSchemaDefinitionWarnings
def init(): Unit = {
this.setOOLAGContext(
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLFormatAnnotation.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLFormatAnnotation.scala
index fdcf2bee7..c91ee8fc6 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLFormatAnnotation.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLFormatAnnotation.scala
@@ -195,20 +195,36 @@ abstract class DFDLFormatAnnotation(nodeArg: Node,
annotatedSCArg: AnnotatedSche
res
}
+ /**
+ * Some properties (e.g. dfdl:ref, daf:suppressSchemaDefinitionWarnings) do
not follow normal
+ * scoping rules and so are manually handled elsewhere in Daffodil. These
are the lists of
+ * those properties used to exlucde them from property lookups.
+ */
+ private lazy val nonStandardDfdlProperties = Seq("ref")
+ private lazy val nonStandardDfdlxProperties = Seq()
+ private lazy val nonStandardDafProperties =
Seq("suppressSchemaDefinitionWarnings")
+
private lazy val shortFormProperties: Set[PropItem] =
LV[Set[PropItem]]('shortFormProperties) {
// shortForm properties should be prefixed by dfdl
// Remove the dfdl prefix from the attributes so that they
// can be properly combined later.
- val dfdlKvPairs = XMLUtils.dfdlAttributes(annotatedSC.xml).asAttrMap.map
{
- case (key: String, value: String) => (removePrefix(key), value)
- }
- val dfdlxKvPairs =
XMLUtils.dfdlxAttributes(annotatedSC.xml).asAttrMap.map {
- case (key: String, value: String) => (removePrefix(key), value)
- }
- val dafKvPairs = XMLUtils.dafAttributes(annotatedSC.xml).asAttrMap.map {
- case (key: String, value: String) => (removePrefix(key), value)
- }
+ val dfdlKvPairs = XMLUtils
+ .dfdlAttributes(annotatedSC.xml)
+ .asAttrMap
+ .map { kv => (removePrefix(kv._1), kv._2) }
+ .filterNot { kv => nonStandardDfdlProperties.contains(kv._1) }
+ val dfdlxKvPairs = XMLUtils
+ .dfdlxAttributes(annotatedSC.xml)
+ .asAttrMap
+ .map { kv => (removePrefix(kv._1), kv._2) }
+ .filterNot { kv => nonStandardDfdlxProperties.contains(kv._1) }
+ val dafKvPairs = XMLUtils
+ .dafAttributes(annotatedSC.xml)
+ .asAttrMap
+ .map { kv => (removePrefix(kv._1), kv._2) }
+ .filterNot { kv => nonStandardDafProperties.contains(kv._1) }
+
dfdlKvPairs.keys.foreach { propName =>
DeprecatedProperty.warnIfDeprecated(propName, XMLUtils.DFDL_NAMESPACE,
this)
}
@@ -220,8 +236,7 @@ abstract class DFDLFormatAnnotation(nodeArg: Node,
annotatedSCArg: AnnotatedSche
}
val kvPairs = dfdlKvPairs ++ dfdlxKvPairs ++ dafKvPairs
- val kvPairsButNotRef = kvPairs.filterNot { _._1 == "ref" } // dfdl:ref
is NOT a property
- val pairs = kvPairsButNotRef.map { case (k, v) =>
+ val pairs = kvPairs.map { case (k, v) =>
(k, (v, annotatedSC)).asInstanceOf[PropItem]
}
pairs.toSet
@@ -229,28 +244,22 @@ abstract class DFDLFormatAnnotation(nodeArg: Node,
annotatedSCArg: AnnotatedSche
private lazy val longFormProperties: Set[PropItem] =
LV[Set[PropItem]]('longFormProperties) {
// longForm Properties are not prefixed by dfdl
- val dfdlAttrs = dfdlAttributes(xml).asAttrMap
- schemaDefinitionUnless(dfdlAttrs.isEmpty, "long form properties are not
prefixed by dfdl:")
+ schemaDefinitionUnless(
+ dfdlAttributes(xml).isEmpty,
+ "long form properties are not prefixed by dfdl:"
+ )
+ val dfdlAttrMap = xml.attributes.asAttrMap
+ .filter { kv => !kv._1.contains(":") }
+ .filterNot { kv => nonStandardDfdlProperties.contains(kv._1) }
// however, extension properties are prefixed, even in long form
- val dfdlxAttrMap = dfdlxAttributes(xml).asAttrMap.map { case (key: String,
value: String) =>
- (removePrefix(key), value)
- }
- val dafAttrMap = dafAttributes(xml).asAttrMap.map { case (key: String,
value: String) =>
- (removePrefix(key), value)
- }
- //
- // TODO: This strips away any qualified attribute
- // That won't work when we add extension attributes
- // like daffodil:asAttribute="true"
- //
- val kvPairs = xml.attributes.asAttrMap.collect {
- case (k, v) if (!k.contains(":")) => (k, v)
- }
- val unqualifiedAttribs = kvPairs.filterNot {
- _._1 == "ref"
- } // get the ref off there. it is not a property.
-
- unqualifiedAttribs.keys.foreach { propName =>
+ val dfdlxAttrMap = dfdlxAttributes(xml).asAttrMap
+ .map { kv => (removePrefix(kv._1), kv._2) }
+ .filterNot { kv => nonStandardDfdlxProperties.contains(kv._1) }
+ val dafAttrMap = dafAttributes(xml).asAttrMap
+ .map { kv => (removePrefix(kv._1), kv._2) }
+ .filterNot { kv => nonStandardDafProperties.contains(kv._1) }
+
+ dfdlAttrMap.keys.foreach { propName =>
DeprecatedProperty.warnIfDeprecated(propName, XMLUtils.DFDL_NAMESPACE,
this)
}
dfdlxAttrMap.keys.foreach { propName =>
@@ -260,7 +269,7 @@ abstract class DFDLFormatAnnotation(nodeArg: Node,
annotatedSCArg: AnnotatedSche
DeprecatedProperty.warnIfDeprecated(propName, XMLUtils.EXT_NS_APACHE,
this)
}
- val dfdlAndExtAttribs = unqualifiedAttribs ++ dfdlxAttrMap ++ dafAttrMap
+ val dfdlAndExtAttribs = dfdlAttrMap ++ dfdlxAttrMap ++ dafAttrMap
val res = dfdlAndExtAttribs.map { case (k, v) =>
(k, (v, this.asInstanceOf[LookupLocation]))
}.toSet
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
index 7630ad360..9d78ab250 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala
@@ -21,6 +21,7 @@ import scala.xml.Node
import org.apache.daffodil.core.runtime1.SchemaComponentRuntime1Mixin
import org.apache.daffodil.lib.api.DaffodilTunables
+import org.apache.daffodil.lib.api.WarnID
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.schema.annotation.props.PropTypes
import org.apache.daffodil.lib.util.Delay
@@ -67,6 +68,18 @@ trait SchemaComponent
def xml: Node
+ final lazy val localSuppressSchemaDefinitionWarnings = {
+ val optAttr =
+ xml.attribute(XMLUtils.EXT_NS_APACHE,
"suppressSchemaDefinitionWarnings").map { _.text }
+ val warnStrs: Seq[String] =
+ optAttr.map { _.trim.split("\\s+").toSeq }.getOrElse { Seq.empty }
+ val warnIDs = warnStrs.map { warnStr =>
+ // throws SDE if not valid warnID
+ WarnID.stringToEnum("daf:suppressSchemaDefinitionWarnings", warnStr,
this)
+ }
+ warnIDs
+ }
+
override def oolagContextViaArgs = optLexicalParent
override lazy val tunable: DaffodilTunables = optLexicalParent.get.tunable
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/GrammarTerm.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/GrammarTerm.scala
index 1ee3f2703..c1237a889 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/GrammarTerm.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/GrammarTerm.scala
@@ -58,6 +58,8 @@ abstract class Gram(contextArg: SchemaComponent)
final override def namespaces = context.namespaces
final override def unqualifiedPathStepPolicy =
context.unqualifiedPathStepPolicy
final override def schemaFileLocation = context.schemaFileLocation
+ final override def localSuppressSchemaDefinitionWarnings =
+ context.localSuppressSchemaDefinitionWarnings
final override def SDE(str: String, args: Any*): Nothing = context.SDE(str,
args: _*)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala
index 59dcc6a85..0493c691a 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/ElementBaseRuntime1Mixin.scala
@@ -220,7 +220,8 @@ trait ElementBaseRuntime1Mixin { self: ElementBase =>
maybeCheckByteAndBitOrderEv,
maybeCheckBitOrderAndCharsetEv,
isQuasiElement,
- runtimeProperties
+ runtimeProperties,
+ localSuppressSchemaDefinitionWarnings
)
newERD
}.value
diff --git
a/daffodil-propgen/src/main/scala/org/apache/daffodil/propGen/TunableGenerator.scala
b/daffodil-propgen/src/main/scala/org/apache/daffodil/propGen/TunableGenerator.scala
index 3ae6edefd..bbdd232a9 100644
---
a/daffodil-propgen/src/main/scala/org/apache/daffodil/propGen/TunableGenerator.scala
+++
b/daffodil-propgen/src/main/scala/org/apache/daffodil/propGen/TunableGenerator.scala
@@ -106,10 +106,6 @@ class TunableGenerator(schemaRootConfig: scala.xml.Node,
schemaRootExt: scala.xm
| }
| }
|
- | def notSuppressedWarning(warnID: WarnID) =
- | !suppressSchemaDefinitionWarnings.contains(warnID) &&
- | !suppressSchemaDefinitionWarnings.contains(WarnID.All)
- |
| private def throwInvalidTunableValue(tunable: String, value: String) = {
| throw new IllegalArgumentException("Invalid value for tunable " +
tunable + ": " + value)
| }
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
index 2b7b56c12..47c95ddf4 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/debugger/InteractiveDebugger.scala
@@ -20,6 +20,7 @@ package org.apache.daffodil.runtime1.debugger
import java.io.File
import org.apache.daffodil.lib.api.DaffodilTunables
+import org.apache.daffodil.lib.api.WarnID
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.exceptions.UnsuppressableException
import org.apache.daffodil.lib.oolag.ErrorsNotYetRecorded
@@ -2369,4 +2370,6 @@ class DebuggerHost(override val tunable: DaffodilTunables)
def unqualifiedPathStepPolicy:
org.apache.daffodil.lib.api.UnqualifiedPathStepPolicy = ???
// Members declared in org.apache.daffodil.lib.exceptions.ThrowsSDE
def schemaFileLocation:
org.apache.daffodil.lib.exceptions.SchemaFileLocation = ???
+
+ override lazy val localSuppressSchemaDefinitionWarnings: Seq[WarnID] = Seq()
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
index c65c5bd88..0108e5f8a 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/SDE.scala
@@ -242,6 +242,7 @@ trait ImplementsThrowsSDE extends ThrowsSDE {
trait ImplementsThrowsOrSavesSDE extends ImplementsThrowsSDE with
SavesErrorsAndWarnings {
def tunable: DaffodilTunables
+ def localSuppressSchemaDefinitionWarnings: Seq[WarnID]
def error(th: Diagnostic): Unit
def warn(th: Diagnostic): Unit
@@ -256,7 +257,11 @@ trait ImplementsThrowsOrSavesSDE extends
ImplementsThrowsSDE with SavesErrorsAnd
* Issue a warning. The WarnID allows suppression of warning messages.
*/
def SDW(warnID: WarnID, fmt: String, args: Any*): Unit = {
- if (tunable.notSuppressedWarning(warnID)) {
+ val lssdw = localSuppressSchemaDefinitionWarnings
+ val tssdw = tunable.suppressSchemaDefinitionWarnings
+ val suppress = lssdw.contains(warnID) || lssdw.contains(WarnID.All) ||
+ tssdw.contains(warnID) || tssdw.contains(WarnID.All)
+ if (!suppress) {
val sdw = new SchemaDefinitionWarning(
warnID,
Some(schemaFileLocation),
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
index ba53c7069..8789b11e2 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/ProcessorStateBases.scala
@@ -566,8 +566,12 @@ abstract class ParseOrUnparseState protected (
}
final def SDW(warnID: WarnID, str: String, args: Any*) = {
- if (tunable.notSuppressedWarning(warnID)) {
- val ctxt = getContext()
+ val ctxt = getContext()
+ val lssdw = ctxt.localSuppressSchemaDefinitionWarnings
+ val tssdw = tunable.suppressSchemaDefinitionWarnings
+ val suppress = lssdw.contains(warnID) || lssdw.contains(WarnID.All) ||
+ tssdw.contains(warnID) || tssdw.contains(WarnID.All)
+ if (!suppress) {
val rsdw =
new RuntimeSchemaDefinitionWarning(warnID, ctxt.schemaFileLocation,
this, str, args: _*)
diagnostics = rsdw :: diagnostics
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala
index 9c38a6cc7..f1f2d7884 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/RuntimeData.scala
@@ -24,6 +24,7 @@ import scala.util.matching.Regex
import scala.xml.NamespaceBinding
import org.apache.daffodil.lib.Implicits.ImplicitsSuppressUnusedImportWarning
+import org.apache.daffodil.lib.api.WarnID
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.exceptions.HasSchemaFileLocation
import org.apache.daffodil.lib.exceptions.SchemaFileLocation
@@ -692,7 +693,8 @@ sealed class ElementRuntimeData(
maybeCheckByteAndBitOrderEvArg: Maybe[CheckByteAndBitOrderEv],
maybeCheckBitOrderAndCharsetEvArg: Maybe[CheckBitOrderAndCharsetEv],
val isQuasiElement: Boolean,
- val runtimeProperties: java.util.Map[String, String]
+ val runtimeProperties: java.util.Map[String, String],
+ val localSuppressSchemaDefinitionWarnings: Seq[WarnID]
) extends TermRuntimeData(
positionArg,
partialNextElementResolverDelay,
@@ -824,8 +826,9 @@ sealed abstract class ErrorERD(local: String, namespaceURI:
String)
null, // fillByteEvArg => FillByteEv
Nope, // maybeCheckByteAndBitOrderEvArg: => Maybe[CheckByteAndBitOrderEv],
Nope, // maybeCheckBitOrderAndCharsetEvArg: =>
Maybe[CheckBitOrderAndCharsetEv],
- false, // isQuasiElementArg: => Boolean
- null // runtimeProperties: java.util.Map[String,String]
+ false, // isQuasiElementArg: => Boolean,
+ null, // runtimeProperties: java.util.Map[String,String],
+ null // localSuppressSchemaDefinitionWarnings: Seq[WarnID]
) {
override def toString() =
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
index 045b98685..f8c0fedb1 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/SchemaDefinitionErrors.tdml
@@ -281,4 +281,31 @@
</tdml:parserTestCase>
+ <tdml:defineSchema name="warning_suppressed">
+ <xs:include
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+ <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited"
encoding="utf-8" representation="text"/>
+ <xs:element name="elem" type="xs:string"
daf:suppressSchemaDefinitionWarnings="appinfoDFDLSourceWrong">
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/dfdl-1.0/" />
+ </xs:annotation>
+ </xs:element>
+ </tdml:defineSchema>
+
+<!--
+ Test Name: schema_warning_locally_suppressed
+ Schema: warning
+ Root: elem
+ Purpose: This test demonstrates locally suppressed warnings
+-->
+
+ <tdml:parserTestCase name="schema_warning_locally_suppressed" root="elem"
+ model="warning_suppressed" ignoreUnexpectedWarnings="false">
+ <tdml:document><![CDATA[test]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <elem>test</elem>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
</tdml:testSuite>
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
index 4aaa08f89..e215b43a2 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section02/schema_definition_errors/TestSDE.scala
@@ -53,4 +53,8 @@ class TestSDE {
@Test def test_ignoreAttributeFormDefault(): Unit = {
runner.runOneTest("ignoreAttributeFormDefault")
}
+
+ @Test def test_schema_warning_locally_suppressed(): Unit = {
+ runner.runOneTest("schema_warning_locally_suppressed")
+ }
}