Skip to content

Commit

Permalink
Provide scalaxb bindings for TDML schema.
Browse files Browse the repository at this point in the history
  • Loading branch information
arosien committed Feb 8, 2024
1 parent da3cc9f commit c4ff24b
Show file tree
Hide file tree
Showing 5 changed files with 365 additions and 301 deletions.
12 changes: 12 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ lazy val sapi = Project("daffodil-sapi", file("daffodil-sapi"))

lazy val tdmlLib = Project("daffodil-tdml-lib", file("daffodil-tdml-lib"))
.dependsOn(macroLib % "compile-internal", lib, io, io % "test->test", slf4jLogger % "test")
.enablePlugins(ScalaxbPlugin)
.settings(commonSettings)
.settings(scalaxbSettings)

lazy val tdmlProc = Project("daffodil-tdml-processor", file("daffodil-tdml-processor"))
.dependsOn(tdmlLib, codeGenC, core, slf4jLogger)
Expand Down Expand Up @@ -211,6 +213,16 @@ lazy val testStdLayout = Project("daffodil-test-stdLayout", file("test-stdLayout
.dependsOn(tdmlProc % "test")
.settings(commonSettings, nopublish)

lazy val scalaxbSettings = Seq(
Compile / scalaxb / scalaxbGenerateMutable := true,
// Even though we don't generate any http clients, we need this to avoid an unused import error in the generated code.
Compile / scalaxb / scalaxbHttpClientStyle := HttpClientStyle.Sync,
Compile / scalaxb / scalaxbPackageName := "org.apache.daffodil.tdml.scalaxb",
Compile / scalaxb / sources := Seq(
(lib / Compile / resourceDirectory).value / "org/apache/daffodil/xsd/tdml-core.xsd",
),
)

// Choices here are Java LTS versions, 8, 11, 17, 21,...
// However 8 is deprecated as of Java 21, so will be phased out.
val minSupportedJavaVersion: String =
Expand Down
325 changes: 325 additions & 0 deletions daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml-core.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.ibm.com/xmlns/dfdl/testData"
xmlns:tns="http://www.ibm.com/xmlns/dfdl/testData"
elementFormDefault="unqualified"
xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<xs:attribute name="tutorialInclude" type="xs:string" fixed="no"/>

<!--
This element's type is a stub that satisfies the need for xhtml5 validation as part of TDML files.
It is just a wildcard with skip validation in it. So it's not really validating anything.
Users of TDML creating tutorials should paste in known-correct xhtml5 as the contents of the
tutorial elements.
-->
<xs:element name="tutorial" substitutionGroup="tns:testSuiteChoices">
<xs:complexType mixed="true">
<xs:sequence>
<xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="skip"/>
</xs:complexType>
</xs:element>

<!-- IBM uses this namespace http://www.ibm.com/xmlns/dfdl/testData -->
<element name="testSuiteChoices" abstract="true"/>

<element name="testSuite">
<complexType>
<sequence>
<xsd:element minOccurs="0" maxOccurs="unbounded" ref="tns:testSuiteChoices"></xsd:element>
</sequence>
<attribute name="suiteName" type="xs:token" use="optional"/>
<attribute name="ID" type="xs:token" use="optional"/>
<attribute name="description" type="xs:string" use="optional"/>
<attribute name="defaultRoundTrip" type="tns:roundTripType" use="optional"/>
<attribute name="defaultValidation" type="tns:validationType" use="optional"/>
<attribute name="defaultConfig" type="xs:string" use="optional"/>
<attribute name="defaultImplementations" type="tns:implementationsType" use="optional"/>
</complexType>
<unique name="unique-parserTestCase-name">
<selector xpath="parserTestCase"/>
<field xpath="@name"/>
</unique>
<unique name="unique-unparserTestCase-name">
<selector xpath="unparserTestCase"/>
<field xpath="@name"/>
</unique>
<!-- These two constraints only apply to tdml.xsd, but because the element is defined here,
these also need to be defined here, despite not having any affect when used by this file. -->
<unique name="unique-embeddedSchema-name">
<selector xpath="defineSchema"/>
<field xpath="@name"/>
</unique>
<unique name="unique-embeddedConfig-name">
<selector xpath="defineConfig"/>
<field xpath="@name"/>
</unique>
</element>

<simpleType name="implementationsType">
<list itemType="tns:implementationItem"/>
</simpleType>

<simpleType name="implementationItem">
<restriction base="xs:token">
<enumeration value="daffodil"/>
<enumeration value="daffodilC"/>
<enumeration value="ibm"/>
</restriction>
</simpleType>

<!-- We want to allow an xsd:schema to be named and directly embedded in
the TDML thereby allowing a fully-self-contained single file test case as
an exchange medium for tests. -->


<element name="parserTestCase" type="tns:parserTestCaseType" substitutionGroup="tns:testSuiteChoices"/>
<complexType name="parserTestCaseType">
<choice minOccurs="2" maxOccurs="11">
<!-- we can't enforce the cardinality in XSD 1.0 -->
<element ref="tns:tutorial"/>
<element ref="tns:document"/>
<element ref="tns:infoset"/>
<element ref="tns:errors"/>
<element ref="tns:warnings" minOccurs='0'/>
<element ref="tns:validationErrors" minOccurs="0"/>
</choice>
<attributeGroup ref="tns:testCaseAttribs"/>
</complexType>

<attributeGroup name="testCaseAttribs">
<attribute name="name" type="xs:NCName" use="required"/>
<attribute name="ID" type="xs:token" use="optional"/>
<attribute name="root" type="xs:NCName" use="optional"/> <!-- only needed when there is no infoset. -->
<attribute name="rootNS" type="xs:string" use="optional"/> <!-- only needed when there is no infoset. -->
<attribute name="model" type="xs:string" use="optional"/> <!-- is there a type for a path/uri? -->
<attribute name="config" type="xs:string" use="optional"/> <!-- is there a type for a path/uri? -->
<attribute name="roundTrip" type="tns:roundTripType" use="optional"/>
<attribute name="description" type="xs:string" use="optional"/>
<attribute name="unsupported" type="xs:boolean" use="optional" default="false"/>
<attribute name="validation" type="tns:validationType" use="optional"/>
<attribute name="implementations" type="tns:implementationsType" use="optional"/>
<attribute name="diagnosticsStripLocationInfo" type="xs:boolean" use="optional" default="true">
<annotation>
<documentation>We strip the file info from the diagnostics to prevent false
positive matches against the test case's error and warning strings
coming from file/dir names.

As there are tests that look for correct file/dir names, those
tests will need to NOT strip them and can do so by setting the
test flag to false.

This is only for purposes of comparing error/warning strings
to the diagnostic messages. Users would always see, displayed,
the full diagnostic messages.</documentation>
</annotation>
</attribute>

</attributeGroup>

<simpleType name="roundTripType">
<restriction base="xs:token">
<enumeration value="false"/> <!-- means same as none -->
<enumeration value="true"/> <!-- means same as onePass -->
<!--
parse only - compare infoset.
-->
<enumeration value="none"/>
<!--
parse, compare infoset, unparse - compare data
-->
<enumeration value="onePass"/>
<!--
parse, unparse, reparse - compare infoset.
Note that this can mask certain errors. So must be used with caution.
-->
<enumeration value="twoPass"/>
<!--
parse, unparse, reparse, reunparse, compare data.
Note that this can mask many kinds of errors very easily, so must be used
rarely and with caution.
-->
<enumeration value="threePass"/>
</restriction>
</simpleType>

<simpleType name="elementFormDefaultType">
<restriction base="xs:token">
<enumeration value="qualified"/>
<enumeration value="unqualified"/>
</restriction>
</simpleType>

<simpleType name="validationType">
<restriction base="xs:token">
<enumeration value="on"/>
<enumeration value="limited"/>
<enumeration value="off"/>
</restriction>
</simpleType>

<element name="document" type="tns:documentType"/>
<element name="infoset" type="tns:infosetType"/>
<element name="errors" type="tns:errorsType"/>
<element name="warnings" type="tns:warningsType"/>
<element name="validationErrors" type="tns:validationErrorsType"/>

<complexType name="documentType" mixed="true">
<sequence>
<element ref="tns:documentPart" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="bitOrder" type="tns:bitOrderEnum" use="optional"/>
<attribute ref="tns:tutorialInclude"/>
</complexType>

<element name="documentPart" type="tns:documentPartType"/>
<complexType name="documentPartType">
<simpleContent>
<extension base="xs:string">
<attribute name="type" type="tns:documentPartTypeEnum" use="required"/>
<attribute name="replaceDFDLEntities" type="xs:boolean"/>
<attributeGroup ref="tns:bitOrderAG"/>
<attribute name="encoding" type="xs:token" use="optional"/>
</extension>
</simpleContent>
</complexType>

<simpleType name="documentPartTypeEnum">
<restriction base="xs:string">
<enumeration value="byte"/>
<enumeration value="text"/>
<enumeration value="bits"/>
<enumeration value="file"/>
</restriction>
</simpleType>

<attributeGroup name="bitOrderAG">
<attribute name="bitOrder" type="tns:bitOrderEnum" use="optional"/>
<attribute name="byteOrder" type="tns:byteOrderEnum" use="optional"/>
</attributeGroup>

<simpleType name="byteOrderEnum">
<annotation>
<documentation>
Not to be confused with dfdl:byteOrder, this attribute describes the
order of bits or bytes in the TDML document part, that is, whether
they
should be given their positions starting from the beginning (LTR) or the
end (RTL). LTR is the normal default where data location number
increase
from left to right. RTL is used for bit-order LSBFirst, and the bytes
are ordered starting on the right increasing to the left.
</documentation>
</annotation>
<restriction base="xs:string">
<enumeration value="RTL"/>
<enumeration value="LTR"/>
</restriction>
</simpleType>

<simpleType name="bitOrderEnum">
<restriction base="xs:string">
<enumeration value="LSBFirst"/>
<enumeration value="MSBFirst"/>
</restriction>
</simpleType>

<complexType name="infosetType">
<sequence>
<element ref="tns:dfdlInfoset"/>
</sequence>
<attribute ref="tns:tutorialInclude"/>
</complexType>

<element name="dfdlInfoset" type="tns:dfdlInfosetType"/>

<complexType name="dfdlInfosetType" mixed="true">
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
<attribute name="type" use="optional" default="infoset">
<simpleType>
<restriction base="xs:string">
<enumeration value="infoset"/>
<enumeration value="file"/>
</restriction>
</simpleType>
</attribute>
</complexType>

<complexType name="errorsType">
<sequence>
<element ref="tns:error" maxOccurs="unbounded" minOccurs="1"/>
</sequence>
<attributeGroup ref="tns:errorWarnAttribs"/>
</complexType>

<complexType name="warningsType">
<sequence>
<element ref="tns:warning" maxOccurs="unbounded" minOccurs="0"/>
<!-- use <warnings/> to indicate no warnings should occur. -->
</sequence>
<attributeGroup ref="tns:errorWarnAttribs"/>
</complexType>

<complexType name="validationErrorsType">
<sequence>
<element ref="tns:error" maxOccurs="unbounded" minOccurs="0"/>
<!-- use <validationErrors/> to indicate no validation should occur. -->
</sequence>
<attributeGroup ref="tns:errorWarnAttribs"/>
</complexType>

<element name="error" type="xs:string"/>
<element name="warning" type="xs:string"/>

<xs:attributeGroup name="errorWarnAttribs">
<xs:attribute name="match" use="optional" default="all">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="all"/>
<xs:enumeration value="any"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:attributeGroup>

<element name="unparserTestCase" type="tns:unparserTestCaseType" substitutionGroup="tns:testSuiteChoices"/>
<complexType name="unparserTestCaseType">
<choice minOccurs="2" maxOccurs="9">
<!-- we just can't enforce cardinality of any of these things using XSD 1.0 -->
<element ref="tns:tutorial"/> <!-- these before, between, or after any of the others -->
<element ref="tns:infoset"/> <!-- required -->
<element ref="tns:document"/> <!-- must have either document, or errors, or both -->
<element ref="tns:errors"/>
<element ref="tns:warnings"/>
</choice>
<attributeGroup ref="tns:testCaseAttribs"/>
</complexType>

</xsd:schema>
Loading

0 comments on commit c4ff24b

Please sign in to comment.