Difference between revisions of "CDO/Preparing EMF Models"

From Eclipsepedia

< CDO
Jump to: navigation, search
(Create the GenModel)
(Create the GenModel)
Line 83: Line 83:
 
==Create the GenModel==
 
==Create the GenModel==
  
The EMF generator model for your Ecore model is much like a usual Genodel except for three differences:
+
The EMF generator model for your Ecore model is much like a usual Genodel except for the following four differences:
 
* The '''Feature Delegation''' property ''must'' be set to <code>Reflective</code>
 
* The '''Feature Delegation''' property ''must'' be set to <code>Reflective</code>
 +
* The '''Model Plug-in Variables''' property ''should'' be set to <code>CDO=org.eclipse.emf.cdo</code>
 
* The '''Root Extends Class''' property ''must'' be set to <code>org.eclipse.emf.internal.cdo.CDOObjectImpl</code>
 
* The '''Root Extends Class''' property ''must'' be set to <code>org.eclipse.emf.internal.cdo.CDOObjectImpl</code>
 
* The '''Root Extends Interface''' property ''can'' be set to <code>org.eclipse.emf.cdo.CDOObject</code>
 
* The '''Root Extends Interface''' property ''can'' be set to <code>org.eclipse.emf.cdo.CDOObject</code>
Line 105: Line 106:
 
     complianceLevel="5.0">
 
     complianceLevel="5.0">
 
   <foreignModel>model1.ecore</foreignModel>
 
   <foreignModel>model1.ecore</foreignModel>
 +
  <modelPluginVariables>CDO=org.eclipse.emf.cdo</modelPluginVariables>
 
   <genPackages prefix="Model1" basePackage="org.eclipse.emf.cdo.tests" disposableProviderFactory="true"
 
   <genPackages prefix="Model1" basePackage="org.eclipse.emf.cdo.tests" disposableProviderFactory="true"
 
       ecorePackage="model1.ecore#/">
 
       ecorePackage="model1.ecore#/">
     <genClasses ecoreClass="model1.ecore#//Supplier">
+
     <genClasses ecoreClass="model1.ecore#//Address">
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Supplier/name"/>
+
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/name"/>
    </genClasses>
+
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/street"/>
    <genClasses ecoreClass="model1.ecore#//PurchaseOrder">
+
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/city"/>
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//PurchaseOrder/date"/>
+
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//PurchaseOrder/supplier"/>
+
    </genClasses>
+
    <genClasses ecoreClass="model1.ecore#//OrderDetail">
+
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//OrderDetail/product"/>
+
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//OrderDetail/price"/>
+
    </genClasses>
+
    <genClasses ecoreClass="model1.ecore#//Product">
+
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Product/name"/>
+
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Product/orderDetails"/>
+
    </genClasses>
+
    <genClasses ecoreClass="model1.ecore#//Category">
+
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Category/name"/>
+
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/categories"/>
+
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/products"/>
+
 
     </genClasses>
 
     </genClasses>
 
     <genClasses ecoreClass="model1.ecore#//Company">
 
     <genClasses ecoreClass="model1.ecore#//Company">
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/categories"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/categories"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/suppliers"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/suppliers"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/purchaseOrders"/>
 
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/customers"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/customers"/>
 +
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/purchaseOrders"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/salesOrders"/>
 
       <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/salesOrders"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//Supplier">
 +
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Supplier/purchaseOrders"/>
 
     </genClasses>
 
     </genClasses>
 
     <genClasses ecoreClass="model1.ecore#//Customer">
 
     <genClasses ecoreClass="model1.ecore#//Customer">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Customer/name"/>
 
 
       <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Customer/salesOrders"/>
 
       <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Customer/salesOrders"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//Order">
 +
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Order/orderDetails"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//OrderDetail">
 +
      <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference model1.ecore#//OrderDetail/order"/>
 +
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//OrderDetail/product"/>
 +
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//OrderDetail/price"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//PurchaseOrder">
 +
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//PurchaseOrder/date"/>
 +
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//PurchaseOrder/supplier"/>
 
     </genClasses>
 
     </genClasses>
 
     <genClasses ecoreClass="model1.ecore#//SalesOrder">
 
     <genClasses ecoreClass="model1.ecore#//SalesOrder">
 
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//SalesOrder/id"/>
 
       <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//SalesOrder/id"/>
 
       <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//SalesOrder/customer"/>
 
       <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//SalesOrder/customer"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//Category">
 +
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Category/name"/>
 +
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/categories"/>
 +
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/products"/>
 +
    </genClasses>
 +
    <genClasses ecoreClass="model1.ecore#//Product">
 +
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Product/name"/>
 +
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Product/orderDetails"/>
 
     </genClasses>
 
     </genClasses>
 
   </genPackages>
 
   </genPackages>

Revision as of 06:32, 1 November 2007

Contents


Create an Ecore Model

There's not much to say about this step. The .ecore file for CDO models is the same as for pure EMF models. The only differences are in the Java code that the EMF generator will produce, as you will see in the next step.

The model1 example model in the usual Ecore model editor looks like follows:


Model1Ecore.png


You can download this Ecore model from here. Its XML form is:

<?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="model1"
    nsURI="http://www.eclipse.org/emf/CDO/tests/model1/1.0.0" nsPrefix="model1">
  <eClassifiers xsi:type="ecore:EClass" name="Address">
    <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="#//Address">
    <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="#//Address">
    <eStructuralFeatures xsi:type="ecore:EReference" name="purchaseOrders" upperBound="-1"
        eType="#//PurchaseOrder" eOpposite="#//PurchaseOrder/supplier"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Customer" eSuperTypes="#//Address">
    <eStructuralFeatures xsi:type="ecore:EReference" name="salesOrders" unique="false"
        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"
        eOpposite="#//Product/orderDetails"/>
    <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:EReference" name="orderDetails" upperBound="-1"
        eType="#//OrderDetail" eOpposite="#//OrderDetail/product"/>
  </eClassifiers>
</ecore:EPackage>


Create the GenModel

The EMF generator model for your Ecore model is much like a usual Genodel except for the following four differences:

  • The Feature Delegation property must be set to Reflective
  • The Model Plug-in Variables property should be set to CDO=org.eclipse.emf.cdo
  • The Root Extends Class property must be set to org.eclipse.emf.internal.cdo.CDOObjectImpl
  • The Root Extends Interface property can be set to org.eclipse.emf.cdo.CDOObject


GenModel.png


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.

You can download this generator model from here. Its XML form is:

<?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.tests.model1/src"
    modelPluginID="org.eclipse.emf.cdo.tests.model1" modelName="Model1" rootExtendsInterface="org.eclipse.emf.cdo.CDOObject"
    rootExtendsClass="org.eclipse.emf.internal.cdo.CDOObjectImpl" reflectiveDelegation="true"
    testsDirectory="" importerID="org.eclipse.emf.importer.ecore" featureDelegation="Reflective"
    complianceLevel="5.0">
  <foreignModel>model1.ecore</foreignModel>
  <modelPluginVariables>CDO=org.eclipse.emf.cdo</modelPluginVariables>
  <genPackages prefix="Model1" basePackage="org.eclipse.emf.cdo.tests" disposableProviderFactory="true"
      ecorePackage="model1.ecore#/">
    <genClasses ecoreClass="model1.ecore#//Address">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/name"/>
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/street"/>
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Address/city"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Company">
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/categories"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/suppliers"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/customers"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/purchaseOrders"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Company/salesOrders"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Supplier">
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Supplier/purchaseOrders"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Customer">
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Customer/salesOrders"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Order">
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Order/orderDetails"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//OrderDetail">
      <genFeatures property="None" notify="false" createChild="false" ecoreFeature="ecore:EReference model1.ecore#//OrderDetail/order"/>
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//OrderDetail/product"/>
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//OrderDetail/price"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//PurchaseOrder">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//PurchaseOrder/date"/>
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//PurchaseOrder/supplier"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//SalesOrder">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//SalesOrder/id"/>
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//SalesOrder/customer"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Category">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Category/name"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/categories"/>
      <genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference model1.ecore#//Category/products"/>
    </genClasses>
    <genClasses ecoreClass="model1.ecore#//Product">
      <genFeatures createChild="false" ecoreFeature="ecore:EAttribute model1.ecore#//Product/name"/>
      <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference model1.ecore#//Product/orderDetails"/>
    </genClasses>
  </genPackages>
</genmodel:GenModel>


Generate The Model

Generate the Java code for your model like you are used to do it:


GenerateTheModel.png


The result of the generation can look similar to this (some artifacts are hidden to declutter the Package Explorer):


GeneratorResults.png


Contribute the Model

At runtime the CDO client needs to determine whether a given EPackage (your model) has been generated for CDO or not. You can declaratively specify this information by contributing to the org.eclipse.emf.cdo.persistent_package extension point, much like you announce the model to EMF via the org.eclipse.emf.ecore.generated_package extension point:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.3"?>

<plugin>

  <extension point="org.eclipse.emf.ecore.generated_package">
    <package 
       uri = "http://www.eclipse.org/emf/CDO/tests/model1/1.0.0" 
       class = "org.eclipse.emf.cdo.tests.model1.Model1Package"
       genModel = "model/model1.genmodel"/> 
  </extension>
  
  <extension point="org.eclipse.emf.cdo.persistent_package">
    <package
       uri = "http://www.eclipse.org/emf/CDO/tests/model1/1.0.0"/>
  </extension>

</plugin>



Wikis: CDO | Net4j | EMF | Eclipse