This is an automated email from the ASF dual-hosted git repository.
olabusayo 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 37edb3639 Remove uses of ReflectiveCalls from Code
37edb3639 is described below
commit 37edb363970d28eef7403e357a589012d2c6c616
Author: olabusayoT <[email protected]>
AuthorDate: Fri Mar 7 15:44:42 2025 -0500
Remove uses of ReflectiveCalls from Code
- remove need for reflection by using traits instead of structural typing
since scala 3 has a different import scala.reflect.Selectables... from scala
2.13 which uses scala.language.reflectiveCalls. Neither import exist in the
other version and are therefore incompatible, so the easiest approach was to
get rid of structural typing in lieu of traits.
- add comments for 2.12 phaseout
- remove JDOMUtils
DAFFODIL-2975
---
.../processors/charset/BitsCharsetDefinition.scala | 7 +-
.../scala/org/apache/daffodil/lib/Implicits.scala | 7 +-
.../org/apache/daffodil/lib/api/Validator.scala | 4 +-
.../scala/org/apache/daffodil/lib/util/Misc.scala | 4 +-
.../lib/util/SimpleNamedServiceLoader.scala | 5 +-
.../org/apache/daffodil/lib/xml/JDOMUtils.scala | 117 ---------------------
.../org/apache/daffodil/lib/xml/QNameBase.scala | 18 ----
.../lib/util/TestXMLCatalogAndValidate.scala | 16 +--
.../daffodil/lib/xml/test/unit/TestXMLUtils.scala | 8 --
.../runtime1/dsom/CompiledExpression1.scala | 27 ++++-
.../apache/daffodil/runtime1/layers/api/Layer.java | 3 +-
11 files changed, 43 insertions(+), 173 deletions(-)
diff --git
a/daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/BitsCharsetDefinition.scala
b/daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/BitsCharsetDefinition.scala
index c6af1fb95..f166ea1fc 100644
---
a/daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/BitsCharsetDefinition.scala
+++
b/daffodil-io/src/main/scala/org/apache/daffodil/io/processors/charset/BitsCharsetDefinition.scala
@@ -16,13 +16,18 @@
*/
package org.apache.daffodil.io.processors.charset
+import org.apache.daffodil.lib.util.SimpleNamedLoadableService
+
/**
* These are the classes which must be dynamically loaded in order to add a
charset implementation
* to Daffodil. All charsets must implement this class and be added to the
* org.apache.daffodil.runtime1.processors.charset.BitsCharsetDefinition file
in
* daffodil-io/src/main/resources/META-INF/services. name() must return a
fully capitalized string
*/
-abstract class BitsCharsetDefinition(charset: BitsCharset, alias:
Option[String] = None) {
+abstract class BitsCharsetDefinition(
+ charset: BitsCharset,
+ alias: Option[String] = None
+) extends SimpleNamedLoadableService {
final def name(): String = alias.getOrElse(charset.name).toUpperCase()
final def charset(): BitsCharset = charset
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/Implicits.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/Implicits.scala
index 4be562f6d..aed961ff8 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/Implicits.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/Implicits.scala
@@ -19,7 +19,6 @@ package org.apache.daffodil.lib
import java.io.{ BufferedInputStream, ByteArrayInputStream }
import scala.language.implicitConversions
-import scala.language.reflectiveCalls
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.lib.xml.NS
@@ -47,10 +46,10 @@ object Implicits {
/**
* Used for reading/writing to database, files, etc.
- * Code From the book "Beginning Scala"
- * http://www.amazon.com/Beginning-Scala-David-Pollak/dp/1430219890
+ * Code without reflection
+ * TODO: scala 2.12 Phaseout. Replace with scala.util.Using
*/
- def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
+ def using[A <: AutoCloseable, B](param: A)(f: A => B): B =
try { f(param) }
finally { param.close() }
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/api/Validator.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/api/Validator.scala
index da1b0c218..5730a300d 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/api/Validator.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/api/Validator.scala
@@ -17,6 +17,8 @@
package org.apache.daffodil.lib.api
+import org.apache.daffodil.lib.util.SimpleNamedLoadableService
+
import com.typesafe.config.Config
/**
@@ -35,7 +37,7 @@ trait Validator {
*
* The factory implementations are expected to be thread safe
*/
-trait ValidatorFactory {
+trait ValidatorFactory extends SimpleNamedLoadableService {
/**
* Unique name of this Validator service
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/Misc.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/Misc.scala
index 7679f0be2..46927224e 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/Misc.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/Misc.scala
@@ -638,11 +638,11 @@ object Misc {
}
}
- import scala.language.reflectiveCalls // scala 2.10 creates warning unless
we have this.
/**
* Convenient I/O tools
+ * TODO: scala 2.12 Phaseout. Replace with scala.util.Using
*/
- def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
+ def using[A <: AutoCloseable, B](param: A)(f: A => B): B =
try { f(param) }
finally { param.close() }
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/SimpleNamedServiceLoader.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/SimpleNamedServiceLoader.scala
index 24d6f6dbb..9324a79ea 100644
---
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/SimpleNamedServiceLoader.scala
+++
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/util/SimpleNamedServiceLoader.scala
@@ -19,7 +19,8 @@ package org.apache.daffodil.lib.util
import java.util.ServiceConfigurationError
import java.util.ServiceLoader
import scala.collection.mutable.ArrayBuffer
-import scala.language.reflectiveCalls
+
+trait SimpleNamedLoadableService { def name(): String }
/**
* Contains methods for dynamic loading of classes from the class path.
@@ -39,7 +40,7 @@ object SimpleNamedServiceLoader {
* It must have a name member returning a string. It must have a
default (no-arg) constructor.
* @return A map from the name (string) to the corresponding instance of the
class.
*/
- def loadClass[T <: { def name(): String }](clazz: Class[T]): Map[String, T]
= {
+ def loadClass[T <: SimpleNamedLoadableService](clazz: Class[T]): Map[String,
T] = {
val thingName = Misc.getNameGivenAClassObject(clazz)
val iter = ServiceLoader.load(clazz).iterator()
val instanceBuf = new ArrayBuffer[T]
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/JDOMUtils.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/JDOMUtils.scala
deleted file mode 100644
index e5f49e211..000000000
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/JDOMUtils.scala
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.daffodil.lib.xml
-
-import scala.xml._
-
-import org.apache.daffodil.lib.exceptions.Assert
-
-object JDOMUtils {
-
- val xsiNS = org.jdom2.Namespace.getNamespace("xsi",
XMLUtils.XSI_NAMESPACE.toString)
-
- import scala.language.reflectiveCalls // allows structural type - the def
toXML below.
-
- /**
- * JDOM is no longer our infoset, but we will still want to convert
- * into it for Java users who want JDOM.
- */
- def Infoset2JDOM(node: { def toXML: scala.xml.NodeSeq }) = {
- val scalaXML = node.toXML
- elem2Element(scalaXML)
- }
-
- def elem2Element(nodes: scala.xml.NodeSeq): Seq[org.jdom2.Element] =
nodes.map { elem =>
- elem2Element(elem)
- }
-
- def elem2Element(node: scala.xml.Node): org.jdom2.Element = {
- val jdomNode = new org.jdom2.Element(node.label, node.prefix,
node.namespace)
- val Elem(_, _, _, nsBinding: NamespaceBinding, _*) =
node.asInstanceOf[scala.xml.Elem]
-
- XMLUtils.namespaceBindings(nsBinding).foreach { ns =>
- {
- val prefix = ns.prefix
- if (
- prefix != null && prefix != ""
- && jdomNode.getNamespace(prefix) == null
- )
-
jdomNode.addNamespaceDeclaration(org.jdom2.Namespace.getNamespace(ns.prefix,
ns.uri))
- }
- }
-
- val attribsList = if (node.attributes == null) Null else node.attributes
-
- val attribs = attribsList.map { (attribute: MetaData) =>
- {
- val attrNS = attribute.getNamespace(node)
- val name = attribute.key
- val value = attribute.value.text
- val prefixedKey = attribute.prefixedKey
- val prefix = if (prefixedKey.contains(":")) prefixedKey.split(":")(0)
else ""
- val ns = (prefix, attrNS) match {
- //
- // to make our test cases less cluttered and more compact visually,
we're
- // going to specifically allow for an attribute named xsi:nil where
xsi prefix
- // is NOT defined.
- //
- case ("xsi", null) | ("xsi", "") => xsiNS
- case (_, null) | (_, "") => {
- Assert.invariantFailed(
- "attribute with prefix '%s', but no associated
namespace".format(prefix)
- )
- }
- case ("", uri) => org.jdom2.Namespace.getNamespace(uri)
- case (pre, uri) => org.jdom2.Namespace.getNamespace(pre, uri)
- }
-
- if (attribute.isPrefixed && attrNS != "") {
- new org.jdom2.Attribute(name, value, ns)
- } else
- new org.jdom2.Attribute(name, value)
- }
- }
- attribs.foreach { attrib => jdomNode.setAttribute(attrib) }
-
- for (child <- node.child) {
- child.label match {
- case "#PI" => // drop ProcInstrs
- // Note that for PCDATA and CDATA, we want to use child.text. If
- // instead we used child.toString, then we will get the escaped string
- // (e.g. apersands willbe &). The problem is that when we provide
- // these escape strings to jdom, jdom will escape them too, so &
- // would become &amp;, effectively double escaping strings. By
- // using child.text, we get the unescaped value, which jdom is then
- // free to escape.
- case "#PCDATA" => jdomNode.addContent(child.text)
- case "#CDATA" => jdomNode.addContent(new org.jdom2.CDATA(child.text))
- case "#REM" => // leave out comments
- case _ => jdomNode.addContent(elem2Element(child))
- }
- }
- jdomNode
- }
-
- def isNil(e: org.jdom2.Element) = {
- val nilAttr = e.getAttribute("nil", xsiNS)
- val res =
- if (nilAttr == null) false
- else nilAttr.getValue() == "true"
- res
- }
-}
diff --git
a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala
b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala
index b14b6047a..57e8e90d9 100644
--- a/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala
+++ b/daffodil-lib/src/main/scala/org/apache/daffodil/lib/xml/QNameBase.scala
@@ -19,7 +19,6 @@ package org.apache.daffodil.lib.xml
import java.net.URI
import java.net.URISyntaxException
-import scala.language.reflectiveCalls
import scala.util.Try
import org.apache.daffodil.lib.api.UnqualifiedPathStepPolicy
@@ -486,23 +485,6 @@ final case class StepQName(prefix: Option[String], local:
String, namespace: NS)
case _ => Assert.usageError("other must be a NamedQName")
}
}
-
- /**
- * Finds the matches in a list of things that have QNames.
- * Used for finding if a named path step has corresponding element
declaration.
- *
- * Handles local or global matches
- *
- */
- def findMatches[T <: { def namedQName: NamedQName }](candidates: Seq[T]):
Seq[T] = {
- val matched = candidates.filter { x =>
- val other = x.namedQName
- val res = matches(other)
- res
- }
- matched
- }
-
}
protected trait RefQNameFactoryBase[T] {
diff --git
a/daffodil-lib/src/test/scala/org/apache/daffodil/lib/util/TestXMLCatalogAndValidate.scala
b/daffodil-lib/src/test/scala/org/apache/daffodil/lib/util/TestXMLCatalogAndValidate.scala
index 04aa8eb09..892075fd9 100644
---
a/daffodil-lib/src/test/scala/org/apache/daffodil/lib/util/TestXMLCatalogAndValidate.scala
+++
b/daffodil-lib/src/test/scala/org/apache/daffodil/lib/util/TestXMLCatalogAndValidate.scala
@@ -20,7 +20,6 @@ package org.apache.daffodil.lib.util
import java.io.File
import javax.xml.XMLConstants
import javax.xml.parsers.SAXParser
-import scala.language.reflectiveCalls
import scala.xml.Attribute
import scala.xml.Elem
import scala.xml.MetaData
@@ -31,8 +30,8 @@ import scala.xml.SAXParseException
import scala.xml.Text
import scala.xml.parsing.NoBindingFactoryAdapter
+import org.apache.daffodil.lib.Implicits.using
import org.apache.daffodil.lib.exceptions.Assert
-import org.apache.daffodil.lib.util.Implicits.using
import org.apache.daffodil.lib.util.collections.Stack
import org.apache.daffodil.lib.xml.DaffodilSAXParserFactory
import org.apache.daffodil.lib.xml.NS
@@ -53,19 +52,6 @@ import org.xml.sax.InputSource
import org.xml.sax.XMLReader
import org.xml.sax.helpers.XMLFilterImpl
-object Implicits {
-
- /**
- * Used for reading/writing to database, files, etc.
- * Code From the book "Beginning Scala"
- * http://www.amazon.com/Beginning-Scala-David-Pollak/dp/1430219890
- */
- def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
- try { f(param) }
- finally { param.close() }
-
-}
-
/**
* The goal here is to integrate XML Catalog with XSD Validation, so that both
* the DFDL Schema references to other DFDL Schema namespaces would be
resolved via
diff --git
a/daffodil-lib/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
b/daffodil-lib/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
index c23dba738..748a40716 100644
---
a/daffodil-lib/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
+++
b/daffodil-lib/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
@@ -24,7 +24,6 @@ import java.nio.file.StandardOpenOption
import scala.xml._
import org.apache.daffodil.lib.util.Misc
-import org.apache.daffodil.lib.xml.JDOMUtils
import org.apache.daffodil.lib.xml.NS
import org.apache.daffodil.lib.xml.XMLUtils
@@ -159,13 +158,6 @@ class TestXMLUtils {
assertFalse(isSame)
}
- @Test def testIsNil(): Unit = {
- val d1 = JDOMUtils.elem2Element(<a xmlns:xsi={XMLUtils.XSI_NAMESPACE}
xsi:nil="true"/>)
- val d2 = JDOMUtils.elem2Element(<a
xmlns:xsi={XMLUtils.XSI_NAMESPACE}>foo</a>)
- assertTrue(JDOMUtils.isNil(d1))
- assertFalse(JDOMUtils.isNil(d2))
- }
-
@Test def testWalkUnicodeString1(): Unit = {
val s = "abc"
val Seq((ab, 'a', 'b'), ('a', 'b', 'c'), ('b', 'c', ca)) =
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/CompiledExpression1.scala
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/CompiledExpression1.scala
index 7d5323210..162d50757 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/CompiledExpression1.scala
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dsom/CompiledExpression1.scala
@@ -459,12 +459,31 @@ class DPathElementCompileInfo(
matches(0)
}
+ /**
+ * Finds the matches in a list of DPathElementCompileInfo.
+ * Used for finding if a named path step has corresponding element
declaration.
+ *
+ * Handles local or global matches
+ *
+ */
+ def findMatches(
+ step: StepQName,
+ candidates: Seq[DPathElementCompileInfo]
+ ): Seq[DPathElementCompileInfo] = {
+ val matched = candidates.filter { x =>
+ val other = x.namedQName
+ val res = step.matches(other)
+ res
+ }
+ matched
+ }
+
private def findNamedMatches(
step: StepQName,
possibles: Seq[DPathElementCompileInfo],
expr: ImplementsThrowsOrSavesSDE
): Seq[DPathElementCompileInfo] = {
- val matchesERD: Seq[DPathElementCompileInfo] = step.findMatches(possibles)
+ val matchesERD: Seq[DPathElementCompileInfo] = findMatches(step, possibles)
val retryMatchesERD =
if (
@@ -476,7 +495,7 @@ class DPathElementCompileInfo(
// default namespace was assumed but didn't match, the unqualified path
// step policy allows us to try to match NoNamespace elements.
val noNamespaceStep = step.copy(namespace = NoNamespace)
- noNamespaceStep.findMatches(possibles)
+ findMatches(noNamespaceStep, possibles)
} else {
matchesERD
}
@@ -493,7 +512,7 @@ class DPathElementCompileInfo(
step: StepQName,
possibles: Seq[DPathElementCompileInfo]
): Seq[DPathElementCompileInfo] = {
- val matchesERD = step.findMatches(possibles)
+ val matchesERD = findMatches(step, possibles)
val retryMatchesERD =
if (
matchesERD.isEmpty &&
@@ -504,7 +523,7 @@ class DPathElementCompileInfo(
// default namespace was assumed but didn't match, the unqualified path
// step policy allows us to try to match NoNamespace elements.
val noNamespaceStep = step.copy(namespace = NoNamespace)
- noNamespaceStep.findMatches(possibles)
+ findMatches(noNamespaceStep, possibles)
} else {
matchesERD
}
diff --git
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/layers/api/Layer.java
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/layers/api/Layer.java
index 395d20def..5a3cedfd2 100644
---
a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/layers/api/Layer.java
+++
b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/layers/api/Layer.java
@@ -16,6 +16,7 @@
*/
package org.apache.daffodil.runtime1.layers.api;
+import org.apache.daffodil.lib.util.SimpleNamedLoadableService;
import org.apache.daffodil.runtime1.layers.LayerRuntime;
import org.apache.daffodil.runtime1.layers.LayerUtils;
@@ -257,7 +258,7 @@ import java.util.List;
* <p>
* Unhandled exceptions thrown by the layer code are treated as fatal errors.
*/
-public abstract class Layer {
+public abstract class Layer implements SimpleNamedLoadableService {
private final String localName;
private final String targetNamespace;