This is an automated email from the ASF dual-hosted git repository.
slawrence pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git
The following commit(s) were added to refs/heads/master by this push:
new cbb9245 Use reference equality for dsom shared keys
cbb9245 is described below
commit cbb92453a2f6693cd4c9aae8884276d466bc25bc
Author: Steve Lawrence <[email protected]>
AuthorDate: Tue Mar 31 07:32:27 2020 -0400
Use reference equality for dsom shared keys
By using the default object equality, it is possible that two chunks of
XML could look exactly the same and will be shared, even though their
contexts are different and should not be shared. By using reference
equality, XML nodes that happen to have the exact same content but in
different contexts will be seen as different and will not be shared.
DAFFODIL-2308
---
.../daffodil/dsom/AnnotatedSchemaComponent.scala | 29 ++++++++++--
.../section14/sequence_groups/SequenceGroup.tdml | 21 +++++++++
.../SimilarModelGroupElement1.dfdl.xsd | 47 ++++++++++++++++++
.../SimilarModelGroupElement2.dfdl.xsd | 47 ++++++++++++++++++
.../sequence_groups/SimilarModelGroupRoot.dfdl.xsd | 55 ++++++++++++++++++++++
.../sequence_groups/TestSequenceGroups3.scala | 1 +
6 files changed, 195 insertions(+), 5 deletions(-)
diff --git
a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
index 1214006..943ff85 100644
---
a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
+++
b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/AnnotatedSchemaComponent.scala
@@ -241,6 +241,27 @@ case class PropEnv(
defaultPropSource: Seq[Set[(String, String)]],
optNext: Option[scala.xml.Node])
+case class ShareKey(
+ xml: scala.xml.Node,
+ env: PropEnv) {
+
+ /**
+ * It is critical here that we perform reference equality on the XML. This is
+ * because it is possible that the same piece of XML with the same properties
+ * could appear in two completely different contexts. If we perform object
+ * equality, then we might end up sharing parts of the grammar that shouldn't
+ * be shared just because they look the same. By performing reference
+ * equality on the XML, we ensure that we only share parts of grammar that
+ * are actually the same.
+ */
+ override def equals(that: Any): Boolean = {
+ that match {
+ case that: ShareKey => (this.xml eq that.xml) && (this.env == that.env)
+ case _ => false
+ }
+ }
+}
+
/**
* Shared object factory/cache.
*
@@ -249,16 +270,14 @@ case class PropEnv(
*/
final class SharedFactory[SharedType] {
- private type KeyType = (scala.xml.Node, PropEnv)
-
- private val vals = new mutable.HashMap[KeyType, SharedType]
+ private val vals = new mutable.HashMap[ShareKey, SharedType]
/**
* The passing of the value argument by name is critical here, as
* we want to avoid evaluating that at all when the key is one
* we have already seen.
*/
- final def getShared(key: KeyType, value: => SharedType): SharedType = {
+ final def getShared(key: ShareKey, value: => SharedType): SharedType = {
val opt = vals.get(key)
opt match {
case Some(y) => y
@@ -306,7 +325,7 @@ trait AnnotatedSchemaComponent
}
}
- protected final lazy val shareKey = (actualDef.xml, propEnv)
+ protected final lazy val shareKey = ShareKey(actualDef.xml, propEnv)
/**
* For property combining only. E.g., doesn't refer from an element
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
index 3e6b4e7..b7f8c75 100644
---
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroup.tdml
@@ -1480,4 +1480,25 @@
</tdml:infoset>
</tdml:parserTestCase>
+ <tdml:parserTestCase name="similar_model_groups_01" root="root"
+ model="SimilarModelGroupRoot.dfdl.xsd" description="Section 14 - Groups -
DFDL-14-042R">
+ <tdml:document>
+ <tdml:documentPart type="text"><![CDATA[0a0b]]></tdml:documentPart>
+ </tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <root>
+ <similarElement1>
+ <field>0</field>
+ <differentElement1>a</differentElement1>
+ </similarElement1>
+ <similarElement2>
+ <field>0</field>
+ <differentElement2>b</differentElement2>
+ </similarElement2>
+ </root>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
</tdml:testSuite>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement1.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement1.dfdl.xsd
new file mode 100644
index 0000000..5e4491c
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement1.dfdl.xsd
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:ex="http://example.com"
+ targetNamespace="http://example.com"
+ elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format ref="ex:GeneralFormat" />
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:element name="similarElement1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="field" type="xs:int" dfdl:lengthKind="explicit"
dfdl:length="1" />
+ <xs:element name="differentElement1" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="1" />
+ <xs:choice dfdl:choiceDispatchKey="{ xs:string(field) }">
+ <xs:sequence dfdl:choiceBranchKey="0" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement2.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement2.dfdl.xsd
new file mode 100644
index 0000000..69f8a6b
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupElement2.dfdl.xsd
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:ex="http://example.com"
+ targetNamespace="http://example.com"
+ elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format ref="ex:GeneralFormat" />
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:element name="similarElement2">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="field" type="xs:int" dfdl:lengthKind="explicit"
dfdl:length="1" />
+ <xs:element name="differentElement2" type="xs:string"
dfdl:lengthKind="explicit" dfdl:length="1" />
+ <xs:choice dfdl:choiceDispatchKey="{ xs:string(field) }">
+ <xs:sequence dfdl:choiceBranchKey="0" />
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git
a/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupRoot.dfdl.xsd
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupRoot.dfdl.xsd
new file mode 100644
index 0000000..d3651b9
--- /dev/null
+++
b/daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SimilarModelGroupRoot.dfdl.xsd
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<!--
+ This schema contains references to two completely different elements
+ (simpleElement1 and simpleElement2), which are exactly the same (including
+ line numbers) except for the root elements and a sibling element. This schema
+ is used to test that even though these schemas are very similar (particularly
+ the choice with dispatch) and do have some object equality, because they are
+ in different XML files they should not have reference equality and dsom
+ elements will not be shared.
+-->
+<xs:schema
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:fn="http://www.w3.org/2005/xpath-functions"
+ xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+ xmlns:ex="http://example.com"
+ targetNamespace="http://example.com"
+ elementFormDefault="unqualified">
+
+ <xs:include
schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+ <xs:include schemaLocation="SimilarModelGroupElement1.dfdl.xsd" />
+ <xs:include schemaLocation="SimilarModelGroupElement2.dfdl.xsd" />
+
+ <xs:annotation>
+ <xs:appinfo source="http://www.ogf.org/dfdl/">
+ <dfdl:format ref="ex:GeneralFormat" />
+ </xs:appinfo>
+ </xs:annotation>
+
+ <xs:element name="root">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="ex:similarElement1" />
+ <xs:element ref="ex:similarElement2" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
diff --git
a/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups3.scala
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups3.scala
index ac87b83..cc6d6d7 100644
---
a/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups3.scala
+++
b/daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroups3.scala
@@ -46,4 +46,5 @@ class TestSequenceGroups3 {
@Test def test_sequence_group_with_annotation_01() {
runner_02.runOneTest("sequence_group_with_annotation_01") }
@Test def test_choice_group_with_annotation_01() {
runner_02.runOneTest("choice_group_with_annotation_01") }
+ @Test def test_similar_model_groups_01() {
runner_02.runOneTest("similar_model_groups_01") }
}