in src/main/scala/org/apache/daffodil/DaffodilSaver.scala [41:159]
def main(args: Array[String]): Unit = {
assert(
args.length == 5,
"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 = args(0).toInt
val schemaResource = args(1)
val schemaUrl = this.getClass.getResource(schemaResource)
if (schemaUrl == null) {
System.err.println(s"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) != "") args(3) else null
val config = if (args(4) != "") args(4) else null
// parameter types
val cURI = classOf[URI]
val cString = classOf[String]
val cWritableByteChannel = classOf[WritableByteChannel]
// get the Compiler, ProcessorFactory, and DataProcessor classes and the functions we need
// to invoke on those classes. Note that we use JAPI because its easier to use via
// reflection than the Scala API and it is much smaller and easier to use then the lib API
val daffodilClass = Class.forName("org.apache.daffodil.japi.Daffodil")
val daffodilCompiler = daffodilClass.getMethod("compiler")
val compilerClass = Class.forName("org.apache.daffodil.japi.Compiler")
val compilerWithTunable = compilerClass.getMethod("withTunable", cString, cString)
// the compileResource method added in Daffodil 3.9.0 allows for depersonalized diagnostics
// and better reproducibility of saved parsers--use it instead of compileSource for newer
// versions of Daffodil
val compilerCompile = apiVersion match {
case 1 => compilerClass.getMethod("compileSource", cURI, cString, cString)
case 2 => compilerClass.getMethod("compileResource", cString, cString, cString)
}
val processorFactoryClass = Class.forName("org.apache.daffodil.japi.ProcessorFactory")
val processorFactoryIsError = processorFactoryClass.getMethod("isError")
val processorFactoryOnPath = processorFactoryClass.getMethod("onPath", cString)
val processorFactoryGetDiagnostics = processorFactoryClass.getMethod("getDiagnostics")
val dataProcessorClass = Class.forName("org.apache.daffodil.japi.DataProcessor")
val dataProcessorIsError = dataProcessorClass.getMethod("isError")
val dataProcessorSave = dataProcessorClass.getMethod("save", cWritableByteChannel)
val dataProcessorGetDiagnostics = processorFactoryClass.getMethod("getDiagnostics")
val diagnosticClass = Class.forName("org.apache.daffodil.japi.Diagnostic")
val diagnosticIsError = diagnosticClass.getMethod("isError")
val diagnosticToString = diagnosticClass.getMethod("toString")
def printDiagnostics(diags: java.util.List[Object]): Unit = {
diags.asScala.foreach { d =>
// val msg = d.toString
val msg = diagnosticToString.invoke(d).asInstanceOf[String]
// val isError = d.isError
val isError = diagnosticIsError.invoke(d).asInstanceOf[Boolean]
val level = if (isError) "error" else "warning"
System.err.println(s"[$level] $msg")
}
}
// val compiler = Daffodil.compiler()
var compiler = daffodilCompiler.invoke(null)
// compiler = compiler.withTunable(...)
if (config != null) {
val configXml = scala.xml.Utility.trim(scala.xml.XML.loadFile(config))
(configXml \ "tunables").foreach { tunablesNode =>
tunablesNode.child.foreach { node =>
compiler = compilerWithTunable.invoke(compiler, node.label, node.text)
}
}
}
// val processorFactory = compiler.compileSource(schemaUrl.toURI, root, None) // < 3.9.0
// val processorFactory = compiler.compileResource(name, root, None) // >= 3.9.0
val schemaArg = apiVersion match {
case 1 => schemaUrl.toURI
case 2 => schemaResource
}
val processorFactory = compilerCompile.invoke(compiler, schemaArg, root, null)
// val processorFactoryDiags = processorFactory.getDiagnostics()
val processorFactoryDiags = processorFactoryGetDiagnostics
.invoke(processorFactory)
.asInstanceOf[java.util.List[Object]]
printDiagnostics(processorFactoryDiags)
// if (processorFactory.isError) System.exit(1)
if (processorFactoryIsError.invoke(processorFactory).asInstanceOf[Boolean]) System.exit(1)
// val dataProcessor= processorFactory.onPath("/")
val dataProcessor = processorFactoryOnPath.invoke(processorFactory, "/")
// val dataProcessorDiags = dataProcessor.getDiagnostics()
val dataProcessorDiags = dataProcessorGetDiagnostics
.invoke(dataProcessor)
.asInstanceOf[java.util.List[Object]]
printDiagnostics(dataProcessorDiags)
// if (dataProcessor.isError) System.exit(1)
if (dataProcessorIsError.invoke(dataProcessor).asInstanceOf[Boolean]) System.exit(1)
// dataProcessor.save(output)
dataProcessorSave.invoke(dataProcessor, output)
System.exit(0)
}