Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Authoring XML Schemas for use with EMF"

(Mapping Structural Content)
m (Mapping to uncontained EReference)
 
(10 intermediate revisions by 2 users not shown)
Line 94: Line 94:
 
=Mapping XSD to Ecore=
 
=Mapping XSD to Ecore=
  
 +
More information on this subject can be also found in draft document XML Schema to Ecore Mapping. [http://www.eclipse.org/modeling/emf/docs/overviews/XMLSchemaToEcoreMapping.pdf]
  
 
==Mapping Schema to EPackage==
 
==Mapping Schema to EPackage==
Line 101: Line 102:
 
(in progress...)
 
(in progress...)
  
==Mapping Simple and Complex Type to Classes, DataTypes, and Enums==
+
==Mapping Types==
  
 
{{IndentedSection|body=Types in a Schema are mapped to ''Classifiers'' in Ecore (one of EClass, EDataType, EEnum). A Complex Type always results in a Class, but a Simple Type can be mapped to either a DataType or an Enum, depending on the presence of restricted values.}}
 
{{IndentedSection|body=Types in a Schema are mapped to ''Classifiers'' in Ecore (one of EClass, EDataType, EEnum). A Complex Type always results in a Class, but a Simple Type can be mapped to either a DataType or an Enum, depending on the presence of restricted values.}}
  
===Simple Type to DataType or Enum===
+
===Mapping SimpleType to EDataType/EEnum===
  
 
An EDataType will be created if there are no enumerations:
 
An EDataType will be created if there are no enumerations:
Line 253: Line 254:
 
|}
 
|}
  
==Mapping Structural Content==
+
==Mapping Structural Features==
 +
 
 +
===Common Mapping Options===
  
 
[[Image:Xsd_emf_mapping_features.gif]]
 
[[Image:Xsd_emf_mapping_features.gif]]
  
Whether you're mapping an xsd:attribute or xsd:element to an EAttribute or EReference, most of the mapping options for EStructuralFeatures are valid.
+
Whether you're mapping an xsd:attribute or xsd:element to an EAttribute or EReference, most of the mapping options for EStructuralFeatures are shared.
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
Line 272: Line 275:
  
 
|-
 
|-
{{CodeCell|2}} <xsd:''feature'' | ''EStructuralFeature'' (EReference or EAttribute)
+
{{CodeCell|2}} <xsd:''feature''
 +
| ''EStructuralFeature'' (EReference or EAttribute)
  
 
{{AnnotationSection|name=Default Mappings}}
 
{{AnnotationSection|name=Default Mappings}}
Line 278: Line 282:
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
 
{{CodeCell|3}}name="author"
 
{{CodeCell|3}}name="author"
{{AnnotationCell| The feature's name will default to this value}}
+
{{AnnotationCell| -> name (The feature's name) }}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
 
{{CodeCell|3}}type=''type''
 
{{CodeCell|3}}type=''type''
{{AnnotationCell| -> EDataType for EAttributes<BR>EClass for EReferences }}
+
{{AnnotationCell| -> attributeType for EAttributes<BR>-> referenceType for EReferences }}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
Line 308: Line 312:
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
 
{{CodeCell|3}}ecore:required="<u>$auto$</u>|boolean"
 
{{CodeCell|3}}ecore:required="<u>$auto$</u>|boolean"
{{AnnotationCell| Default value is calculated by EMF, perhaps when lower bound is &gt;0 (review needed) }}
+
{{AnnotationCell| Default value is calculated by EMF, perhaps when lower bound &gt; 0 (review needed) }}
  
 
{{AnnotationSection|name=Ecore Specific}}
 
{{AnnotationSection|name=Ecore Specific}}
Line 334: Line 338:
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
 
{{CodeCell|3}}ecore:transient="<u>$auto$</u>|''boolean''"
 
{{CodeCell|3}}ecore:transient="<u>$auto$</u>|''boolean''"
{{AnnotationCell|False is assumed. Transient features will not be written out}}
+
{{AnnotationCell|False by default, unless a featuremap is involved. Transient features are '''not''' persisted }}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|3}}ecore:volatile="<u>false</u>|true"
+
{{CodeCell|3}}ecore:derived="<u>$auto$</u>|''boolean''"
{{AnnotationCell|False is assumed}}
+
{{AnnotationCell|False by default, unless a featuremap is involved.}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|3}}ecore:derived="<u>$auto$</u>|''boolean''"
+
{{CodeCell|3}}ecore:volatile="<u>false</u>|true"
 
{{AnnotationCell|False is assumed}}
 
{{AnnotationCell|False is assumed}}
  
Line 352: Line 356:
 
|}
 
|}
  
===Attribute to EAttribute===
+
===Mapping to EAttributes===
  
Simple attributes in your schema (attributes that are not references) are mapped to EAttributes. The upper bound on the EAttribute of this type <u>must</u> be 1.
+
{{IndentedSection|body=
 +
[[Image:Xsd_emf_mapping_to_attribute.gif]]
 +
 
 +
<P>XSD Elements and Attributes whose types are SimpleTypes always map to EAttributes. The only exceptions are "HREF" types such as "xs:anyURI" or "xs:IDREF", which must be treated as EReferences.
  
In a document the attribute would appear as:
+
}}
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
 +
|+ In the XML, an EAttribute may takes several forms:
 
|-
 
|-
{{CodeCell|0}}<Event <u>message="Something happened"</u><BR>...<BR></Event>
+
{{CodeCell|1}}<Event <u>message="Something happened"</u>/>
 +
|-
 +
| (Or)
 +
|-
 +
{{CodeCell|1}}<Event>
 +
|-
 +
{{CodeCell|2}}<u><message>Something happened</message></u>
 +
|-
 +
{{CodeCell|1}}</Event>
 +
|-
 +
| (Or)
 +
|-
 +
{{CodeCell|1}}<Event>
 +
|-
 +
{{CodeCell|2}}<u><message>First Message</message></u>
 +
|-
 +
{{CodeCell|2}}<u><message>Second Message</message></u>
 +
|-
 +
{{CodeCell|1}}</Event>
 +
 
 
|}
 
|}
 +
 +
Note that elements must be used for attributes with multiplicity &gt;1.
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
Line 369: Line 398:
  
 
|- style="color:gray" |
 
|- style="color:gray" |
{{CodeCell|0}}<xsd:complexType name="Event">
+
{{CodeCell|0}}<xsd:complexType name="Event"><BR>...
 
+
|- style="color:gray" |
+
{{CodeCell|1}}<xsd:sequence>
+
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|2}}<xsd:attribute
+
{{CodeCell|2}}<xsd:(attribute|element)
 
{{AnnotationCell|EAttribute}}
 
{{AnnotationCell|EAttribute}}
  
Line 382: Line 408:
 
|-
 
|-
 
{{CodeCell|4}}name="message"
 
{{CodeCell|4}}name="message"
 +
| -> name
  
 
|-
 
|-
 
{{CodeCell|4}}type="xsd:string"
 
{{CodeCell|4}}type="xsd:string"
| -> EDataType
+
| -> attributeType (must be SimpleType -> EDataType)
  
 
|-
 
|-
 
{{CodeCell|4}}default="Hello world"
 
{{CodeCell|4}}default="Hello world"
 
| -> Default Value Literal
 
| -> Default Value Literal
 +
 +
{{AnnotationSection|name=xsd:attributes only}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
 
{{CodeCell|4}}use="<u>optional</u>|required|prohibited"
 
{{CodeCell|4}}use="<u>optional</u>|required|prohibited"
{{AnnotationCell| Affects the '''lower bound''' and '''required''' properties of the EAttribute<BR>Note that '''unsettable''' is true by default when '''upper bound''' is 1(review needed) }}
+
{{AnnotationCell| Affects upper and/or lower bounds }}
  
{{AnnotationSection|name=Overriding default mappings}}
+
{{AnnotationSection|name=xsd:elements only}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|4}}ecore:required="<u>''f(use)''</u>|boolean"
+
{{CodeCell|4}}minOccurs="''value''"<BR>maxOccurs="''value''"
{{AnnotationCell| Overrides '''required''', which by default is true iff use is "required" }}
+
{{AnnotationCell| Affects upper and/or lower bounds }}
  
 
|-
 
|-
Line 405: Line 434:
  
 
|- style="color:gray" |
 
|- style="color:gray" |
{{CodeCell|1}}</xsd:sequence>
+
{{CodeCell|1}}...
  
 
|- style="color:gray" |
 
|- style="color:gray" |
Line 412: Line 441:
 
|}
 
|}
  
===Element to EAttribute===
+
===Mapping Element to Contained EReference===
  
Elements which are Simple Types <u>must</u> be mapped to EAttributes. Exceptions are strings that are references to other Objects. Elements may occur multiple times, and they are the only way to represent multi-valued attributes.
+
Elements with {{HoverText|<nowiki>e.g. <xsd:element type="tns:Address"></nowiki>|Complex Types}} can only be mapped to EReferences. Since Elements represent nested data in a document, it's no surprise that the EReference must be contained. EReferences which are not contained are saved as URIs to some other location, which means that a Simple Type is sufficient.
 +
 
 +
In a document, contained content could appear as:
  
Example Document:
 
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
 
|-
 
|-
{{CodeCell|0}}...<BR><Book>
+
{{CodeCell|0}}<List>
 
|-
 
|-
{{CodeCell|1}}<u><Author>Randy Hudson</Author></u>
+
{{CodeCell|1}}<Item text="This is item 1"/>
 
|-
 
|-
{{CodeCell|1}}<u><Author>Author #2</Author></u>
+
{{CodeCell|1}}<Item text="This is item 2"/>
 
|-
 
|-
{{CodeCell|1}}...
+
{{CodeCell|0}}</List>
|-
+
{{CodeCell|0}}</Book><BR>...
+
 
|}
 
|}
 
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
Line 437: Line 464:
  
 
|- style="color:gray" |
 
|- style="color:gray" |
 
+
{{CodeCell|0}}<xsd:complexType name="Container">
{{CodeCell|0}}<xsd:complexType name="Book">
+
 
+
 
|- style="color:gray" |
 
|- style="color:gray" |
 
{{CodeCell|1}}<xsd:sequence>
 
{{CodeCell|1}}<xsd:sequence>
 
+
|-  
|-
+
 
{{CodeCell|2}}<xsd:element
 
{{CodeCell|2}}<xsd:element
| EAttribute
+
| EReference
 
+
{{AnnotationSection|name=Default Mappings}}
+
  
 
|-
 
|-
{{CodeCell|3}}name="author"
+
{{CodeCell|4}}name="child"
 
+
{{AnnotatedLine}}
+
{{CodeCell|3}}type="string"
+
{{AnnotationCell| -> EDataType (must be a SimpleType)}}
+
  
 
|-
 
|-
{{CodeCell|3}}default="John Doe"/>
+
{{CodeCell|4}}type="tns:Child"
 +
 
 +
| -> EClass (type must be Complex)
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|3}}minOccurs="0|<u>1</u>|n"
+
{{CodeCell|4}}minOccurs="0|<u>1</u>|n"
 
{{AnnotationCell| -> Lower Bound}}
 
{{AnnotationCell| -> Lower Bound}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|3}}maxOccurs="0|<u>1</u>|n|unbounded"
+
{{CodeCell|4}}maxOccurs="0|<u>1</u>|n|unbounded"
 
{{AnnotationCell| -> Upper Bound}}
 
{{AnnotationCell| -> Upper Bound}}
 +
 +
{{AnnotationSection|name=Overriding default mappings}}
 +
 +
|-
 +
{{CodeCell|4}}ecore:lowerBound = "<u>$minOccurs$</u>|n"
 +
 +
|-
 +
{{CodeCell|4}}ecore:upperBound = "<u>$maxOccurs$</u>|n"
 +
 +
{{AnnotationSection|name=Ecore Specific}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|3}}nillable="<u>false</u>|true"
+
{{CodeCell|4}}ecore:opposite="<u>null</u>|opposite"
{{AnnotationCell| Setting to <tt>true</tt> allows <tt>null</tt> to occur as a value. Note that java primitives like <tt>int</tt> are not Objects (review needed) }}
+
{{AnnotationCell|Identifies the inverse EReference using the XSD element/attribute name from the ComplexType }}
  
 +
{{AnnotatedLine}}
 +
{{CodeCell|4}}ecore:changeable="false|<u>true*</u>"
 +
{{AnnotationCell| True by default<BR> * may be false when featureMaps are involved (review needed) }}
 +
 +
|-
 +
{{CodeCell|4}}...<BR>/>
 
|- style="color:gray" |
 
|- style="color:gray" |
 
{{CodeCell|1}}</xsd:sequence>
 
{{CodeCell|1}}</xsd:sequence>
 
 
|- style="color:gray" |
 
|- style="color:gray" |
 
{{CodeCell|0}}</xsd:complexType>
 
{{CodeCell|0}}</xsd:complexType>
Line 479: Line 514:
 
|}
 
|}
  
===Element to Contained EReference===
+
===Mapping to uncontained EReference===
  
Elements with {{HoverText|<nowiki>e.g. <xsd:element type="tns:Address"></nowiki>|Complex Types}} can only be mapped to EReferences. Since Elements represent nested data in a document, it's no surprise that the EReference must be contained. EReferences which are not contained are saved as URIs to some other location, which means that a Simple Type is sufficient.
+
[[Image:Xsd_emf_mapping_to_reference.gif]]
  
In a document, contained content could appear as:
+
Both Attributes and Elements can be mapped to uncontained EReferences. As with EAttribute, only XSD elements will allow for multiplicity &gt;1.
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
 +
|+ In the XML, the EReference may takes several forms:
 
|-
 
|-
{{CodeCell|0}}<List>
+
{{CodeCell|1}}<Event <u>origin="_DHejd3ks8dh3je8shre"</u>/>
 
|-
 
|-
{{CodeCell|1}}<Item text="This is item 1"/>
+
| (Or)
 
|-
 
|-
{{CodeCell|1}}<Item text="This is item 2"/>
+
{{CodeCell|1}}<Event>
 
|-
 
|-
{{CodeCell|0}}</List>
+
{{CodeCell|2}}<u><origin>_DHejd3ks8dh3je8shre</origin></u>
 +
|-
 +
{{CodeCell|1}}</Event>
 +
|-
 +
| (Or)
 +
|-
 +
{{CodeCell|1}}<Event>
 +
|-
 +
{{CodeCell|2}}<u><message>_DHejd3ks8dh3je8shre</message></u>
 +
|-
 +
{{CodeCell|2}}<u><message>_ks8dh3je8sXGejd3hre</message></u>
 +
|-
 +
{{CodeCell|1}}</Event>
 +
 
 
|}
 
|}
 +
 +
Note that elements must be used for references with multiplicity &gt; 1.
  
 
{{AnnotatedSourceCode}}
 
{{AnnotatedSourceCode}}
Line 502: Line 553:
  
 
|- style="color:gray" |
 
|- style="color:gray" |
{{CodeCell|0}}<xsd:complexType name="Container">
+
{{CodeCell|0}}<xsd:complexType name="Event"><BR>...
|- style="color:gray" |
+
{{CodeCell|1}}<xsd:sequence>
+
|-
+
{{CodeCell|2}}<xsd:element
+
| EReference
+
  
|-
+
{{AnnotatedLine}}
{{CodeCell|4}}name="child"
+
{{CodeCell|2}}<xsd:(attribute|element)
 +
{{AnnotationCell|EAttribute}}
 +
 
 +
{{AnnotationSection|name=Default Mappings}}
  
 
|-
 
|-
{{CodeCell|4}}type="tns:Child"
+
{{CodeCell|4}}name="source"
| -> EClass (must be ComplexType) }}
+
| -> name
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|4}}minOccurs="0|<u>1</u>|n"
+
{{CodeCell|4}}type="xsd:anyURI"
{{AnnotationCell| -> Lower Bound}}
+
{{AnnotationCell| resolveProxies and other settings are sensitive to the ref type (review needed)}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|4}}maxOccurs="0|<u>1</u>|n|unbounded"
+
{{CodeCell|4}}*type="ecore:type"
{{AnnotationCell| -> Upper Bound}}
+
{{AnnotationCell| (*required) EMF must be told the type of the reference (review needed)}}
 
+
{{AnnotationSection|name=Overriding default mappings}}
+
  
 
|-
 
|-
{{CodeCell|4}}ecore:lowerBound = "<u>$minOccurs$</u>|n"
+
{{CodeCell|4}}default="???"
 +
| Does a default value make any sense (review needed)
  
|-
+
{{AnnotationSection|name=xsd:attributes only}}
{{CodeCell|4}}ecore:upperBound = "<u>$maxOccurs$</u>|n"
+
 
+
{{AnnotationSection|name=Ecore Specific}}
+
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|4}}ecore:opposite="<u>none</u>|opposite"
+
{{CodeCell|4}}use="<u>optional</u>|required|prohibited"
{{AnnotationCell|Identifies the inverse EReference using the XSD element/attribute name from the ComplexType }}
+
{{AnnotationCell| Affects upper and/or lower bounds }}
 +
 
 +
{{AnnotationSection|name=xsd:elements only}}
  
 
{{AnnotatedLine}}
 
{{AnnotatedLine}}
{{CodeCell|4}}ecore:changeable="false|<u>true*</u>"
+
{{CodeCell|4}}minOccurs="''value''"<BR>maxOccurs="''value''"
{{AnnotationCell| True by default<BR> * may be false when featureMaps are involved (review needed) }}
+
{{AnnotationCell| Affects upper and/or lower bounds }}
  
 
|-
 
|-
 
{{CodeCell|4}}...<BR>/>
 
{{CodeCell|4}}...<BR>/>
 +
 
|- style="color:gray" |
 
|- style="color:gray" |
{{CodeCell|1}}</xsd:sequence>
+
{{CodeCell|1}}...
 +
 
 
|- style="color:gray" |
 
|- style="color:gray" |
 
{{CodeCell|0}}</xsd:complexType>
 
{{CodeCell|0}}</xsd:complexType>
  
 
|}
 
|}
 
===Mapping XSD Feature to uncontained EReference===
 
 
Both attributes and elements can be mapped to non-containment EReferences. Elements must be used when the upper bound is more than 1.
 
 
(in progress...)
 
  
 
= Tips and Techniques =
 
= Tips and Techniques =
Line 565: Line 608:
  
 
If the assumptions made by the architects of java are correct, then the only useful form of multiple inheritance is to "overlay" additional method signatures onto a class already extending some other class. (Or in the simplest case, just for "tagging", e.g. java.lang.Cloneable). Let's hope they're right, because these are basically the same limitations we are dealing with here.
 
If the assumptions made by the architects of java are correct, then the only useful form of multiple inheritance is to "overlay" additional method signatures onto a class already extending some other class. (Or in the simplest case, just for "tagging", e.g. java.lang.Cloneable). Let's hope they're right, because these are basically the same limitations we are dealing with here.
 +
 +
It may be useful to think of the "single inheritance" permitted for ComplexTypes as being similar to java class extension. Java only allows you to inherit one implementation class. This "free", inherited implementation is analogous to the free, inherited attributes and elements from your base ComplexType. Let's say that we mix in an additional ComplexType using <tt>ecore:implements="tns:SecondSuper"</tt>. When you try to save an xsd:attribute or xsd:element inherited this way, you can't.  Your schema has no idea what you're talking about.
 +
 +
So, let's think of mix-in types as interfaces that can never be "implemented". Implementation here refers to being persisted using something actually defined in your XSD.
 +
 +
(in progress..)
 
}}
 
}}

Latest revision as of 10:52, 18 February 2009

This article focuses on authoring and using XML Schemas for the purpose of generating an EMF model.

Introduction

An EMF Model (files of type *.genmodel) is your hub for importing/exporting other metamodel formats, linking to other EMF models, and generating implementation code. Out of the box, EMF can import XML Schema Definitions (XSDs) into Ecore Models (files of type *.ecore). Similarly, EMF can export Ecore Models to XSDs. But without an understanding of the differences between these two metamodels, and without knowing how to control the mapping process, the results will often be less than desired.

Luckily, both Ecore models and XML Schemas have support for annotations. Annotations can be almost anything, but for this discussion, annotations serve two purposes:

  • Provide additional information when transforming one metamodel to another
  • Provide additional information on how to serialize/deserialize your model objects

EMF supports transformations in either direction (to or from XSDs). Currently, if you start with an Ecore model, round-tripping to XSD and back to Ecore should be lossless. However, Ecore supports some structures that have no XSD equivalent, such as multiple inheritance. Information will be lost in such cases. Also, if you start with an XSD, not all of the information is captured in the Ecore model. Therefore, "round-tripping" XSD->Ecore->XSD is not a recommended practice as of the Europa release. Information might get lost, and almost certainly will get shuffled around.

This article will focus only on the practice of authoring (and annotating) XSDs and importing them into Ecore models. However, it can be a useful learning tool to model certain structures first in Ecore, and then exporting to see the annotated XSD equivalent.

Reasons to use XSDs with EMF

Here are a few reasons why XSDs are used with EMF:
  • The XSD already exists
  • You must ship an XSD
  • Using an XSD is one way to customize how EMF models are persisted

Important Differences between XSDs and Ecore Models

Multiple Inheritance

Global Elements and Attributes

The Transformation Process

The overall process looks like:
  1. An EMF Model is created and associated with one or more XSDs
  2. When the Wizard finishes, the conversion process creates *.ecore files
  3. At this point, EMF will not read your XSDs again. All information needed by EMF has been tucked away somewhere else.
  4. If you modify your schemas, the transformation can be performed again from the .genmodel Editor. Affected Ecore models are completely replaced.

Which Parts of an XML Schema are Processed?

Without being told otherwise, EMF will process your Schema, all of its globally declared Elements, and all Types contained therein. Other content (e.g. globally-declared Attributes, AttributeGroups, and Groups) is ignored by EMF. These entries are just macros that Elements and Types can reference, effectively in-lining a copy. If two Types reference the same global Attribute, AttributeGroup, or Element, EMF sees them as two distinct features which happen to have identical information.

What is the Output of the Process?

The Process generates, updates, or replaces the following:
  1. Ecore Models
    Schemas become Packages; Simple/Complex Types become EClasses, EDataTypes, and EEnums; Elements and Attributes become EStructuralFeatures
    Annotations in your Ecore Models
    Ecore annotations are added in several places to capture the way your model should be serialized/deserialized. These annotations are what enable EMF to read and write XML documents that don't conform to EMF's default serialization format.
    A Helper EClass named "DocumentRoot"
    In certain cases, EMF must create a DocumentRoot class to store additional information.
    Helper EStructuralFeatures, such as feature maps with the suffix "group"
    To handle XSD features like substitution groups, the substitution rule to be used when writing must be known. To handle these cases, your Class' EReferences don't hold onto the actual content, but are instead derived from these "group" references which contains keys in addition to the actual referenced object.
    Your EMF Model
    References to the schemas you imported are kept so that you can invoke a reload later. Generations options are configured the first time with different defaults, under the assumption that you'll be reading and writing to XML files.

Mapping XSD to Ecore

More information on this subject can be also found in draft document XML Schema to Ecore Mapping. [1]

Mapping Schema to EPackage

Each XML Schema is mapped to an EPackage.

(in progress...)

Mapping Types

Types in a Schema are mapped to Classifiers in Ecore (one of EClass, EDataType, EEnum). A Complex Type always results in a Class, but a Simple Type can be mapped to either a DataType or an Enum, depending on the presence of restricted values.

Mapping SimpleType to EDataType/EEnum

An EDataType will be created if there are no enumerations:


<xs:simpleType EDataType
[Default Mappings]
name="RGB" -> Name (unless overridden)
[Override Default Mapping]
ecore:ignore="true" Ignores this type
ecore:name="overrideName" Determines the name
ecore:instanceClass="package.JavaType" Determines the fully qualified java Class or Interface
... >
<xs:restriction base="xs:string"/> Determines the Instance Class Name in many cases
</xs:simpleType>

If the restriction includes enumerations an EEnum is created:


<xs:simpleType EEnum
name="Align" -> Name (unless overridden)
[Overriding Default Mappings]
ecore:ignore="(true)" Ignores this Simple Type
ecore:name="$name|override" Overrides the Name, normally determined by name
...
>
<xs:restriction>
<xs:enumeration EEnum Literal (for each xs:enumeration)
value="Left"
ecore:value="auto|int" Overrides the Literal's Value
ecore:name="auto|override" Overrides the Literal's Name, normally determined by value
...
/>
<xs:enumeration value="Center"/>
<xs:enumeration value="Right"/>
</xs:restriction>
</xs:simpleType>
...

Complex Type to EClass

<xsd:complexType EClass
name="Container" -> Name (unless overridden)
abstract="false|true" -> Abstract (qualifier on the impl class)
ecore:name="$name$|override" Overrides name
ecore:implements="(tns:MixinInterface)" Adds additional supertypes to the EClass. See the section on multiple inheritance.
ecore:interface="false|true"> If true only the java interface is generated
<xsd:complexContent>
<xsd:extension base="tns:Child"> Determines the first Super Type of the EClass
...
(Structural Features)
...
Elements and Attributes which appear here are described elsewhere
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

Mapping Structural Features

Common Mapping Options

Xsd emf mapping features.gif

Whether you're mapping an xsd:attribute or xsd:element to an EAttribute or EReference, most of the mapping options for EStructuralFeatures are shared.


XML Schema Description
<xsd:complexType name="Book">
...
<xsd:feature EStructuralFeature (EReference or EAttribute)
[Default Mappings]
name="author" -> name (The feature's name)
type=type -> attributeType for EAttributes
-> referenceType for EReferences
default="value"/> -> (needs review) Default Value Literal
[Overriding the default mappings]
ecore:ignore="false|true" Instructs EMF not to perform any mapping
ecore:name="$auto$|name" Overrides the name
ecore:lowerBound = "$auto$|n" Overrides the lower bound, which is normally calculated from other information to be 0 or 1
ecore:upperBound = "$auto$|n" Overrides upper bound, normally calculated from other information to be 1 or "many"
ecore:required="$auto$|boolean" Default value is calculated by EMF, perhaps when lower bound > 0 (review needed)
[Ecore Specific]
ecore:unsettable="boolean" Overrides unsettable, default value is true if lower bound is 0, OR upper bound is 1 (review needed)
ecore:suppressedGetVisibility="false|true" Removes the accessor method from the generated interface only
ecore:suppressedSetVisibility="false|true" Removes the set method method from the generated interface only
ecore:suppressedIsSetVisibility="false|true" Removes the "is set" method method from the generated interface only
ecore:suppressedUnsetVisibility="false|true" Removes the unset method method from the generated interface only
ecore:transient="$auto$|boolean" False by default, unless a featuremap is involved. Transient features are not persisted
ecore:derived="$auto$|boolean" False by default, unless a featuremap is involved.
ecore:volatile="false|true" False is assumed
</xsd:sequence>
</xsd:complexType>

Mapping to EAttributes

Xsd emf mapping to attribute.gif

XSD Elements and Attributes whose types are SimpleTypes always map to EAttributes. The only exceptions are "HREF" types such as "xs:anyURI" or "xs:IDREF", which must be treated as EReferences.</div>

In the XML, an EAttribute may takes several forms:
<Event message="Something happened"/>
(Or)
<Event>
<message>Something happened</message>
</Event>
(Or)
<Event>
<message>First Message</message>
<message>Second Message</message>
</Event>

Note that elements must be used for attributes with multiplicity >1.


XML Schema Description
<xsd:complexType name="Event">
...
<xsd:(attribute|element) EAttribute
[Default Mappings]
name="message" -> name
type="xsd:string" -> attributeType (must be SimpleType -> EDataType)
default="Hello world" -> Default Value Literal
[xsd:attributes only]
use="optional|required|prohibited" Affects upper and/or lower bounds
[xsd:elements only]
minOccurs="value"
maxOccurs="value"
Affects upper and/or lower bounds
...
/>
...
</xsd:complexType>

Mapping Element to Contained EReference

Elements with Complex Types can only be mapped to EReferences. Since Elements represent nested data in a document, it's no surprise that the EReference must be contained. EReferences which are not contained are saved as URIs to some other location, which means that a Simple Type is sufficient.

In a document, contained content could appear as:


<List>
<Item text="This is item 1"/>
<Item text="This is item 2"/>
</List>


XML Schema Description
<xsd:complexType name="Container">
<xsd:sequence>
<xsd:element EReference
name="child"
type="tns:Child" -> EClass (type must be Complex)
minOccurs="0|1|n" -> Lower Bound
maxOccurs="0|1|n|unbounded" -> Upper Bound
[Overriding default mappings]
ecore:lowerBound = "$minOccurs$|n"
ecore:upperBound = "$maxOccurs$|n"
[Ecore Specific]
ecore:opposite="null|opposite" Identifies the inverse EReference using the XSD element/attribute name from the ComplexType
ecore:changeable="false|true*" True by default
* may be false when featureMaps are involved (review needed)
...
/>
</xsd:sequence>
</xsd:complexType>

Mapping to uncontained EReference

Xsd emf mapping to reference.gif

Both Attributes and Elements can be mapped to uncontained EReferences. As with EAttribute, only XSD elements will allow for multiplicity >1.


In the XML, the EReference may takes several forms:
<Event origin="_DHejd3ks8dh3je8shre"/>
(Or)
<Event>
<origin>_DHejd3ks8dh3je8shre</origin>
</Event>
(Or)
<Event>
<message>_DHejd3ks8dh3je8shre</message>
<message>_ks8dh3je8sXGejd3hre</message>
</Event>

Note that elements must be used for references with multiplicity > 1.


XML Schema Description
<xsd:complexType name="Event">
...
<xsd:(attribute|element) EAttribute
[Default Mappings]
name="source" -> name
type="xsd:anyURI" resolveProxies and other settings are sensitive to the ref type (review needed)
*type="ecore:type" (*required) EMF must be told the type of the reference (review needed)
default="???" Does a default value make any sense (review needed)
[xsd:attributes only]
use="optional|required|prohibited" Affects upper and/or lower bounds
[xsd:elements only]
minOccurs="value"
maxOccurs="value"
Affects upper and/or lower bounds
...
/>
...
</xsd:complexType>

Tips and Techniques

Almost Multiple Inheritance

An XSD ComplexType may have at most one super-type, while both Ecore and the java language support multiple inheritance. Single inheritance is just too restrictive, so most Ecore models, or equivalently, most model APIs, are going to need more.

If the assumptions made by the architects of java are correct, then the only useful form of multiple inheritance is to "overlay" additional method signatures onto a class already extending some other class. (Or in the simplest case, just for "tagging", e.g. java.lang.Cloneable). Let's hope they're right, because these are basically the same limitations we are dealing with here.

It may be useful to think of the "single inheritance" permitted for ComplexTypes as being similar to java class extension. Java only allows you to inherit one implementation class. This "free", inherited implementation is analogous to the free, inherited attributes and elements from your base ComplexType. Let's say that we mix in an additional ComplexType using ecore:implements="tns:SecondSuper". When you try to save an xsd:attribute or xsd:element inherited this way, you can't. Your schema has no idea what you're talking about.

So, let's think of mix-in types as interfaces that can never be "implemented". Implementation here refers to being persisted using something actually defined in your XSD.

(in progress..)

Back to the top