Preparing the Models |
 |
Author: Eike Stepper
Table of Contents
1 Creating an Ecore Model
There's really not much to say about this step. The .ecore file for CDO models is the same as for pure EMF models.
Use the Empty EMF Project New Wizard to create an initial project for your model:
Create an ordinary Ecore model file in the models folder.
The model1 example model in the usual Ecore model editor looks like follows:
The XML representation of this Ecore model is:
|
company.ecore |
 |
|
|
 |
<?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="company" nsURI="http://www.eclipse.org/emf/CDO/examples/company/1.0.0"
nsPrefix="company">
<eClassifiers xsi:type="ecore:EClass" name="Addressable" abstract="true">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="street" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="city" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Company" eSuperTypes="#//Addressable">
<eStructuralFeatures xsi:type="ecore:EReference" name="categories" upperBound="-1"
eType="#//Category" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="suppliers" upperBound="-1"
eType="#//Supplier" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="customers" upperBound="-1"
eType="#//Customer" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="purchaseOrders" upperBound="-1"
eType="#//PurchaseOrder" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="salesOrders" upperBound="-1"
eType="#//SalesOrder" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Supplier" eSuperTypes="#//Addressable">
<eStructuralFeatures xsi:type="ecore:EReference" name="purchaseOrders" upperBound="-1"
eType="#//PurchaseOrder" eOpposite="#//PurchaseOrder/supplier"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="preferred" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"
defaultValueLiteral="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Customer" eSuperTypes="#//Addressable">
<eStructuralFeatures xsi:type="ecore:EReference" name="salesOrders" upperBound="-1"
eType="#//SalesOrder" eOpposite="#//SalesOrder/customer"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Order">
<eStructuralFeatures xsi:type="ecore:EReference" name="orderDetails" upperBound="-1"
eType="#//OrderDetail" containment="true" eOpposite="#//OrderDetail/order"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="OrderDetail">
<eStructuralFeatures xsi:type="ecore:EReference" name="order" lowerBound="1" eType="#//Order"
eOpposite="#//Order/orderDetails"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="product" eType="#//Product"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="price" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="PurchaseOrder" eSuperTypes="#//Order">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="date" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDate"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="supplier" lowerBound="1"
eType="#//Supplier" eOpposite="#//Supplier/purchaseOrders"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="SalesOrder" eSuperTypes="#//Order">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="id" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="customer" lowerBound="1"
eType="#//Customer" eOpposite="#//Customer/salesOrders"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Category">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="categories" upperBound="-1"
eType="#//Category" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="products" upperBound="-1"
eType="#//Product" containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Product">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="vat" eType="#//VAT" defaultValueLiteral="vat15"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="description" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"
transient="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="price" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EEnum" name="VAT">
<eLiterals name="vat0"/>
<eLiterals name="vat7" value="7"/>
<eLiterals name="vat15" value="15"/>
</eClassifiers>
</ecore:EPackage>
|
The model project should look similar to this, now:
2 Using the CDO Model Importer
The CDO SDK contributes an Ecore model importer to the EMF Generator Model wizard. It creates a
GenModel configured for CDO-native generated objects and adjusts CDO-specific generator
properties. Choose this importer when generated instances should participate directly in CDO's
object and revision APIs. An ordinary EMF model can also be used in legacy mode, but generated
objects then need CDO's adaptation layer and do not necessarily implement CDOObject.
Right-click the Ecore model file and select New and Other... and choose the EMF Generator Model New Wizard:
On the next page, the Select a Model Importer page, select the Ecore model (CDO native) importer:
On the next page, the Ecore Import page, click the Load button:
On the next page, the Package Selection page, adjust the settings depending on your model and its referenced models:
After clicking the Finish button your model project should look similar to this (please note that the CDO marker
file META-INF/CDO.MF has also been created by the importer):
3 Using the CDO Model Migrator
To convert an existing GenModel, select the CDO Model Migrator action contributed by the SDK.
It adjusts the GenModel in place; review and save those changes before regenerating model code.
Keep generated code synchronized with the updated GenModel rather than editing generated
implementation classes by hand.
In case the generator model was successfully migrated to CDO the following dialog box will appear:
Proceed with Generate The Model.
4 Migrating a GenModel Manually
If you migrate a GenModel manually, use the current CDO migrator defaults as the reference. It
adjusts feature delegation, generated base types, and generator flags so generated objects use
CDO's reflective feature storage path. The relevant properties are:
- The Feature Delegation property is set to
Reflective.
- The Root Extends Class property is set to
org.eclipse.emf.internal.cdo.CDOObjectImpl.
The migrator currently selects this implementation base for generated native models. It
is a generator/runtime dependency, not an application API; application code should use
the public CDOObject contract.
- The Root Extends Interface property is set to
org.eclipse.emf.cdo.CDOObject.
- Model plug-in variables include
CDO=org.eclipse.emf.cdo. If generating an edit
plug-in, edit plug-in variables include CDO_EDIT=org.eclipse.emf.cdo.edit and
the provider root class is org.eclipse.emf.cdo.edit.CDOItemProviderAdapter.
- Boolean flags are disabled and packed enums are disabled, as configured by the migrator.
Note that you do not need to generate an editor if you want to use your model with the CDO User Interface
A dedicated model editor is only needed if you plan to use your model with normal XML based files as well.
Even in this scenario it could be simpler to use the EMF Reflective Model Editor though.
The XML representation of this GenModel is:
|
company.genmodel |
 |
|
|
 |
<?xml version="1.0" encoding="UTF-8"?>
<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" modelDirectory="/org.eclipse.emf.cdo.examples.company/src" creationIcons="false"
editDirectory="/org.eclipse.emf.cdo.examples.company.edit/src" editorDirectory=""
modelPluginID="org.eclipse.emf.cdo.examples.company" modelName="Company" editPluginClass="org.eclipse.emf.cdo.examples.company.provider.CompanyEditPlugin"
editorPluginClass="" updateClasspath="false" rootExtendsClass="org.eclipse.emf.internal.cdo.CDOObjectImpl"
reflectiveDelegation="true" codeFormatting="true" testsDirectory="" testSuiteClass="org.eclipse.emf.cdo.examples.company.tests.CompanyAllTests"
importerID="org.eclipse.emf.importer.ecore" featureDelegation="Reflective" complianceLevel="8.0"
providerRootExtendsClass="org.eclipse.emf.cdo.edit.CDOItemProviderAdapter" editPluginID="org.eclipse.emf.cdo.examples.company.edit"
editorPluginID="org.eclipse.emf.cdo.examples.company.editor" testsPluginID="org.eclipse.emf.cdo.examples.company.editor"
optimizedHasChildren="true" colorProviders="true" fontProviders="true" runtimeVersion="2.6">
<foreignModel>company.ecore</foreignModel>
<modelPluginVariables>CDO=org.eclipse.emf.cdo</modelPluginVariables>
<genPackages prefix="Company" basePackage="org.eclipse.emf.cdo.examples" disposableProviderFactory="true"
extensibleProviderFactory="true" childCreationExtenders="true" ecorePackage="company.ecore#/">
<genEnums typeSafeEnumCompatible="false" ecoreEnum="company.ecore#//VAT">
<genEnumLiterals ecoreEnumLiteral="company.ecore#//VAT/vat0"/>
<genEnumLiterals ecoreEnumLiteral="company.ecore#//VAT/vat7"/>
<genEnumLiterals ecoreEnumLiteral="company.ecore#//VAT/vat15"/>
</genEnums>
<genClasses image="false" ecoreClass="company.ecore#//Addressable">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Addressable/name"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Addressable/street"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Addressable/city"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Company">
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Company/categories"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Company/suppliers"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Company/customers"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Company/purchaseOrders"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Company/salesOrders"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Supplier">
<genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference company.ecore#//Supplier/purchaseOrders"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Supplier/preferred"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Customer">
<genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference company.ecore#//Customer/salesOrders"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Order">
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Order/orderDetails"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//OrderDetail">
<genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference company.ecore#//OrderDetail/order"/>
<genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference company.ecore#//OrderDetail/product"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//OrderDetail/price"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//PurchaseOrder">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//PurchaseOrder/date"/>
<genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference company.ecore#//PurchaseOrder/supplier"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//SalesOrder">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//SalesOrder/id"/>
<genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference company.ecore#//SalesOrder/customer"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Category">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Category/name"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Category/categories"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference company.ecore#//Category/products"/>
</genClasses>
<genClasses ecoreClass="company.ecore#//Product">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Product/name"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Product/vat"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Product/description"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute company.ecore#//Product/price"/>
</genClasses>
</genPackages>
</genmodel:GenModel>
|
5 Generating a Model
Generate the Java code for your model as you are used to do it:
The result of the generation can look similar to this (some artifacts are hidden to remove noise from the Package Explorer):
6 Modifying Generated Getters and Setters
Reflective feature delegation lets CDO intercept generated model feature access and store values
in revision data. Custom getters and setters must preserve that path; switching delegation to
None can make generated Java fields diverge from repository-backed state. Keep
custom behavior in generated accessor overrides that delegate to the compatible reflective
implementation, and verify the generated code against the EMF/CDO versions in use.

Copyright (c) 2004-2026 Eike Stepper (Loehne, Germany) and others.
All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html