-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
Enables systems that want to interface tightly with Daffodil via JAPI, to walk the runtime schema information so as to construct their own corresponding metadata. DAFFODIL-2832
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package org.apache.daffodil.japi.schema | ||
|
||
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, | ||
} | ||
|
||
/** | ||
* Base class used by japi clients who want to walk the runtime schema information. | ||
*/ | ||
abstract class RuntimeSchemaHandler() { | ||
|
||
/** | ||
* 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( | ||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L66
|
||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L71
|
||
} | ||
|
||
private def walkTerm(handler: RuntimeSchemaHandler, trd: TermRuntimeData): Unit = { | ||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L76-L80
|
||
} | ||
} | ||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L85-L86
|
||
else | ||
walkSimpleElement(handler, erd) | ||
Check warning on line 88 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L88
|
||
} | ||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L95-L99
|
||
} | ||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L101-L103
|
||
} | ||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L110-L114
|
||
} | ||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L116
|
||
} | ||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L120-L122
|
||
} | ||
handler.endSequence() | ||
Check warning on line 124 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L124
|
||
} | ||
|
||
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 Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L128-L130
|
||
} | ||
handler.endChoice() | ||
Check warning on line 132 in daffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala Codecov / codecov/patchdaffodil-japi/src/main/scala/org/apache/daffodil/japi/schema/RuntimeSchemaWalker.scala#L132
|
||
} | ||
|
||
} |