Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Metadata walker for JAPI #1092

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,49 +22,36 @@
import java.nio.channels.ReadableByteChannel
import java.nio.channels.WritableByteChannel
import scala.collection.JavaConverters._

import org.apache.daffodil.core.compiler.{ Compiler => SCompiler }
import org.apache.daffodil.core.compiler.{ InvalidParserException => SInvalidParserException }
import org.apache.daffodil.core.compiler.{ ProcessorFactory => SProcessorFactory }
import org.apache.daffodil.core.compiler.{Compiler => SCompiler}
import org.apache.daffodil.core.compiler.{InvalidParserException => SInvalidParserException}
import org.apache.daffodil.core.compiler.{ProcessorFactory => SProcessorFactory}
import org.apache.daffodil.core.dsom.ExpressionCompilers
import org.apache.daffodil.core.dsom.walker.RootView
import org.apache.daffodil.japi.debugger._
import org.apache.daffodil.japi.infoset._
import org.apache.daffodil.japi.io.InputSourceDataInputStream
import org.apache.daffodil.japi.packageprivate._
import org.apache.daffodil.japi.schema.{RuntimeSchemaHandler, RuntimeSchemaWalker}
import org.apache.daffodil.lib.api.URISchemaSource
import org.apache.daffodil.lib.api.Validator
import org.apache.daffodil.lib.api.{ DataLocation => SDataLocation }
import org.apache.daffodil.lib.api.{ Diagnostic => SDiagnostic }
import org.apache.daffodil.lib.api.{ LocationInSchemaFile => SLocationInSchemaFile }
import org.apache.daffodil.lib.api.{ WithDiagnostics => SWithDiagnostics }
import org.apache.daffodil.lib.api.{DataLocation => SDataLocation}
import org.apache.daffodil.lib.api.{Diagnostic => SDiagnostic}
import org.apache.daffodil.lib.api.{LocationInSchemaFile => SLocationInSchemaFile}
import org.apache.daffodil.lib.api.{WithDiagnostics => SWithDiagnostics}
import org.apache.daffodil.lib.xml.DFDLCatalogResolver
import org.apache.daffodil.lib.xml.XMLUtils
import org.apache.daffodil.runtime1.api.DFDL.{
DaffodilUnhandledSAXException => SDaffodilUnhandledSAXException,
}
import org.apache.daffodil.runtime1.api.DFDL.{
DaffodilUnparseContentHandler => SDaffodilUnparseContentHandler,
}
import org.apache.daffodil.runtime1.api.DFDL.{
DaffodilUnparseErrorSAXException => SDaffodilUnparseErrorSAXException,
}
import org.apache.daffodil.runtime1.api.DFDL.{DaffodilUnhandledSAXException => SDaffodilUnhandledSAXException}
import org.apache.daffodil.runtime1.api.DFDL.{DaffodilUnparseContentHandler => SDaffodilUnparseContentHandler}
import org.apache.daffodil.runtime1.api.DFDL.{DaffodilUnparseErrorSAXException => SDaffodilUnparseErrorSAXException}
import org.apache.daffodil.runtime1.debugger.Debugger
import org.apache.daffodil.runtime1.debugger.{ InteractiveDebugger => SInteractiveDebugger }
import org.apache.daffodil.runtime1.debugger.{ TraceDebuggerRunner => STraceDebuggerRunner }
import org.apache.daffodil.runtime1.processors.{
DaffodilParseXMLReader => SDaffodilParseXMLReader,
}
import org.apache.daffodil.runtime1.processors.{ DataProcessor => SDataProcessor }
import org.apache.daffodil.runtime1.processors.{
ExternalVariableException => SExternalVariableException,
}
import org.apache.daffodil.runtime1.processors.{
InvalidUsageException => SInvalidUsageException,
}
import org.apache.daffodil.runtime1.processors.{ ParseResult => SParseResult }
import org.apache.daffodil.runtime1.processors.{ UnparseResult => SUnparseResult }

import org.apache.daffodil.runtime1.debugger.{InteractiveDebugger => SInteractiveDebugger}
import org.apache.daffodil.runtime1.debugger.{TraceDebuggerRunner => STraceDebuggerRunner}
import org.apache.daffodil.runtime1.processors.{DaffodilParseXMLReader => SDaffodilParseXMLReader}
import org.apache.daffodil.runtime1.processors.{DataProcessor => SDataProcessor}
import org.apache.daffodil.runtime1.processors.{ExternalVariableException => SExternalVariableException}
import org.apache.daffodil.runtime1.processors.{InvalidUsageException => SInvalidUsageException}
import org.apache.daffodil.runtime1.processors.{ParseResult => SParseResult}
import org.apache.daffodil.runtime1.processors.{UnparseResult => SUnparseResult}
import org.xml.sax.Attributes
import org.xml.sax.ContentHandler
import org.xml.sax.DTDHandler
Expand Down Expand Up @@ -401,6 +388,12 @@
extends WithDiagnostics(dp)
with Serializable {

/**
* For use by the JAPI implementation only.
* @return the underlying data processor
*/
private [japi] def getUnderlyingDataProcessor = dp

Check warning on line 395 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala#L395

Added line #L395 was not covered by tests
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved

private def copy(dp: SDataProcessor = dp) = new DataProcessor(dp)

/**
Expand Down Expand Up @@ -514,6 +507,11 @@
*/
def save(output: WritableByteChannel): Unit = dp.save(output)

def walkRuntimeSchema(handler: RuntimeSchemaHandler): Unit = {
val walker = new RuntimeSchemaWalker(dp)
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved
walker.walk(handler)

Check warning on line 512 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/Daffodil.scala#L511-L512

Added lines #L511 - L512 were not covered by tests
}

/**
* Obtain a new [[DaffodilParseXMLReader]] from the current [[DataProcessor]].
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.apache.daffodil.japi.schema
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved

import org.apache.daffodil.japi.{ DataProcessor => JDataProcessor }
import org.apache.daffodil.lib.exceptions.Assert
import org.apache.daffodil.runtime1.dpath.NodeInfo.PrimType
import org.apache.daffodil.runtime1.processors.{
ChoiceRuntimeData,
DataProcessor => SDataProcessor,
ElementRuntimeData,
ErrorERD,
SequenceRuntimeData,
TermRuntimeData,
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Base class used by japi clients who want to walk the runtime schema information.
*/
abstract class RuntimeSchemaHandler() {
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved

/**
* Called for simple type element declarations.
*
* @param qnameString
* @param primTypeName
* @param isArray only true if more than one occurrence is possible. Disjoint with isOptional
* @param isOptional true if 0 or 1 occurrence only. Allows for a different representation of optional from a 0..1 array
*/
def elementSimple(
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved
qnameString: String,
primTypeName: String,
isArray: Boolean,
isOptional: Boolean,
): Unit

/**
* Called for complex type element declarations
*
* Subsequent calls will be for the model group making up the content
* of the element.
*
* @param qnameString
*/
def startElementComplex(qnameString: String, isArray: Boolean, isOptional: Boolean): Unit
def endElementComplex(qnameString: String, isArray: Boolean, isOptional: Boolean): Unit

def startSequence(): Unit

def endSequence(): Unit

def startChoice(): Unit

def endChoice(): Unit

}

/**
* Walks the schema, but not the DSOM schema, it walks the RuntimeData objects that
* represent the DFDL schema at runtime.
*
* @param dp
*/
class RuntimeSchemaWalker(private val dp: SDataProcessor) {

// provided so that people can write various tests from JAPI only.
// we wouldn't need this otherwise.
def this(jdp: JDataProcessor) = this(jdp.getUnderlyingDataProcessor)

Check warning on line 66 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L66

Added line #L66 was not covered by tests

private lazy val rootERD = dp.ssrd.elementRuntimeData

def walk(handler: RuntimeSchemaHandler): Unit = {
walkTerm(handler, rootERD)

Check warning on line 71 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L71

Added line #L71 was not covered by tests
}

private def walkTerm(handler: RuntimeSchemaHandler, trd: TermRuntimeData): Unit = {
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved
trd match {
case err: ErrorERD => Assert.invariantFailed("should not get ErrorERDs")
case erd: ElementRuntimeData => walkElement(handler, erd)
case srd: SequenceRuntimeData => walkSequence(handler, srd)
case crd: ChoiceRuntimeData => walkChoice(handler, crd)
case _ => Assert.invariantFailed(s"unrecognized TermRuntimeData subtype: $trd")

Check warning on line 80 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L76-L80

Added lines #L76 - L80 were not covered by tests
}
}

private def walkElement(handler: RuntimeSchemaHandler, erd: ElementRuntimeData): Unit = {
if (erd.optComplexTypeModelGroupRuntimeData.isDefined)
walkComplexElement(handler, erd)

Check warning on line 86 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L85-L86

Added lines #L85 - L86 were not covered by tests
else
walkSimpleElement(handler, erd)

Check warning on line 88 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L88

Added line #L88 was not covered by tests
}

private def walkComplexElement(
handler: RuntimeSchemaHandler,
erd: ElementRuntimeData,
): Unit = {
val qname = erd.namedQName.toQNameString
val isArray = erd.isArray
val isOptional = erd.isOptional
val mgrd = erd.optComplexTypeModelGroupRuntimeData.getOrElse {
Assert.invariantFailed("not a complex type element")

Check warning on line 99 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L95-L99

Added lines #L95 - L99 were not covered by tests
}
handler.startElementComplex(qname, isArray, isOptional)
walkTerm(handler, mgrd)
handler.endElementComplex(qname, isArray, isOptional)

Check warning on line 103 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L101-L103

Added lines #L101 - L103 were not covered by tests
}

private def walkSimpleElement(
handler: RuntimeSchemaHandler,
erd: ElementRuntimeData,
): Unit = {
val qname = erd.namedQName.toQNameString
val isArray = erd.isArray
val isOptional = erd.isOptional
val primType: PrimType = erd.optPrimType.getOrElse {
erd.optSimpleTypeRuntimeData.map { _.primType }.get

Check warning on line 114 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L110-L114

Added lines #L110 - L114 were not covered by tests
}
handler.elementSimple(qname, primType.toString, isArray, isOptional)

Check warning on line 116 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L116

Added line #L116 was not covered by tests
}

private def walkSequence(handler: RuntimeSchemaHandler, srd: SequenceRuntimeData): Unit = {
handler.startSequence()
srd.groupMembers.map { trd =>
walkTerm(handler, trd)

Check warning on line 122 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L120-L122

Added lines #L120 - L122 were not covered by tests
}
handler.endSequence()

Check warning on line 124 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L124

Added line #L124 was not covered by tests
}

private def walkChoice(handler: RuntimeSchemaHandler, crd: ChoiceRuntimeData): Unit = {
handler.startChoice()
crd.groupMembers.map { trd =>
walkTerm(handler, trd)

Check warning on line 130 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L128-L130

Added lines #L128 - L130 were not covered by tests
}
handler.endChoice()

Check warning on line 132 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L132

Added line #L132 was not covered by tests
}
mbeckerle marked this conversation as resolved.
Show resolved Hide resolved

}
Loading