2.3 Model instances and serialization

 < Day Day Up > 



2.3 Model instances and serialization

In this section we examine how to create and serialize model instances. We provide examples that illustrate how to customize serialization and discuss the effect that different modeling techniques can have on the way in which instances are serialized.

2.3.1 Creating model instances

We can use the code generated for the model plug-in from our model to create instances of that model.

Example 2-18 shows how we create a Workflow instance and a Task instance using the WorkflowFactory. The example also demonstrates how we use the methods from the generated code to set properties such as the name on the Task, and maintain references, in this case adding the Task to the nodes of the Workflow, and adding an InputPort and OutputPort to the Task.

Example 2-18: Creating instances

start example
 Map registry = EPackage.Registry.INSTANCE; String workflowURI = WorkflowPackage.eNS_URI; WorkflowPackage wfPackage = (WorkflowPackage) registry.get(workflowURI); WorkflowFactory wfFactory = wfPackage.getWorkflowFactory(); Workflow workflow = wfFactory.createWorkflow(); // add a Task to the workflow Task t1 = wfFactory.createTask(); workflow.getNodes().add(t1); t1.setName("Task 1"); // add an input port and an output port to the Task t1.getInputs().add(wfFactory.createInputPort()); t1.getOutputs().add(wfFactory.createOutputPort()); ... 
end example

If we were using the reflective API to manipulate our instance objects, we would replace methods such as setName() and getNodes() that are specific to the WorkflowModel with generic eSet() and eGet() methods, for example: t1.eSet(WorkflowPackage.eINSTANCE.getTask_Name(), "Task 2") to set the name of the Task.

An interesting application of using the reflective APIs is to work with dynamic models, that is, to work with Ecore models as in-memory objects rather than generating code from the model and using the generated classes. Example 2-19 shows an sample of how we can create instances of the Ecore model to represent a very basic model of Workflow.

Example 2-19: Creating a dynamic model

start example
 // Create the Workflow Package EPackage workflowPackage = EcoreFactory.eINSTANCE.createEPackage(); // create the Port class EClass portClass = EcoreFactory.eINSTANCE.createEClass(); portClass.setName("Port"); EClass inputPortClass = EcoreFactory.eINSTANCE.createEClass(); inputPortClass.setName("InputPort"); // set up inheritance inputPortClass.getESuperTypes().add(portClass); // create the Task class EClass taskClass = EcoreFactory.eINSTANCE.createEClass(); taskClass.setName("Task"); // add name attribute to Task EAttribute taskNameAttr = EcoreFactory.eINSTANCE.createEAttribute(); taskNameAttr.setName("name"); taskNameAttr.setEType(EcorePackage.eINSTANCE.getEString()); taskClass.getEAttributes().add(taskNameAttr); // set up the reference between Task and InputPort EReference taskToInputPortRef = EcoreFactory.eINSTANCE.createEReference(); taskToInputPortRef.setUpperBound(-1); taskToInputPortRef.setLowerBound(1); taskToInputPortRef.setEType(inputPortClass); taskClass.getEReferences().add(taskToInputPortRef); ... // add the classes to the package workflowPackage.getEClassifiers().add(taskClass); workflowPackage.getEClassifiers().add(portClass); workflowPackage.getEClassifiers().add(inputPortClass); ... 
end example

We can create instances of this model using the reflective API, as Example 2-20 demonstrates.

Example 2-20: Using the reflective API to create dynamic model instances

start example
 EFactory wfFactory = workflowPackage.getEFactoryInstance(); EObject task1 = wfFactory.create(taskClass); task1.eSet(taskNameAttr, "Task 1"); 
end example

Obviously, this dynamic approach only works for some applications — if you are using a model where you would normally customize the code generated from the model, for example, to implement EOperations, then this approach is not suitable.

2.3.2 Default serialization of model instances

When you create and serialize instances of an Ecore model, they are serialized by default as XMI 2.0. This section provides examples illustrating how EMF objects are represented in the XMI.

For a more complete description of XMI 2.0, please refer to the XML Metadata Interchange (XMI) Specification, Version 2.0, found at:

  • http://www.omg.org/technology/documents/formal/xmi.htm

Note 

We have already seen several examples of XMI representing model instances. The Ecore model is itself an EMF model, so the Ecore documents describing the models that we created in 2.1, "EMF modeling techniques" on page 30, were all examples of the default serialization of Ecore model instances to XMI.

All of the example serializations discussed in this section can be found in the Serializations directory in the examples provided for this section.

Example 2-21 shows XMI representing a Workflow instance, representing a Workflow containing a Comment and two Tasks, each with an input, output, and fault port, and an Edge connecting them. You can load this example from the file SimpleXMIInstance.workflow.

Example 2-21: Default XMI serialization of a Workflow instance

start example
 <workflow:Workflow xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:workflow="http://www.redbooks.ibm.com/sal330r/workflow">    <nodes xsi:type="workflow:Task" name="Task 1" x="31" y="82"        isStart="true">       <outputs xsi:type="workflow:FaultPort" name="fault"          />       <outputs name="output"  edges="w105966226568762"/>       <inputs name="input" />    </nodes>    <nodes xsi:type="workflow:Task" name="Task 2" x="265" y="81"        isFinish="true">       <outputs xsi:type="workflow:FaultPort" name="fault"          />       <outputs name="output" />       <inputs name="input"  edges="w105966226568762"/>    </nodes>    <edges  target="w105966226568766"       source="w105966226568761"/>    <comments comment="This is a sample Workflow instance" x="24" y="20"       /> </workflow:Workflow> 
end example

As the example shows, the Workflow object is serialized to an element in the XMI, with attributes representing its EAttributes and non-containment EReferences. Containment EReferences are represented as elements, with the content of the contained object contained inline, as we see for the nodes elements from the example. When the reference can be to objects of different types (that is, to different subtypes of the referenced class), the xsi:type attribute is also serialized to identify the type of the object represented by the element.

Non-containment EReferences, such as the references between each edge and its target and source Ports, are represented as strings, that identify the object being referenced. By default, the strings used to identify other objects are based on the containing resource, type and position of the referenced object. Example 2-22 shows how positional references are used to serialize a Workflow. In Example 2-21, the id attribute is used instead of positional references. This is because the id property for that attribute it set to true in the model. If the id property is true for one of the attributes, references will refer to objects using the value of that attribute, if it is set, or use a positional reference if the id attribute is not set. If you are using an id attribute, it is important to ensure that its values are unique within a resource, so that the ids in the XMI are unique within the document, as required by the standard.

Example 2-22: Positional references

start example
 <workflow:Workflow xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:workflow="http://www.redbooks.ibm.com/sal330r/workflow">    <nodes xsi:type="workflow:Task" name="Task 1">       <outputs name="output" edges="//@edges.0"/>       <inputs name="input"/>    </nodes>    <nodes xsi:type="workflow:Task" name="Task 2">       <outputs name="output1"/>       <inputs name="input1" edges="//@edges.0"/>    </nodes>    <edges target="//@nodes.1/@inputs.0" source="//@nodes.0/@outputs.0"/> </workflow:Workflow> 
end example

You can customize the way that references are represented in the XMI by overriding the eURIFragmentSegment() and eObjectForURIFragmentSegment() methods in your model implementation classes. The default positional references are provided by these methods in EObjectImpl, which is a superclass of all the implementation classes generated from a model.

When the references are to objects contained by another resource, then the scheme for finding the file that is the serialization of the resource (for example, http) and the name of the file is also added to the reference. An example of this is when we use cross-package references and serialize the containing Ecore EPackages into separate files, such as the following snippet taken from Example 2-4 on page 37:

    <eReferences name="model"    eType="ecore:EClass WorkflowWithCommonSupertype.ecore#//Task"/> 

Each model instance that is created by the generated editor plug-in is added to a Resource, which can later be used to serialize that instance. Within any EMF-based application, we can use an XMIResource to serialize or deserialize instance objects. In the sample application discussed in Chapter 7, "Implementing the sample" on page 203, we use XMIResources to contain WorkflowModel instances. To create or get each resource, we first create a ResourceSet, as Example 2-23 shows.

Example 2-23: Set up the ResourceSet

start example
 // Initialize the workflow package WorkflowPackageImpl.init(); // Register the XMI resource factory for the .workflow extension Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; Map m = reg.getExtensionToFactoryMap(); m.put("workflow", new XMIResourceFactoryImpl()); // Obtain a new resource set ResourceSet resSet = new ResourceSetImpl(); 
end example

ResourceSets are used to group related Resources. A Resource can contain instances of any object from a model, and a ResourceSet is used to group related Resources, that is, Resources that contain objects that reference each other. For the Workflow example, we use Resources to contain Workflow instances. We can use the ResourceSet created in Example 2-23 to create a new Resource as shown in Example 2-24.

Example 2-24: Create an XMIResource

start example
 // Create a resource Resource resource =    resSet.createResource(URI.createPlatformResourceURI(path.toString())); 
end example

If we want to load from an existing resource, we use the getResource() method instead, as shown in Example 2-25.

Example 2-25: Load an XMIResource

start example
 // Get a resource Resource resource =    resSet.getResource(URI.createPlatformResourceURI(path.toString()),true); 
end example

Once we have the resource, we can add objects to the contents of the resource. Objects contained by the same resource will be serialized to the same file. Example 2-26 shows how we create and add a Workflow object to a resource.

Example 2-26: Add a model object to a resource

start example
 Workflow workflow = wfFactory.createWorkflow(); resource.getContents().add(workflow); 
end example

Many models are based on an inheritance hierarchy, with a single top-level container. One of the advantages of this approach is that you need only add the top-level object to the resource explicitly. All of the other objects contained in the hierarchy will be serialized as elements within that top-level element. If you are using a model without a top-level container, then any objects that are not contained need to be added to the Resource explicitly.

2.3.3 Using the XSD plug-in to customize serialization

In this section, we demonstrate how to use a custom serialization to XML, by annotating our model with information used by the XSD plug-in.

Whenever we create an Ecore model from an XML Schema using the XSD plug-in, annotations that describe how each object is serialized to XML are added to the model, so that serialized model instances conform to the source schema. Use of these annotations is not limited to models imported from XML Schema; we show how to use the same annotations on any Ecore model to control how its instances are serialized.

Note 

Although the XML produced by using techniques described in this section may look very similar to the XMI described in 2.3.2, "Default serialization of model instances" on page 66, it is important to notice that it does not conform to the XMI 2.0 standard.

We make the following changes to improve the readability of XML representing WorkflowModel instances:

  • Use an XML element instead of an XML attribute to represent EAttributes that potentially have lengthy values, including:

    • comment from WorkflowElement

    • transformExpression from Transformation

    • condition from ConditionalOutputPort

    • whileCondition from LoopTask

  • Use the singular form of the name of multi-valued containment EReferences to prevent the plural form being used for an elements that represent single objects. Notice that we do not make this change for non-containment EReferences, as the default serialization is to an XML attribute that represents the entire list of values, and so using the plural form of the name is appropriate.

  • For example, within Workflow:

    • comments becomes comment

    • edges becomes edge

    • nodes becomes node

  • Change the Workflow element to be lower case, to provide consistent capitalization throughout the document.

We begin by annotating the workflow EPackage, as shown in Example 2-27, indicating to the XSD plug-in that instances of this package use elements and attributes from the namespace http://www.redbooks.ibm.com/sal330r/workflowXSD. The annotations on the objects contained by the package indicate how each object maps to elements and attributes from this namespace.

Example 2-27: XSD annotation on workflow EPackage

start example
 <ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" nsPrefix="workflow"    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="workflow"    nsURI="http://www.redbooks.ibm.com/sal330r/workflowXSD">    <eAnnotations source="http:///org/eclipse/emf/mapping/xsd2ecore/XSD2Ecore">       <details key="representation" value="schema"/>       <details key="targetNamespace"          value="http://www.redbooks.ibm.com/sal330r/workflowXSD"/>    </eAnnotations>    ... existing content ... </ecore:EPackage> 
end example

Example 2-28 shows the eAnnotations element we use to annotate the comment EAttribute of WorkflowElement, to indicate that it should be represented as an element, rather than as an attribute. This is achieved by setting the value of the representation key to element. To force serialization as an attribute, we would use the value attribute instead. We add similar eAnnotations to the eAttributes elements representing transformExpression, condition and whileCondition so that they are also represented as XML elements.

Example 2-28: XSD annotation on comment EAttribute

start example
 <eAttributes name="comment" eType="ecore:EDataType    http://www.eclipse.org/emf/2002/Ecore#//EString">    <eAnnotations       source="http:///org/eclipse/emf/mapping/xsd2ecore/XSD2Ecore">       <details key="representation" value="element"/>       <details key="name" value="comment"/>       <details key="targetNamespace"/>    </eAnnotations> </eAttributes> 
end example

We use a similar annotation to change the names of elements used to represent EReferences with pluralized names. For example, to use an element called node instead of nodes to represent each node contained by a Workflow, we add the EAnnotation shown in Example 2-29. We provide the new element name node as the value of the name key. We add similar annotations for all of the other multi-valued containment EReferences in our model.

Example 2-29: XSD annotation on nodes EReference

start example
 <eReferences name="nodes" eType="#//WorkflowNode" upperBound="-1"    containment="true" eOpposite="#//WorkflowNode/workflow">    <eAnnotations source="http:///org/eclipse/emf/mapping/xsd2ecore/XSD2Ecore">       <details key="representation" value="element"/>       <details key="name" value="node"/>       <details key="targetNamespace"/>    </eAnnotations> </eReferences> 
end example

We use the same technique to ensure that a lower-case element name is used for Workflow, however we have to be careful to make sure we specify the targetNamespace correctly, as the workflow element is the top-level element of our XML instance documents, so we cannot rely on XML namespace scoping for this value. Because we have constraints in the WorkflowModel that mean that all other objects are contained either directly or indirectly by a Workflow, we do not have to specify targetNamespace for any other elements, however, if you are using this technique to customize serialization for other models, make sure you specify this value for any elements that could appear as the top-level element in a serialized instance. Example 2-30 shows how we annotate the eClassifiers element representing the Workflow class. The targetNamspace that we specify in this annotation should match the nsURI of the containing package exactly.

Example 2-30: XSD annotation on Workflow EClass

start example
 <eClassifiers xsi:type="ecore:EClass" name="Workflow"    eSuperTypes="#//WorkflowElement">    <eAnnotations source="http:///org/eclipse/emf/mapping/xsd2ecore/XSD2Ecore">       <details key="representation" value="element"/>       <details key="name" value="workflow"/>       <details key="targetNamespace"          value="http://www.redbooks.ibm.com/sal330r/workflowXSD"/>    </eAnnotations>    ... existing content ... </eClassifiers> 
end example

Having annotated our model, we re-generate the model plug-in as follows:

  1. Create or reload the GenModel from the annotated WorkflowModel, as described in "Java annotation and the code generation process" on page 24. To reload, select Reload... from the context menu that appears when you right-click the GenModel file in the Navigator or Package Explorer view, and then open the GenModel file.

  2. We modify the GenModel so the regenerated code supports our customizations. Refer to 2.2.2, "Customizing code generation through GenModel properties" on page 47 for more information about setting properties in the GenModel. Select the workflow package from the GenModel tree and set Resource Type to XML.

  3. Save the GenModel and then select Generate Model Code from the right-click context menu of the top-level element in the GenModel. You may wish to select Generate All instead if you do not have an up-to-date editor generated from your model. If adding these annotations is the only change that you have made to the model since generating the edit, and editor plug-ins, you do not need to regenerate them.

The model plug-in now includes code that supports serializing to our custom XML syntax. When we run our editor and create new model instances as described in Chapter 1, "Introduction to EMF" on page 3, the object instances are represented as elements or attributes according to the annotations that we added to the model. If we take a look at a new instance in a text editor, such as the instance shown in Example 2-31, and compare this to the default serialization shown in Example 2-21, we can see evidence of the changes that we have made to the serialization format.

Example 2-31: Custom serialization of a Workflow instance

start example
 <workflow:workflow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:workflow="http://www.redbooks.ibm.com/sal330r/workflowXSD"    >    <node xsi:type="workflow:Task" name="Task 1" x="31" y="82"        isStart="true">       <output xsi:type="workflow:FaultPort" name="fault"          />       <output name="output"  edges="w105966226568762"/>       <input name="input" />    </node>    <node xsi:type="workflow:Task" name="Task 2" x="265" y="81"        isFinish="true">       <output xsi:type="workflow:FaultPort" name="fault"          />       <output name="output" />       <input name="input"  edges="w105966226568762"/>    </node>    <edge  target="w105966226568766"       source="w105966226568761"/>    <comment x="24" y="20" >       <comment>This is a sample Workflow instance</comment>    </comment> </workflow:workflow> 
end example

You can find the completed annotated model in the WorkflowXSD folder in the examples for this section. This example demonstrates how to control whether model objects are serialized as XML elements or attributes, and allows us to provide names of our choosing for those elements and attributes. There are other annotations that are used by XSD to control feature-order and map XML Schema types to model objects, as discussed in 2.1.2, "Migrating existing models" on page 40, which you may also use to customize the serialization further.

2.3.4 Customizing XMI serialization using an XMLMap

When we customize the serialization using XSD annotations, we are using the XSD plug-in to generate an XMLMap that specifies the mapping between model objects and their serialization. We can perform similar customizations when we serialize without annotating the model.

The XMI 2.0 production rules allow features to be serialized either as elements or attributes. We can control whether each feature is serialized as an element or as an attribute by creating an XMLMap and adding appropriate mappings, as the following example illustrates. You can find the code for this example in the XMLMapExample directory in the examples for this section.

In this example, we change the serialization of the comment attribute of WorkflowElement, so that an XML element rather than an attribute is used to represent the value. We modify the execute() method within the WorkspaceModifyOperation in the doSave() method of the generated editor as shown in Example 2-32, to customize the serialization.

Example 2-32: Using an XMLMap to customize serialization of XMI

start example
 XMLMapImpl map = new XMLMapImpl(); XMLInfoImpl x = new XMLInfoImpl(); x.setXMLRepresentation(XMLInfoImpl.ELEMENT); map.add(WorkflowPackage.eINSTANCE.getWorkflowElement_Comment(), x); Map options = new HashMap(); options.put(XMLResource.OPTION_XML_MAP, map); Resource savedResource =    (Resource)editingDomain.getResourceSet().getResources().get(0); savedResources.add(savedResource); savedResource.save(options); 
end example

We perform the following steps to customize the serialization of a type or feature from the model:

  1. Create an XMLMap to store the information about mapping the model to XML.

  2. For each model object with a custom serialization:

    1. Create an XMLInfo and use the setName(), setTargetNamespace() and setXMLRepresentation() method to specify the how the object is represented in the XML.

    2. Add the XMLInfo to the XMLMap, using the object for which you want to customize serialization as the key. We do this in the example with: map.add(WorkflowPackage.eINSTANCE.getWorkflowElement_Comment(), x);

  3. Put the XMLMap as the OPTION_XML_MAP in the options map that you use to save the resource.

Use the setName() method on the XMLInfoImpl to customize the name of the element or attribute tag used in the XML, and setTargetNamespace() to set the namespace for that element or attribute.

Use setXMLRepresentation() to specify whether the object is represented as an ELEMENT, ATTRIBUTE or CONTENT. Specifying CONTENT results in the value of object being contained directly by its parent. For example, we might use CONTENT to represent the condition attribute of a ConditionalOutputPort so that serialized instances look something like this:

    <outputs xsi:type="workflow:ConditionalOutputPort" >    This is the condition    </outputs> 

instead of looking like this:

    <outputs xsi:type="workflow:ConditionalOutputPort"  condition="This    is the condition"/> 

2.3.5 Providing a custom resource implementation

When we use the XSD plug-in to customize serialization, we are using an XMLResource to contain our model objects rather than an XMIResource. If we set the Resource Type property of a package to Basic, XMI, or XML in the GenModel, when we generate the model plug-in from the model, a ResourceImpl and ResourceFactoryImpl are generated for our model in the util package. By modifying the implementation of the ResourceImpl generated for our model, we can customize the serialization. If we have chosen XMI or XML as the Resource Type, the generated ResourceImpl will be a subclass of XMIResource or XMLResource, respectively. We can override methods in that subclass to customize serialization to XMI or XML. If we have chosen to use a Basic Resource Type, then we can serialize to any format by providing the necessary methods to implement ResourceImpl.

Customizing XMI serialization

When customizing XMI serialization, it is important to remember that if you customize the serialization format too much, it will no longer be standard XMI. However, there are some customizations that you can make without breaking conformance to the XMI 2.0 standard. One such customization is to use an element instead of an attribute to represent features, as we demonstrate in 2.3.4, "Customizing XMI serialization using an XMLMap" on page 74.

Another change that you can make while still complying with the standard is to modify how ids are generated in the serialization. Instead of using an attribute with the id property set to true in the model, you may wish to generate ids for all elements in the serialization. Although the ids are not accessible from the model, the advantage of generating them is that you can ensure that they remain unique. Be aware, however, that generating ids means that elements can potentially have a different id each time they are serialized.

The ids are mapped to objects from the model by the resource, which uses a map to map ids to each EObject. You can assign ids specifically to particular objects before you serialize by using the setID() method on the resource, as shown in Example 2-33.

Example 2-33: Set object ids via setID()

start example
 Resource resource = ... EObject myobject = .... resource.setId(myobject, "id1"); 
end example

If you want ids to be generated automatically for your objects, you can override the getID() in your resource implementation to do this, as Example 2-34 shows.

Example 2-34: Override getId() to generate ids

start example
 public String getId(EObject obj){    String id = super.getID(obj);    if (id == null){       id = generateID();       setID(obj,id);    }    return id; } 
end example

Customizing XML serialization

The XML that we generated in 2.3.3, "Using the XSD plug-in to customize serialization" on page 70, used the names of references to contained objects for the XML elements representing those objects. A different representation would be to use a name that identifies the type of the reference, particularly in a model where there is usually only a single reference between objects of each type.

The mapping of element and attribute names to model objects is taken care of by an XMLHelper. We provide our own custom XMLHelper, to override the default names for references, replacing reference names with the name of the type instead. Example 2-35 shows how we override this method in our XMLHelper implementation.

Example 2-35: Customized XMLHelper

start example
 public class WorkflowXMLHelperImpl extends XMLHelperImpl implements XMLHelper {    ...    public String getName(ENamedElement obj) {       XMLResource.XMLInfo info = null;       if (xmlMap != null) {          info = xmlMap.getInfo(obj);       }       if (info != null && info.getName() != null) {          return info.getName();       } else {          if (obj instanceof EReference          && ((EReference) obj).getEType() != null)            return ((EReference) obj).getEType().getName();          else             return obj.getName();       }    } } 
end example

Note 

When there are multiple references to a type from the same object, we have to be careful, for example in the case of CompoundTask, because it has two references to Workflow, we have to be able to distinguish between the two, so we might need to add additional information to the serialization to do this. Generally you would only want to use a serialization such as this one if the type implied the reference.

To use the XMLHelper from our XMLResourceImpl, we simply override the method that creates the helper, to create an instance of our WorkflowXMLHelper instead, as Example 2-36 shows.

Example 2-36: Overriding the createXMLHelper() method

start example
    protected XMLHelper createXMLHelper()    {       return new WorkflowXMLHelperImpl(this);    } 
end example

The file XMLResourceCustomization.workflow contains an example of a Workflow serialized using WorkflowXMLResource.

So far we have only dealt with serializing to the custom format, we would also have to override the getFeatureWithoutMap() method to map the types back to features, however we leave this an exercise for the reader.

Customizing XMLHelper allows us to use the names of the types of the references for element names, however because XMLHelper is creating names from the model itself, rather than from instances, it cannot create specific type names for subtypes. An example of using more specific type names for the WorkflowModel would be to use element names FaultPort or ConditionalOutputPort instead of just using OutputPort for those types, or to use Task, Comment or Choice instead of WorkflowNode, such as the fragment shown in Example 2-37.

Example 2-37: A more readable representation of contained objects

start example
 <Task name="Task 2" x="265" y="81"  isFinish="true">       <FaultPort name="fault" />       <OutputPort name="output" />    ... </Task> 
end example

The serialization would produce such elements if you added explicit references to each class with specific names for each reference, in the same way that we already have specific references to OutputPort and InputPort rather than a general reference to Port.

However, then you would need to maintain all of these references separately or lose the benefits of polymorphism, and your model would be cluttered. However, we could implement such a serialization by providing our own subclasses of XMLSaveImpl and XMLLoadImpl and use them within WorkflowResourceImpl, as these are the classes that actually serialize our instances, and override methods such as saveElement() to provide a more specific name.

These examples are provided to give you an idea of the types of things you can customize by providing your own XMLHelper, XMLSave or XMLLoad implementations. You may choose to override the methods from those classes to produce any XML serialization.

Other serializations

To serialize to other formats, all you need to do is to implement your own versions of the doSave() and doLoad() methods in your ResourceImpl subclass.



 < 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