Reputation: 1204
As example I want to model in EMF a word-document:
This would be my metamodel:
document
- table (0..*)
- paragraph (0..*)
The problem here is that the model would be very linear:
document
- table_1
- table_2
- table_3
- paragraph_1
There is no possibility to insert a paragraph between two tables (table_1 and table_2).
My solution was to model the metamodel in another way:
document
- (abstract) documentChild (0..*)
table inherit documentChild
paragraph inherit documentChild
This seems for me not optimal. Is there another way to solve this problem in EMF?
Upvotes: 1
Views: 506
Reputation: 1841
This is exactly a use-case for "Feature maps" in EMF.
You want to combine multiple types of objects into a single ordered list and then access individual types using separate references.
So, I created a minimal meta-model that shows how a Document
can contain a mixture of Table
and Paragraph
instances.
The trick is that all the instances are actually located in the elements
attribute (EFeatureMapEntry data type). Then, the tables
and paragraphs
references are just projections of the elements
container.
As you can see in the following figure, the instances are stored in a correct order.
It is a bit tricky to properly set up all the properties of EMF classes. Especially
volatile="true"
transient="true"
derived="true"
containment="true"
Therefore, I'm listing the complete XMI content of the meta-model here:
<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="doc" nsURI="doc" nsPrefix="doc">
<eClassifiers xsi:type="ecore:EClass" name="Table">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Paragraph">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Document">
<eStructuralFeatures xsi:type="ecore:EReference" name="tables" ordered="false"
upperBound="-1" eType="#//Table" volatile="true" transient="true" derived="true"
containment="true">
<eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
<details key="group" value="#elements"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EReference" name="paragraphs" ordered="false"
upperBound="-1" eType="#//Paragraph" volatile="true" transient="true" derived="true"
containment="true">
<eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
<details key="group" value="#elements"/>
</eAnnotations>
</eStructuralFeatures>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="elements" upperBound="-1"
eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFeatureMapEntry">
<eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
<details key="kind" value="group"/>
</eAnnotations>
</eStructuralFeatures>
</eClassifiers>
</ecore:EPackage>
Upvotes: 3
Reputation: 115
In my opinion, the order of child references only matters in the persistent model. However, since the model is an abstraction of your word-document, its persistent model does not necessarily represent what it abstracts from. If you want to put tables and paragraphs in order then just add an order attribute and set its value for every concerned elements.
Upvotes: 0