2.2 EMF.Edit-based editors and code generation

 < Day Day Up > 



2.2 EMF.Edit-based editors and code generation

The Tutorial: Generating an EMF Model describes how to use the GenModel wizard to create a GenModel for the WorkflowModel, and how to generate plug-ins that can be used to create and edit WorkflowModel instances. In this section, we describe the correspondences between generated plug-ins and the model from which they are generated, by examining the code produced for the model, edit, and editor plug-ins generated from the WorkflowModel. We then discuss how to customize these generated plug-ins using code generation properties.

2.2.1 The generated plug-ins

In this section we describe the model, edit, and editor plug-ins generated for the WorkflowModel, and discuss the correspondences between the model and the generated code. The generated plug-ins are provided in the sample code provided with this book.

Note 

The JET framework is used to generate model, edit, and editor plug-ins from EMF models. The templates that are used to generate these plug-ins are located in:

<ECLIPSEHOME>/plugins/org.eclipse.emf.codegen.ecore_<EMFVERSION>/templates

Where <ECLIPSEHOME> is the location where you installed Eclipse, and <EMFVERSION> is the version of the EMF plug-in that you have installed.

We discuss the JET framework and how to customize code generation using templates in 2.4, "Using JET to customize code generation" on page 79.

The model plug-in

In this section, we describe the code in the model plug-in generated from the WorkflowModel.

Packages

For each EPackage, two or three Java packages are generated. For the WorkflowModel, these packages are workflow, workflow.impl, and workflow.util. Notice that there may be a prefix used to generate package names, as discussed in "Package-level GenModel properties" on page 54; however, for the purposes of describing the generated plug-ins in this section, we will ignore it. The util package is optional: Its presence will depend on the code generation properties. The util package is generated when the code generation properties are set to their defaults.

Classes

For each EClass in the EPackage, an interface is generated in the base package, and a Java class that implements it is generated in the impl package. If the EClass inherits from another EClass, then the generated interface and implementation extend the interface and implementation generated for the supertype.

If a class has multiple supertypes, then the first supertype in the eSuperTypes list is considered to be the primary supertype. The generated implementation for a subclass extends the corresponding implementation class of the primary supertype, and implements methods defined in the interfaces generated for any other supertypes. For example, for the WorkflowDiagram model from "Working with packages" on page 35, WorkflowDiagramTask extends TaskImpl (the primary supertype), and implements the methods from DiagramNode.

Features

For each feature, getter and setter methods are generated in the class and interface generated from their containing class. A field to cache the value of the feature is also generated if the feature is not volatile. If a feature is not changeable, then only getter methods are generated.

For multi-valued attributes and references, an EList is used to represent the feature, while single valued attributes are represented by the type of that attribute, for example EString, or the instanceClass of a user-defined EDataType. The type of the EList used to represent features will depend on the constraints in the model, for example, a non-containment reference is represented by an EObjectWithInverseResolvingEList while a containment reference is represented by an EObjectContainmentWithInverseEList.

The reflective methods such as eSet() are generated from all features for the containing class.

Operations

For each EOperation, a public method signature is generated in the interface of the containing class, and a skeleton implementation is generated in the corresponding implementation.

DataTypes

For each EEnum, an implementation is generated that extends org.eclipse.common.util.AbstractEnumerator. For other EDataTypes, there are no interfaces or implementations generated; instead, their instanceClass is used directly for EAttributes of that type.

The edit plug-in

ItemProviders are generated for each class in the edit plug-in in the provider package. In addition, an EMFPluginClass is generated for the entire plug-in. The ItemProviders extend org.eclipse.emf.edit.provider.ItemProviderAdaptor and adapt the corresponding EObject from the model. For example, WorkflowElementItemProvider adapts a WorkflowElement. The ItemProvider forwards some notifications received when the model object changes via fireNotifyChanged(), and filters the rest. You can control which notifications are filtered when you generate the plug-in, as described in 2.2.2, "Customizing code generation through GenModel properties" on page 47.

ItemProviders also manage property descriptors for all features of the class, as well as an icon and description for the class, returned by the getImage() and getText() methods.

An ItemProviderAdaptorFactory is also generated for all of the generated ItemProviders. For the WorkflowModel, it is WorkflowItemProviderAdaptorFactory. Refer to The EMF.Edit framework and code generator overview for more information about these factories.

The editor plug-in

For each model, three classes are generated in the editor plug-in, in the presentation package. There is a multi-page editor, which creates several different JFace viewers for the model, including a TreeViewer which use the ItemProviders from the edit plug-in as their content and label providers. The editor also creates an outline view and property sheet page that displays the properties for the selected object from the viewers.

An ActionBarContributor is also generated, that is used to create the context menu to add children or siblings to selected items from the viewers in the editor.

The final class generated in the editor plug-in is a wizard, which allows you to create a new resource containing an instance of one of your model objects.

2.2.2 Customizing code generation through GenModel properties

The EMF Users' Guide describes the properties defined for each of the Ecore objects in a model. Some of these properties affect the way in which code is generated from the model and are duplicated in the GenModel for that model. In 2.2.1, "The generated plug-ins" on page 45, we examine the code generated for the WorkflowModel's model, edit, and editor plug-ins. For any Ecore model, the generation of the model, edit, and editor plug-ins is driven by the properties represented in the GenModel created for that model. In this section, we examine those properties, and discuss the effect that changing them has on code generation.

If we examine the GenModel for the WorkflowModel using a text editor, we can see that it is described using XMI. This is because the GenModel is itself an EMF model, so its instances are serialized by default according to the XMI 2.0 production rules [2], as described in 2.3.2, "Default serialization of model instances" on page 66.

Example 2-12 shows the top-level XMI element from the GenModel for the WorkflowModel. As we can see, the GenModel has properties (represented in the XMI as attributes) that identify the model from which the edit, and editor plug-ins are generated, and that specify the name and package of the generated plug-ins. We provide details of the effect that these properties have on code generation in "Top-level GenModel properties" on page 52.

Example 2-12: Top-level element for WorkflowModel GenModel

start example
 <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="/WorkflowModel/src"    editDirectory="/WorkflowModel.edit/src"    editorDirectory="/WorkflowModel.editor/src"    modelPlugin modelName="Workflow"    editPlugin    editorPlugin>    ... </genmodel:GenModel> 
end example

Nested within the top level element of the WorkflowModel's GenModel XMI, we find elements corresponding to each object from the WorkflowModel, with attributes representing the properties specific to each object. The nesting of the contents of a GenModel XMI matches the nesting within the source Ecore model, with elements corresponding to classes, data types, and sub-packages nested within the element corresponding to their containing package; and elements corresponding to references, attributes, and operations nested within the element corresponding to their containing class.

In Example 2-13, we see a fragment of the GenModel for the WorkflowModel that corresponds to the Workflow class.The genClasses element corresponding to the Workflow class contains genFeatures elements that correspond to the name attribute, and to the task and edge references of the Workflow class. The effect on code generation of the properties represented for each class is discussed in "Class-level GenModel properties" on page 55.

Example 2-13: GenModel fragment for EClass Workflow

start example
 <genClasses ecore>    <genFeatures       ecoreFeature="ecore:EAttribute Workflow.ecore#//Workflow/name"/>    <genFeatures property="None" children="true"       ecoreFeature="ecore:EReference Workflow.ecore#//Workflow/task"/>    <genFeatures property="None" children="true"       ecoreFeature="ecore:EReference Workflow.ecore#//Workflow/edge"/> </genClasses> 
end example

Aside: 

If you have installed the org.eclipse.emf.source plug-in, you can take a look at the file GenModel.ecore, which describes the GenModel. The zip file containing the file is usually installed at the following location:

<ECLIPSEHOME>/plugins/org.eclipse.emf.source_<EMFVERSION>/src/org.eclipse.emf.codegen.ecore_<EMFVERSION>/runtime/codegen.ecoresrc.zip

Where <ECLIPSEHOME> is the location where you installed Eclipse, and <EMFVERSION> is the version of the EMF plug-in that you have installed.

While you can control the generation of plug-ins by editing the GenModel XMI directly, you can also edit the GenModel properties with the editor provided by the GenModel plug-in. Figure 2-6 shows the GenModel editor displaying the top-level properties from the GenModel for the WorkflowModel. As the figure shows, the tree view provided by the GenModel editor mirrors the containment hierarchy from the GenModel XMI and the source model, and displays the properties for the selected item in the Properties view. If you do not see the properties, select Window -> Show View -> Other and then select Properties from the Basic item in the tree.

click to expand
Figure 2-6: Top-level GenModel properties for WorkflowModel

An advantage of using the GenModel editor over editing the XMI directly is that the properties are organized by category, as we see in Figure 2-6, where the properties for the WorkflowModel GenModel are categorized according to whether they relate to the generation of the model, edit, or editor plug-ins. There is also a Templates & Merge category that is not shown in the figure, which we discuss in 2.4, "Using JET to customize code generation" on page 79.

You can toggle between the categorized view and a flat view of the properties by clicking the button identified by the tree icon, as shown in Figure 2-7, with the tool tip Show Categories. Here we see the properties for the name attribute of the class Workflow. The property view allows us to view and edit all of the properties associated with each object in the model. The editor provides a brief description of each of the properties, which is displayed in the status bar whenever a property is selected, as shown for the Property Type property. For properties that have a fixed set of values, such as Property Type here, the editor provides a pull-down list from which you may select an alternate value. Notice that the XMI file representing the model may not explicitly persist a property that is unchanged from its default value, as shown in Example 2-13 on page 49, where none of the properties in the Edit category for the name attribute are present in the XMI.

click to expand
Figure 2-7: Using the GenModel editor to edit properties

In addition to specifying code generation properties using the GenModel editor, you may provide values for some of these properties when you initially create or import your model from XMI or annotated Java interfaces. When you use the GenModel wizard to create a GenModel from your model, the values that you supply in your model are used to populate the GenModel, and for any properties for which you do not supply a value, a default value is used instead.

In the following sections, we detail the GenModel properties, organizing them according to the GenModel hierarchy. At each level, we provide a table that outlines the name of the property as it appears in the GenModel editor, the category to which the property belongs in the GenModel editor, the attribute used to represent the property in the GenModel XMI and the default value provided by the GenModel wizard for that property. We also discuss the effect that changing each property from its default has on the generation of the model, edit, and editor plug-ins.

Top-level GenModel properties

The properties represented at the top level for each GenModel are described in Table 2-1.

Table 2-1: Top-level GenModel properties

Property

Category

XMI attribute

Default Value

Copyright Text

All

copyrightText

 

Creation Commands

Edit

creationCommands

true

Edit Directory

Edit

editDirectory

<PROJECT>.edit/src

Editor Directory

Editor

editorDirectory

<PROJECT>.editor/src

Editor Plug-in Class

Editor

editorPluginClass

<basePackage of top-level EPackage><modelName> EditorPlugin

Edit Plug-in Class

Edit

editPluginClass

<basePackage of top-level EPackage><modelName> EditPlugin

Generate Schema

Model

generateSchema

false

Model Directory

Model

modelDirectory

<PROJECT>/src

Model Name

All

modelName

GenModel base filename

Model Plug-in Class

Model

modelPluginClass

 

Model Plug-in ID

All

modelPluginID

<PROJECT>

Non-NLS Markers

All

nonNLSMarkers

false

The copyrightText property provides the value for the final static field copyright in every generated Java class in the model and edit plug-ins. By default, the copyright field is set to be the empty string. Notice that this field is not generated in the classes for the editor plug-in.

The creationCommands property controls whether or not the generated edit plug-in includes support for creating new objects. If creationCommands is false, the generated editor only allows properties of existing objects to be modified, and the menu options for creating new child or sibling objects are not present. If creationCommands is true, in the edit plug-in, each ItemProvider generated from each class in the model contains a method collectNewChildDescriptors, which constructs a list of the types of children objects that can be created. These lists are used by the editor plug-in to construct actions that can be used to create children and sibling objects.

The modelName property is used to construct the default names of the edit, and editor plug-ins. The values of the modelDirectory, editDirectory and editorDirectory properties determine the projects, and path within those projects, into which the plug-ins are generated, while the modelPluginClass, editPluginClass and editorPluginClass properties determine the Java package of each generated plug-in.

The modelPluginID property is used as the plug-in ID of the model plug-in and is referenced from the edit plug-in, which depends on the model plug-in. If you change the value of this property, you need to delete the plugin.xml files from the model and edit plug-ins before regenerating the code, to ensure that they are updated.

Setting the generateSchema property to true means that the XML Schema for the model is generated whenever the model plug-in is generated. When you generate the schemas, you will notice new schema files appear in the project; XMI.xsd and <PackageName>XMI.xsd, where <PackageName> is the name of the top-level package from your model. For example, the XML Schema files generated from the WorkflowModel are XMI.xsd and WorkflowXMI.xsd. XMI.xsd declares XMI elements and attributes that are common to all models, while WorkflowXMI.xsd contains the only element and attribute declarations specific to serializing WorkflowModel instances.

Tip 

For the XML Schema generation to succeed, you must have installed the XSD plug-in available from http://www.eclipse.org/xsd/.

Setting nonNLSMarkers controls whether National Language Support (NLS) comment markers, marking particular strings as non-translatable, are generated in the source of the plug-ins. Example 2-14 shows a code fragment from the toString method from the class PortImpl, generated as part of the model plug-in from the WorkflowModel. We see that the strings name and condition are marked as NON-NLS, that is, that they are not translatable.

Example 2-14: Generated NON-NLS markers

start example
    public String toString() {       ...       result.append(" (name: "); //$NON-NLS-1$       result.append(name);       result.append(", condition: "); //$NON-NLS-1$       result.append(condition);       ...    } 
end example

When nonNLSMarkers is true, strings that are used as keys to lookup resource bundles and strings based on the names of model objects (such as name and condition in this example), are marked as NON-NLS. However, some strings, such as those that represent default values for EString-typed attributes, remain unmarked when this property is true. For more information about internationalizing Eclipse plug-ins, see:

  • http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html

Package-level GenModel properties

For each EPackage in the model, there is a corresponding genPackages element in the GenModel XMI, which is represented in the GenModel editor as an item in the tree view. The properties represented for each package are presented in Table 2-2.

Table 2-2: Package-level GenModel properties

Property

Category

XMI attribute

Default Value

Adaptor Factory

Model

adapterFactory

true

Base Package

All

basePackage

 

Package

Ecore

ecorePackage

EPackage name

Prefix

All

prefix

EPackage name (capitalized)

Resource Type

Model

resource

None

The ecorePackage property identifies the corresponding EPackage from the source model. The prefix property is used to generate the names for the AdapterFactory, Package, Factory and Switch classes generated for the EPackage. The prefix should begin with an upper-case character so that the generated classes have upper-case names.

If a value is specified for basePackage, that value is used as the package prefix for the generated plug-ins. For example, to generate the model interfaces for our WorkflowModel plug-in into the package com.ibm.itso.workflow, we set basePackage for the Workflow package to com.ibm.itso and check that the name of the Workflow package in the WorkflowModel is lower case to ensure that we follow java package naming convention. If you generate the GenModel from a model where the top-level package has a fully qualified Java name, the wizard fills in the basePackage property with the prefix from that package.

Note, if your model contains sub-packages, these are represented in the GenModel as nestedGenPackages elements. The default basePrefix for each nestedGenPackages element is the package name constructed from the basePrefix and ecorePackage properties of the containing genPackages element. If you change the basePrefix for a sub-package, the code generated for the objects directly contained by that sub-package is generated into the package specified by the sub-package's basePrefix and the sub-package name.

The value of adaptorFactory indicates whether an AdapterFactory and Switch is generated for the EPackage, in the corresponding util package.

The resource property indicates whether to generate a Resource and ResourceFactory implementation for the model, and the type of Resource to subclass when doing so. When this property is set to None, as it is by default, the generated editor uses an XMIResource to serialize model instances, as described in 2.3.2, "Default serialization of model instances" on page 66. If resource is set to Basic, a subclass of ResourceImpl is generated in the util package, which can then be modified to customize serialization to any format. Similarly, setting resource to XML or XMI means that the generated ResourceImpl is a subclass of XMLResourceImpl or XMIResourceImpl, respectively, and you can customize these serializations as described in 2.3.5, "Providing a custom resource implementation" on page 75.

Class-level GenModel properties

Classes are represented in the GenModel as genClasses elements. The properties for each class are shown in Table 2-3.

Table 2-3: Class-level GenModel properties

Property

Category

XMI attribute

Default Value

Class

Ecore

ecoreClass

EClass name

Image

Edit

image

true

Label Feature

Edit

labelFeature

 

Provider Type

Edit

provider

Singleton

The ecoreClass property identifies the corresponding EClass from the source model.

The provider property indicates which item provider pattern is used to generate the ItemProvider for this class in the editor plug-in; Singleton, Stateful, or None. Refer to the Item provider implementation classes section, from The EMF.Edit framework and code generator overview, in the Documents section of the EMF project site at: http://www.eclipse.org/emf/ for details of the Singleton and Stateful pattern. If the property is set to None, no Item Provider is generated for the class.

The image property indicates whether an icon is generated for the class in the corresponding ItemProvider, which is returned by the getImage() method.

The labelFeature property identifies the attribute that is used to provide the default label for objects of this type, which is returned by the getText() method in the generated ItemProvider. If this property is not set, then the code generation will look for an attribute called name (or with name as a substring in its name) to use instead, and if that does not exist, it will use the first simple attribute (that is, an attribute that is of a simple type such as EString) from the class.

Feature-level GenModel properties

The GenModel represents each attribute and reference as a genFeatures element in the XMI. The properties for each feature are listed in Table 2-4.

Table 2-4: Feature-level GenModel properties

Property

Category

XMI attribute

Default Value

Children

Edit

children

true for containment references, otherwise false

Feature

Ecore

ecoreFeature

The name of the EAttribute or EReference

Notify

Edit

notify

true for attributes and containment references

Property Type

Edit

property

None for containment/container references, Editable for normal references and attributes, Readonly for features where changeable is false

The corresponding feature (EAttribute or EReference) from the source model is identified by the ecoreFeature property.

The children property indicates whether this feature is considered to be a child of the containing class, for the purposes of constructing the tree view in the editor, and whether the context menu for the parent provides an option to create this feature as a child. Most features are represented as properties, and so children is usually false, however for containment references, children is true by default.

The notify property indicates whether the ItemProvider forwards notifications indicating that the feature has changed. By default, the code generated in the model code notifies whenever any feature changes, however the generated ItemProviders filter these notifications. By default, notifications of changes to attributes and containment references are forwarded, while non-containment reference changes are not.

The property indicates whether this feature is represented as a property on the property sheet, and whether its value can be edited via the property sheet. Features represented as children are usually not included in the property sheet, so it is usual to see containment references with None as the value for property, and attributes and non-containment references with this value set to Editable. Features that have changeable set to false in the Ecore model will be Readonly by default.

GenModel properties for DataTypes

EDataTypes are represented in the GenModel as genDataTypes elements. The ecoreDataType property identifies the associated EDataType from the model. As EDataTypes already reference their implementation class, the GenModel does not represent any other code generation properties for them. Similarly, EEnums are represented in the GenModel by genEnums elements, with an ecoreEnum property referring to the EEnum from the model. The literals are represented by genEnumLiterals elements nested within the corresponding genEnums element, again with a single property, ecoreEnumLiteral, that refers to the EEnumLiteral from the model.

GenModel properties for operations and parameters

Operations are represented as genOperations elements, which contain genParameters elements for each parameter. Apart from the ecoreOperation property of genOperations, and the ecoreParameter property of genParameters identifying the associated model objects, there are no other GenModel properties associated with operations or parameters. If you want to add methods to the generated code, it makes little difference whether you add them to the model first and generate skeletons, or simply add them directly to the generated code. If you do generate them from the model, make sure that you remove the @generated tag when you implement them so that your implementation is not overwritten if you regenerate the code.

Customization example

We can see that the properties at the top-level of the GenModel generally affect the names, packages, and locations of the generated model, edit, and editor plug-ins, while the GenModel properties at the package, class, and feature level affect only the types generated from those model elements. The default values generate three separate plug-ins, such as the plug-ins that we examined in "The generated plug-ins" on page 45. In the following example, we change some of the top-level GenModel properties in order to customize the generated plug-ins.

Our example customizes the code generation so that the model, edit, and editor are generated into a single plug-in, to make it easier to package for distribution. These are the steps that we take to generate a single plug-in called com.ibm.itso.sal330r.workflow, for our WorkflowModel editor:

  1. In our existing WorkflowModel project, we generate the GenModel for the WorkflowModel and open it using the GenModel editor.

  2. We change the modelPluginID to com.ibm.itso.sal330r.workflow, as shown in Figure 2-8. This is the identifier that is used for the plug-in containing the model, edit, and editor code.

    click to expand
    Figure 2-8: Changing the top-level GenModel properties to generate a single plug-in

  3. We edit modelDirectory, editDirectory, and editorDirectory properties so that they are all set to /com.ibm.itso.sal330r.workflow/src. When we generate the plug-ins, the com.ibm.itso.sal330r.workflow project is created if it does not already exist. The code for all three plug-ins is generated to the src directory of this project, and a single plugin.xml is generated to describe the plug-in containing the model, edit, and editor code.

  4. Edit the editPluginClass and editorPluginClass properties, as shown in Figure 2-8, so that they have the same package prefix.

  5. In order to generate the model code into the com.ibm.itso.sal330r.workflow package, we also edit the basePackage property on the workflow package, setting it to com.ibm.itso.sal330r, as shown in Figure 2-9. Notice that the basePackage does not include the package name workflow. When the model code is generated, the name of the EPackage from the model is used to construct the last part of the Java package name.

    click to expand
    Figure 2-9: Changing the basePackage property

  6. Select Generate All from the context menu of the top-level GenModel element to generate the model, edit, and editor code into the com.ibm.itso.sal330r.workflow plug-in. It is important to select Generate All the first time you generate the code, rather than choosing the model, edit, or editor options individually, so that plugin.xml contains all of the required entries for the combined plug-in.

The resulting plug-in is located in the com.ibm.itso.sal330r.workflow project.

Tip 

Be sure to generate from the context menu of the top-level element in the GenModel. Generating from any item lower down in the tree will only generate code associated with that item and its children.

2.2.3 Modifying the generated code

Once you have generated the code for the model, edit, and editor plug-ins, there may still be some customizations that you need to make before you can use it. Common additions that you may make to the model code include implementing methods generated from EOperations, implementing getter and setter methods for volatile features, or adding methods that were not represented in the model.

Important: 

Whenever you modify part of the generated code, be sure to remove the @generated tag, or change it to read @generated NOT in the comment that describes the method, type, or field that you are modifying. If you fail to do this, your changes will be discarded next time you regenerate the code from the model.

Modifying the model plug-in

In the following example, we modify the model code generated from the WorkflowModel to implement the getter and setter methods generated for our volatile attribute id, in WorkflowElementImpl. The id attribute is volatile because we want to generate its value to ensure that it is unique. When we generate the model code, skeletons are generated for the getId() and setId() methods, as shown in Example 2-15.

Example 2-15: Methods generated for volatile feature

start example
 /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public String getId() {    // TODO: implement this method to return the 'Id' attribute    // Ensure that you remove @generated or mark it @generated NOT    throw new UnsupportedOperationException(); } /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ public void setId(String newId) {    // TODO: implement this method to set the 'Id' attribute    // Ensure that you remove @generated or mark it @generated NOT    throw new UnsupportedOperationException(); } 
end example

We modify WorkflowElementImpl to add a method to generate the id, add a field to cache the generated id, and use the method to set the value from within the getId() and setId() method, as shown in Example 2-16. We generate the id in both methods so that the id is never null when it is used.

Example 2-16: Modifying the getID() method

start example
 public abstract class WorkflowElementImpl extends EObjectImpl implements WorkflowElement {    /**     * Prefix used for generated ids     */    protected static final String idPrefix = "w";    /**     * The cached value of the '{@link #getId() <em>id</em>}' attribute.     * <!-- begin-user-doc -->     * <!-- end-user-doc -->     * @see #getId()     *     */    protected String id;    protected static int counter = 0;    ...    /**     * Generate (and cache) an id as needed     */    public String getId() {       if (id == null){          id = generateId();       }       return id;    }    /**     * Generate a random id based on the current time     * @return the generated id     */    public synchronized String generateId(){       long current= System.currentTimeMillis();       return idPrefix + current + counter++;    }    /**     * Set or generate an Id     */    public void setId(String newId) {       if (newId == null && id == null){          id = generateId();       }       else {          id = newId;       }    } } 
end example

We remove the @generated tag from the comments to ensure our methods are not overwritten. Notice that volatile attributes are quite commonly not changeable, and are usually also transient. This means that usually you would not need to cache the value of the attribute or provide a setter implementation. In our case, although the ids are generated, and we don't care what the value of the ids are while the objects are in memory, we use them in the serialization to make the XMI references more readable, which means that the id attribute has to be non-transient and changeable.

Modifying the edit plug-in

A common modification that you might want to make to an ItemProvider generated from a model object is to customize the getText() method. By default, this method returns the type of the object, followed by the value of the label feature for that type, and is used by the generated editor to label each item in the tree view displaying a model. For our WorkflowModel example, although Edges have a name and id, it is more useful to label them by the names of their source and target nodes. We modify the getText() method of EdgeItemProvider as shown in Example 2-17 to provide this functionality.

Example 2-17: The getText() method of EdgeItemProvider

start example
    /**     * This returns the label text for the adapted class.     * <!-- begin-user-doc -->     * <!-- end-user-doc -->     * @generated NOT     */    public String getText(Object object) {       Edge e = (Edge)object;       String label = getString("_UI_Edge_type");       String fromNode = e.getSource().getNode().getName();       String toNode = e.getTarget().getNode().getName();       if (!(fromNode == null || fromNode.length() == 0))          label += " from " + fromNode;       if (!(toNode == null || toNode.length() == 0))          label += " to " + toNode;       return label;    } 
end example

In this case, we must take care, because the features that we are using to label the Edge are non-containment references. Remember from 2.2.2, "Customizing code generation through GenModel properties" on page 47, that notifications of changes to non-containment references are filtered by the ItemProvider and not passed to the editor by default. This means that the label will not be updated to reflect new values for the source or target if they change. We can override this behavior by setting the notify property for the source and target references of Edge in the GenModel to true, and then regenerating the edit code.

You can see the result of the changes in the default WorkflowModel editor in Figure 2-10.

click to expand
Figure 2-10: Editor using modified EdgeItemProvider

[2]For more information, refer to the XML Metadata Interchange (XMI) Specification, Version 2.0, which can be found at: http://www.omg.org/technology/documents/formal/xmi.htm



 < Day Day Up > 



Eclipse Development using the Graphical Editing Framework and the Eclipse Modeling Framework
Eclipse Development Using the Graphical Editing Framework And the Eclipse Modeling Framework
ISBN: 0738453161
EAN: 2147483647
Year: 2004
Pages: 70
Authors: IBM Redbooks

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net