blob: 2811a32b4dc3c8d9183dd428ce447b6a8f0c732e [file] [log] [blame]
/*
* 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.dsom
import org.apache.daffodil.compiler._
import org.apache.daffodil.util.Logging
import org.apache.daffodil.xml.XMLUtils
import org.junit.Assert._
import org.apache.daffodil.util._
import org.junit.Test
class TestRefMap extends Logging {
val xsd = XMLUtils.XSD_NAMESPACE
val dfdl = XMLUtils.dfdlAppinfoSource // XMLUtils.DFDL_NAMESPACE
val xsi = XMLUtils.XSI_NAMESPACE
val example = XMLUtils.EXAMPLE_NAMESPACE
@Test def testRefMapEmpty(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(2, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(1, numEntries)
val numRefPairs = root.refPairsMap.size
assertEquals(1, numRefPairs) // good proxy for schema size
}
@Test def testRefMapComplex1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:sequence>
<xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(5, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(2, numEntries)
val numRefPairs = root.refPairsMap.size
assertEquals(2, numRefPairs) // good proxy for schema size
val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef)
assertEquals(root.referencedElement.shortSchemaComponentDesignator, edecl)
}
@Test def testRefMapGroupRefSeq1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:group ref="ex:g"/>
</xs:complexType>
<xs:group name="g">
<xs:sequence>
<xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:group>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(6, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(3, numEntries)
val numRefPairs = root.refPairsMap.size
assertEquals(3, numRefPairs) // good proxy for schema size
val rootDecl = root.referencedElement
val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef)
assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
val gref = rootDecl.complexType.modelGroup.asInstanceOf[SequenceGroupRef]
val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef).get
assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
assertEquals(6, root.numComponents)
assertEquals(6, root.numUniqueComponents)
}
@Test def testRefMapGroupRefChoice1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:group ref="ex:g"/>
</xs:complexType>
<xs:group name="g">
<xs:choice>
<xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:choice>
</xs:group>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(7, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(3, numEntries)
val numRefPairs = root.refPairsMap.size
assertEquals(3, numRefPairs) // good proxy for schema size
val rootDecl = root.referencedElement
val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef)
assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
val gref = rootDecl.complexType.modelGroup.asInstanceOf[ChoiceGroupRef]
val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef).get
assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
assertEquals(7, root.numComponents)
assertEquals(7, root.numUniqueComponents)
}
@Test def testRefMapGroupRefNest1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:group ref="ex:g"/>
</xs:complexType>
<xs:group name="g">
<xs:choice>
<xs:element name="e" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element ref="ex:r1"/>
</xs:choice>
</xs:group>
<xs:element name="r1" type="ex:ct1"/>
<xs:complexType name="ct1">
<xs:sequence dfdl:hiddenGroupRef="ex:g1"/>
</xs:complexType>
<xs:group name="g1">
<xs:choice>
<xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit" dfdl:outputValueCalc="{ 0 }"/>
<xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:choice>
</xs:group>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(14, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(6, numEntries)
val numRefPairs = root.refPairsMap.size
assertEquals(6, numRefPairs) // good proxy for schema size
val rootDecl = root.referencedElement
val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef)
assertEquals(rootDecl.shortSchemaComponentDesignator, edecl)
val gref = rootDecl.complexType.modelGroup.asInstanceOf[ChoiceGroupRef]
val Seq((grefSSCD, gdRefSpecs)) = refMap.get(gref.groupDef).get
assertEquals(gref.shortSchemaComponentDesignator, grefSSCD)
assertEquals(14, root.numComponents)
assertEquals(14, root.numUniqueComponents)
}
@Test def testRefMapNonExplosion1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:sequence>
<xs:group ref="ex:g"/>
<xs:group ref="ex:g"/>
</xs:sequence>
</xs:complexType>
<xs:group name="g">
<xs:sequence>
<!-- a choice here would be UPA ambiguous -->
<xs:element ref="ex:r1"/>
<xs:element ref="ex:r1"/>
</xs:sequence>
</xs:group>
<xs:element name="r1">
<xs:complexType>
<xs:sequence>
<xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(14, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(4, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(6, numRefPairs) // good proxy for schema size
val allGRefs = root.allGRefs
assertEquals(2, allGRefs.size)
val allERefsCount = root.allERefs.size
assertEquals(2, allERefsCount)
val allCTRefsCount = root.allCTRefs.size
assertEquals(1, allCTRefsCount)
assertEquals(14, root.numComponents)
assertEquals(14, root.numUniqueComponents)
}
@Test def testRefMapExplosion2(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:sequence>
<xs:group ref="ex:g"/>
<xs:group ref="ex:g"/>
</xs:sequence>
</xs:complexType>
<xs:group name="g">
<xs:sequence>
<!-- a choice here would be UPA ambiguous -->
<xs:element ref="ex:r1"/>
<xs:element ref="ex:r1"/>
</xs:sequence>
</xs:group>
<xs:element name="r1">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:r2"/>
<xs:element ref="ex:r2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="r2">
<xs:complexType>
<xs:sequence>
<xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(19, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(5, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(8, numRefPairs)
assertEquals(19, root.numComponents)
assertEquals(19, root.numUniqueComponents)
}
@Test def testRefMapExplosion3(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="r">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:r1"/>
<xs:element ref="ex:r1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="r1">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:r2"/>
<xs:element ref="ex:r2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="r2">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:r3"/>
<xs:element ref="ex:r3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="r3">
<xs:complexType>
<xs:sequence>
<xs:element name="e1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f1" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(21, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(4, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(7, numRefPairs)
assertEquals(21, root.numComponents)
assertEquals(21, root.numUniqueComponents)
}
@Test def testRefMapExplosion4(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="e5">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e4"/>
<xs:element ref="ex:e4"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e4">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e3"/>
<xs:element ref="ex:e3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e3">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e2"/>
<xs:element ref="ex:e2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e2">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e1"/>
<xs:element ref="ex:e1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e1">
<xs:complexType>
<xs:sequence>
<xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(26, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(5, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(9, numRefPairs)
assertEquals(26, root.numComponents)
assertEquals(26, root.numUniqueComponents)
}
@Test def testRefMapExplosion5(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="e6">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e5"/>
<xs:element ref="ex:e5"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e5">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e4"/>
<xs:element ref="ex:e4"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e4">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e3"/>
<xs:element ref="ex:e3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e3">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e2"/>
<xs:element ref="ex:e2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e2">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e1"/>
<xs:element ref="ex:e1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e1">
<xs:complexType>
<xs:sequence>
<xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(31, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(6, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(11, numRefPairs)
assertEquals(31, root.numComponents)
assertEquals(31, root.numUniqueComponents)
}
@Test def testRefMapExplosion6(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="e7">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e6"/>
<xs:element ref="ex:e6"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e6">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e5"/>
<xs:element ref="ex:e5"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e5">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e4"/>
<xs:element ref="ex:e4"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e4">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e3"/>
<xs:element ref="ex:e3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e3">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e2"/>
<xs:element ref="ex:e2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e2">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e1"/>
<xs:element ref="ex:e1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e1">
<xs:complexType>
<xs:sequence>
<xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(36, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(7, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(13, numRefPairs)
assertEquals(36, root.numComponents)
assertEquals(36, root.numUniqueComponents)
}
@Test def testRefMapExplosion7(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat"/>,
<xs:element name="e8">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e7"/>
<xs:element ref="ex:e7"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e7">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e6"/>
<xs:element ref="ex:e6"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e6">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e5"/>
<xs:element ref="ex:e5"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e5">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e4"/>
<xs:element ref="ex:e4"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e4">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e3"/>
<xs:element ref="ex:e3"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e3">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e2"/>
<xs:element ref="ex:e2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e2">
<xs:complexType>
<xs:sequence>
<xs:element ref="ex:e1"/>
<xs:element ref="ex:e1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="e1">
<xs:complexType>
<xs:sequence>
<xs:element name="e0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
<xs:element name="f0" type="xs:int" dfdl:length="1" dfdl:lengthKind="explicit"/>
</xs:sequence>
</xs:complexType>
</xs:element>)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
assertEquals(41, comps.length)
val refMap = root.refMap
val numEntries = refMap.size
assertEquals(8, numEntries)
val refPairsMap = root.refPairsMap.toSeq
val numRefPairs = refPairsMap.map {
_._2.length
}.sum
assertEquals(15, numRefPairs)
assertEquals(41, root.numComponents)
assertEquals(41, root.numUniqueComponents)
}
/**
* This test reproduces a situation observed in the VMF DFDL Schema.
*
* The situation is an element uses a complex type that references a global group g.
* Another global group h, also references g.
* But nothing uses h.
*
* This *was* failing because Daffodil was incorrectly giving the group definition
* for h an enclosingElement of the root. It really should have no enclosing element.
*/
@Test def testUnusedGroup1(): Unit = {
val testSchema = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat" lengthKind="delimited"/>,
<xs:element name="r" type="ex:ct"/>
<xs:complexType name="ct">
<xs:group ref="ex:g"/>
</xs:complexType>
<xs:group name="h"><!-- unused group shares referenced child group -->
<xs:sequence>
<xs:group ref="ex:g"/>
</xs:sequence>
</xs:group>
<xs:group name="g">
<xs:sequence>
<!-- computed element expressions are not meaningful for the unused global group 'h' -->
<xs:element name="e" type="xs:int" dfdl:outputValueCalc='{ ../f }'/>
<xs:element name="f" type="xs:int" dfdl:inputValueCalc='{ ../e }' />
</xs:sequence>
</xs:group>,
useDefaultNamespace = false,
elementFormDefault = "unqualified"
)
val compiler = Compiler()
val sset = compiler.compileNode(testSchema).sset
val root = sset.root
val comps = root.allComponents
val refMap = root.refMap
val numEntries = refMap.size
val numRefPairs = root.refPairsMap.size
val rootDecl = root.referencedElement
val ctDef = root.complexType.asInstanceOf[GlobalComplexTypeDef]
val Some(Seq((edecl, ctRefSpecs))) = refMap.get(ctDef)
val gref = rootDecl.complexType.modelGroup.asInstanceOf[SequenceGroupRef]
val g_gDef = gref.groupDef
val eDecl = g_gDef.groupMembers(0)
val fDecl = g_gDef.groupMembers(1)
val e_enclComps = eDecl.enclosingComponents
assertEquals(1, e_enclComps.length)
val gDef = e_enclComps(0).encloser.asInstanceOf[GlobalSequenceGroupDef]
val e_enclTerms = eDecl.enclosingTerms
assertEquals(2, e_enclTerms.length)
// The second of the above enclosingTerms should NOT have any enclosing element.
val e_enclElems = eDecl.enclosingElements
assertEquals(1, e_enclElems.length)
}
lazy val testRootPathsSchema1 = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat" lengthKind="delimited"/>,
//
// note that the first element below will be the root element.
// it doesn't use any of the rest of the schema
//
// The notRoot element uses type ct, which contains element rr
// which makes the expressions inside group g's elements meaningful.
// But... notRoot isn't the root.
//
// The h element also uses group g. But there is no element rr. The
// relative paths inside group g aren't meaningful in the context of
// element h. Since h is not the root, we will only check, and detect this
// if compileAllTopLevels is true.
//
<xs:element name="r" type="xs:int"/>
<xs:element name="notRoot" type="tns:ct"/>
++
restOfXML,
useDefaultNamespace = false,
elementFormDefault = "unqualified"
)
lazy val restOfXML = (
<xs:element name="h"><!-- uses the substructure, but expressions are past root-->
<xs:complexType>
<xs:sequence>
<!-- The group g contains elements with paths that are past the root for
this usage inside element h -->
<xs:group ref="ex:g"/>
</xs:sequence>
</xs:complexType>
</xs:element>
++
restOfXML2)
lazy val restOfXML2 =
<xs:complexType name="ct">
<xs:sequence>
<xs:element name="rr">
<xs:complexType>
<xs:sequence>
<xs:group ref="ex:g"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:group name="g">
<xs:sequence>
<!--
computed element expressions are not meaningful for the unused global element 'h'
The paths go up two levels of elements, so these upward paths are reaching
outside of the element h, which is not inside element rr.
These paths are only meaningful when this group g is used inside the context
of element rr
-->
<xs:element name="e" type="xs:int" dfdl:outputValueCalc='{ ../../rr/f }'/>
<xs:element name="f" type="xs:int" dfdl:inputValueCalc='{ ../../rr/e }' />
</xs:sequence>
</xs:group>
/**
* The root element doesn't have any substructure that eventually uses the
* group h, so we get the error that indicates h can't be a root (relative path upward)
* because we're checking all top level.
*/
@Test def testPathPastRootFromGlobalDef1(): Unit = {
val compiler = Compiler().withCheckAllTopLevel(true)
val pf = compiler.compileNode(testRootPathsSchema1)
val isError = pf.isError
val msgs = pf.getDiagnostics.map(_.getMessage()).mkString("\n")
// println(msgs)
assertTrue(isError)
assertTrue(msgs.toLowerCase.contains("Relative path '../../rr/f' past root element".toLowerCase))
}
@Test def testPathPastRootFromGlobalDef2(): Unit = {
val compiler = Compiler().withCheckAllTopLevel(false)
val pf = compiler.compileNode(testRootPathsSchema1)
val isError = pf.isError
assertFalse(isError)
}
lazy val testRootPathsSchema2 = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat" lengthKind="delimited"/>,
//
// note that the first element below will be the root element.
//
// The h element also uses group g. But there is no element rr. The
// relative paths inside group g aren't meaningful in the context of
// element h.
//
// However, h is not the root, so even with checkAllTopLevel true
// we don't report errors about these meaningless paths, as we only
// generate code for the root.
//
<xs:element name="r" type="tns:ct"/>
++
restOfXML,
useDefaultNamespace = false,
elementFormDefault = "unqualified"
)
/**
* Shows that so long as the root reaches the expressions
* and they are meaningful in that context, even checkAllTopLevels
* doesn't detect that element h can't be correct (as a root)
*
* Note that if element h were used as part of the substructure of
* root, then if it has proper placement so the expressions are
* meaningful, then that is correct. It's usage as a root is incorrect
* but isn't entertained as a consideration by the schema compiler.
*/
@Test def testPathPastRootFromGlobalDef3(): Unit = {
val compiler = Compiler().withCheckAllTopLevel(true)
val pf = compiler.compileNode(testRootPathsSchema2)
val isError = pf.isError
assertFalse(isError)
}
lazy val testRootPathsSchema3 = SchemaUtils.dfdlTestSchema(
<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
<dfdl:format ref="tns:GeneralFormat" lengthKind="delimited"/>,
//
// note that the first element below will be the root element.
//
// The h element also uses group g. But there is no element rr. The
// relative paths inside group g aren't meaningful in the context of
// element h.
//
// However, h is not the root, so even with checkAllTopLevel true
// we don't report errors about these meaningless paths, as we only
// generate code for the root.
//
// But, h is checked. The meaningless part of it is detected.
//
<xs:element name="r" type="tns:ct"/>
++
<xs:element name="h"><!-- uses the substructure, but expressions are past root-->
<xs:complexType>
<xs:sequence>
<!-- The group g contains elements with paths that are past the root for
this usage inside element h -->
<xs:group ref="ex:g"/>
<xs:sequence dfdl:hiddenGroupRef="tns:noSuchGroup"/>
</xs:sequence>
</xs:complexType>
</xs:element>
++
restOfXML2,
useDefaultNamespace = false,
elementFormDefault = "unqualified"
)
/**
* This test shows that if checkAllTopLevel is false,
* then the error inside global element h, (hiddenGroupRef to non-existing group)
* is NOT detected, since it's not part of the schema reachable
* from the root.
*
* Note that checkAllTopLevels false will NOT prevent
* schema validation checks. But hiddenGroupRef isn't
* a validity check. It's an explicit check done by Daffodil.
*/
@Test def testCheckAllTopLevelWorksToIgnore(): Unit = {
val compiler = Compiler().withCheckAllTopLevel(false)
val pf = compiler.compileNode(testRootPathsSchema3)
val isError = pf.isError
assertFalse(isError)
}
/**
* Test shows that even though it is not the root,
* element h is checked by Daffodil, and the
* erroneous hiddenGroupRef is detected.
*/
@Test def testCheckAllTopLevelWorksToCheck(): Unit = {
val compiler = Compiler().withCheckAllTopLevel(true)
val pf = compiler.compileNode(testRootPathsSchema3)
val isError = pf.isError
val msgs = pf.getDiagnostics.map(_.getMessage()).mkString("\n")
println(msgs)
assertTrue(isError)
assertTrue(msgs.toLowerCase.contains("not found".toLowerCase))
assertTrue(msgs.toLowerCase.contains("noSuchGroup".toLowerCase))
}
}