stevedlawrence commented on code in PR #136: URL: https://github.com/apache/daffodil-sbt/pull/136#discussion_r2518665594
########## utils/src/main/scala/org/apache/daffodil/DaffodilSaver.scala: ########## @@ -0,0 +1,119 @@ +/* + * 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 + +import java.nio.channels.FileChannel +import java.nio.file.Paths +import java.nio.file.StandardOpenOption +import scala.jdk.CollectionConverters._ + +// When creating saved parsers using packageDaffodilBin, we need to create a saved parser for a +// different version of Daffodil than is added to libraryDependencies. For this reason, we have +// this DaffodilSaver class, which can be forked with a Different versionof Daffodil on the +// classpath. Note that we use sbt-projectmatrix to compile this class into three separate jars +// for each version of Scala/Daffodil (Scala 2.12 is used for Daffodil 3.10.0 and older, Scala +// 2.13 is used for Daffodil 3.11.0, and Scala 3.x is used for Daffodil 4.0.0 and newer. WWe +// expect the sbt plugin to set up the classpath to include the correct jar for the version of +// Daffodil being used when forking this class. +object DaffodilSaver { + + /** + * Usage: daffodilSaver <apiVersion> <schemaResource> <outputFile> <root> <config> + * + * If <root> or <config> is unknown/not-provided, they must be the empty string + */ + def main(args: Array[String]): Unit = { + try { + run(args) + } catch { + case e: Exception => { + e.printStackTrace() + System.exit(1) + } + } + } + + private def run(args: Array[String]): Unit = { + + if (args.length != 5) { + throw new Exception( + "DaffodilPlugin did not provide the correct number of arguments when forking DaffodilSaver" + ) + } + + // the "version" of the Daffodil API to use. Note that this is not the same as the Daffodil + // version, but is related. See the "daffodilInternalAPIVersionMapping" in the plugin code + // for an explanation of why we have this and what version of Daffodil it represents. + val apiVersion = Integer.parseInt(args(0)) + + val schemaResource = args(1) + val schemaUrl = this.getClass.getResource(schemaResource) + if (schemaUrl == null) { + System.err.println("failed to find schema resource: " + schemaResource) + System.exit(1) + } + + val output = + FileChannel.open(Paths.get(args(2)), StandardOpenOption.CREATE, StandardOpenOption.WRITE) + val root = if (!args(3).isEmpty()) args(3) else null + val config = if (!args(4).isEmpty()) args(4) else null + + val tunables = + if (config != null) { + val configXml = scala.xml.Utility.trim(scala.xml.XML.loadFile(config)) + (configXml \ "tunables").flatMap { tunablesNode => + tunablesNode.child.map { node => (node.label, node.text) } + }.toMap + } else { + Map.empty[String, String] + } + val jTunables = new java.util.HashMap[String, String](tunables.asJava) + + val compiler = DaffodilAPI + .compiler() + .withTunables(jTunables) + + val processorFactory = apiVersion match { Review Comment: I actually started down this approach and in this specific case it felt like it actually made things more complex without a whole lot of gain. The DaffodilAPI classes a became complex and more different from one another (it's nice to keep this shim class as small as possible), and all it really got rid of was this one small conditional. I think as sbt-daffodil-utils grows in complexity it's very possible we'll need something like what you describe, but I lean towards holding off on that change until we really need it so we can keep things a simple as possible for now. For reference here's the diff to move the logic to the DaffodilAPI class: ```diff diff --git a/utils/src/main/scala-2/org/apache/daffodil/DaffodilAPI.scala b/utils/src/main/scala-2/org/apache/daffodil/DaffodilAPI.scala index 057bd9b..f9c0e64 100644 --- a/utils/src/main/scala-2/org/apache/daffodil/DaffodilAPI.scala +++ b/utils/src/main/scala-2/org/apache/daffodil/DaffodilAPI.scala @@ -22,7 +22,20 @@ package org.apache.daffodil * compatability with Scala 2.x and Daffodil 3.x */ object DaffodilAPI { + type Compiler = org.apache.daffodil.japi.Compiler type Diagnostic = org.apache.daffodil.japi.Diagnostic def compiler() = org.apache.daffodil.japi.Daffodil.compiler() + + def compileResource(compiler: Compiler, resource: String, root: String, apiVersion: Int) = { + apiVersion match { + case 1 => { + val schemaUrl = this.getClass.getResource(resource) + compiler.compileSource(schemaUrl.toURI, root, null) + } + case 2 => { + compiler.compileResource(resource, root, null) + } + } + } } diff --git a/utils/src/main/scala-3/org/apache/daffodil/DaffodilAPI.scala b/utils/src/main/scala-3/org/apache/daffodil/DaffodilAPI.scala index 05c1c69..1ff59a3 100644 --- a/utils/src/main/scala-3/org/apache/daffodil/DaffodilAPI.scala +++ b/utils/src/main/scala-3/org/apache/daffodil/DaffodilAPI.scala @@ -23,6 +23,11 @@ package org.apache.daffodil */ object DaffodilAPI { type Diagnostic = org.apache.daffodil.api.Diagnostic + type Compiler = org.apache.daffodil.api.Compiler def compiler() = org.apache.daffodil.api.Daffodil.compiler() + + def compileResource(compiler: Compiler, resource: String, root: String, apiVersion: Int) = { + compiler.compileResource(resource, root, null) + } } diff --git a/utils/src/main/scala/org/apache/daffodil/DaffodilSaver.scala b/utils/src/main/scala/org/apache/daffodil/DaffodilSaver.scala index 3c66173..be17017 100644 --- a/utils/src/main/scala/org/apache/daffodil/DaffodilSaver.scala +++ b/utils/src/main/scala/org/apache/daffodil/DaffodilSaver.scala @@ -88,10 +88,8 @@ object DaffodilSaver { .compiler() .withTunables(jTunables) - val processorFactory = apiVersion match { - case 1 => compiler.compileSource(schemaUrl.toURI, root, null) - case 2 => compiler.compileResource(schemaResource, root, null) - } + val processorFactory = + DaffodilAPI.compileResource(compiler, schemaResource, root, apiVersion) if (processorFactory.isError()) { printDiagnostics(processorFactory.getDiagnostics.asScala.toSeq) System.exit(1) ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
