Persisting Substitution Groups
- Example XML Schema with Substitution Group
- Java source code for Substitution Group
- Persisting a Substitution Group
- Benefits/Consequences of this approach
This page explains how Substitution Groups are supported in the persistency layer. This is provided as background information as this is normally hidden for the application developer.
Example XML Schema with Substitution Group
The XML Schema below (copied from zvon.org) shows an example of the use of a Substitution Group.
<xsd:element name="root"> <xsd:complexType> <xsd:sequence minOccurs="1"> <xsd:element ref="myAbstract"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="myAbstract" type="AAA" abstract="true"/> <xsd:simpleType name="AAA"> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="1"/> <xsd:maxInclusive value="9"/> </xsd:restriction> </xsd:simpleType> <xsd:element name="odd" substitutionGroup="myAbstract"> <xsd:simpleType> <xsd:restriction base="AAA"> <xsd:enumeration value="1"/> ...... <xsd:enumeration value="9"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="even" substitutionGroup="myAbstract"> <xsd:simpleType> <xsd:restriction base="AAA"> <xsd:enumeration value="2"/> ..... <xsd:enumeration value="8"/> </xsd:restriction> </xsd:simpleType> </xsd:element>
Java source code for Substitution Group
This xml schema will result in getters/setters of the following (truncated form):
/** * ........ * @model unique="false" dataType="org.eclipse.emf.ecore.EFeatureMapEntry" required="true" * extendedMetaData="kind='group' name='myAbstract:group' namespace='##targetNamespace'" * @generated */ FeatureMap getMyAbstractGroup(); /** * ........ * @model unique="false" dataType="org.eclipse.emf.teneo.samples.emf.schemaconstructs.substitutionzvon.AAA" required="true" transient="true" changeable="false" volatile="true" derived="true" * required="true" transient="true" changeable="false" volatile="true" derived="true" * extendedMetaData="kind='element' name='myAbstract' namespace='##targetNamespace' group='myAbstract:group'" * @generated */ BigInteger getMyAbstract();
As is visible one FeatureMap getter is generated for the Substitution Group element. This FeatureMap will keep track of which elements (combination of StructuralFeature and value) is actually used. In addition a getter (getMyAbstract) is generated for direct access to the value.
Persisting a Substitution Group
The Substitution Group element is a FeatureMap which is mapped as a collection with embedded types. The embedded type is org.eclipse.emf.teneo.jpox.elist.GenericFeatureMapEntry. The mapping for the above example is shown below. For more information regarding persisting FeatureMaps see here.
<field name="myAbstractGroup" persistence-modifier="persistent"> <collection element-type="org.eclipse.emf.teneo.jpox.elist.GenericFeatureMapEntry"> <extension vendor-name="jpox" key="cache-lazy-loading" value="true"/> </collection> <join/> <element> <embedded> <field name="featurePath"/> <field name="localAnyValue" embedded="true"> <extension vendor-name="jpox" key="implementation-classes" value="java.math.BigInteger"/> <extension vendor-name="teneo" key="estructuralfeatures" value="myAbstract"/> </field> <field name="localReferenceValue" embedded="true"> <extension vendor-name="jpox" key="implementation-classes" value="org.eclipse.emf.teneo.jpox.mapping.AnyTypeEObject"/> <extension vendor-name="teneo" key="estructuralfeatures" value=""/> <foreign-key delete-action="restrict" update-action="cascade"/> </field> <field name="localContainmentReferenceValue" dependent="true" embedded="true"> <foreign-key delete-action="cascade" update-action="cascade"/> <extension vendor-name="jpox" key="implementation-classes" value="org.eclipse.emf.teneo.jpox.mapping.AnyTypeEObject"/> <extension vendor-name="teneo" key="estructuralfeatures" value=""/> </field> </embedded> </element> <order column="ROOTTYPE_MYABSTRACTGROUP_IDX"/> </field>
Benefits/Consequences of this approach
The chosen approach has a number of benefits/consequences:
- The extensions to persist Substitution Groups are completely hidden for the application developer. He/She can use the standard EMF apis.
- No unnecessary columns: a (nullable) column is only created for the type which can be used in place of the Substitution Group.
- Advanced querying possible: foreign keys are created in the entry table for references to other classes (tables). This means that it is possible to join tables using advanced SQL or JDOQL queries.
- Features such as delete restrictions work directly and without any further extra specifications.