HomeEMF HibernateEMF JDO/JPOXWeb App GenerationServices
 

xsd:any and xsd:anyType

This page explains how xsd:any and xsd:anyType elements are stored in a relational store. This is provided as background information as this is normally hidden for the application developer.

Element with xsd:anyType

Element with type xsd:anyType and maxOccurs="1"

The following xml schema defines an element with type xsd:anyType and maxOccurs="1":

<xsd:element name="singleAnyType" type="xsd:anyType"/>				
			

This xml schema will result in getters/setters of the following (truncated form):

/**
 * ......
 * @model containment="true" resolveProxies="false" required="true"
 *        extendedMetaData="kind='element' name='singleAnyType'"
 * @generated
 */
EObject getSingleAnyType();

/**
 * ......
 * @generated
 */
void setSingleAnyType(EObject value);
		

As is visible the EObject type is used as the member type. When storing any EObject in the database Teneo persistency will use two columns (both varchar). The first columns is used to store the datatype if the EObject if it is a primitive type. The second column either stores the String representation of a primitive value or the unique object id as defined by JPOX.

Element with type xsd:anyType and maxOccurs="unbounded"

The following xml schema defines an element with type xsd:anyType and maxOccurs="unbounded":

<xsd:element name="multiAnyType" type="xsd:anyType" maxOccurs="unbounded"/>				
			

This xml schema will result in a getter of the following (truncated form):

/**
 * ..............
 * @model type="org.eclipse.emf.ecore.EObject" containment="true" resolveProxies="false" required="true"
 *        extendedMetaData="kind='element' name='multiAnyType'"
 * @generated
 */
EList getMultiAnyType();
	

As is visible the member is an EList which can contain EObject types. The maxOccurs="unbounded" anytype is mapped as a collection with an embedded PersistenceCapable type: org.eclipse.emf.teneo.jpox.mapping.AnyTypeEObject.

<field name="multiAnyType" persistence-modifier="persistent" embedded="true" delete-action="restrict">
	<collection element-type="org.eclipse.emf.teneo.jpox.mapping.AnyTypeEObject">
		<extension vendor-name="jpox" key="cache-lazy-loading" value="true"/>
	</collection>
	<join>
		<column name="multianytype_id" allows-null="true"/>
	</join>
	<element>
		<embedded>
			<field name="classifier">
				<column name="CLASSIFIER"/>
			</field>
			<field name="value">
				<column name="VALUE"/>
			</field>
		</embedded>
	</element>
	<order column="TESTANY_MULTIANYTYPE_IDX"/>
</field>
				

This mapping will result in a separate table which has a number of columns: 1) reference to the owner table, 2) index field to keep track of the order, 3) is used to store the datatype if the EObject is a primitive type, and 4) either stores the String representation of a primitive value or the unique object id as defined by JPOX.

Setting a primitive value in an xsd:anyType member

It is possible to set a primitive value in an xsd:anyType member. Teneo persistency assumes that primitive values are set using an EObject which implements org.eclipse.emf.ecore.xml.type.SimpleAnyType. An example of such an object is: org.eclipse.emf.ecore.xml.type.impl.SimpleAnyTypeImpl. When a primitive type is retrieved from the relational store then the system will encapsulate the primitive value in a org.eclipse.emf.teneo.jpox.mapping.JPOXSimpleAnyTypeImpl object.

xsd:any Element

The following xml schema defines a xsd:any element:

<xsd:any maxOccurs="unbounded" namespace="##other"/>
			

This xml schema will result in getter of the following (truncated form):

/**
 * ..........
 * @model unique="false" dataType="org.eclipse.emf.ecore.EFeatureMapEntry" required="true" many="true"
 *        extendedMetaData="kind='elementWildcard' wildcards='##other' name=':4' processing='strict'"
 * @generated
 */
FeatureMap getAny();
	

The xsd:any type is translated into a FeatureMap which allows different features to be added. The implementation of the xsd:any FeatureMap is different from the derived feature. In case of xsd:any the system can not determine which types can be stored in this element. Instead the system will store all objects in a separate table. This table will have four columns: 1) reference to the owner table, 2) index field to keep track of the order, 3) is used to store the datatype if the EObject is a primitive type, and 4) either stores the String representation of a primitive value or the unique object id as defined by JPOX.

Note:

  • The persistency solution ignores the namespace XML Schema attribute of the xsd:any element. It is assumed that the EMF layer will handle this attribute.
  • It is possible to set maxOccurs="1" or maxOccurs="unbounded" on the xsd:any element. For the java implementation and the persistency solution this makes no difference. In both cases a FeatureMap with a separate table is used. The EMF layer will check that no more than maxOccurs entries are stored in the FeatureMap.

Benefits/Consequences of this approach

The chosen approach has a number of benefits/consequences:

  • The extensions to persist xsd:any/xsd:anyType are completely hidden for the application developer. He/She can use the standard EMF apis.
  • Support for containment (including cascading delete)
  • No support for JDOQL querying on content of xsd:any fields.
  • No constraint checking when an eobject referenced from an xsd:any is deleted.