Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "BPMN2-Modeler/DeveloperTutorials/AddingCDATA"

m
Line 59: Line 59:
  
 
Save the ecore file, open your genmodel and generate the model code.
 
Save the ecore file, open your genmodel and generate the model code.
 +
 +
== Edit The Model Code ==
 +
Now open the java implementation class for MetaData. You should see that the generated getValue() and setValue() methods look like this:
 +
 +
<pre>
 +
    /**
 +
    * <!-- begin-user-doc -->
 +
    * <!-- end-user-doc -->
 +
    * @generated
 +
    */
 +
    public String getValue() {
 +
        // TODO: implement this method to return the 'Value' attribute
 +
        // Ensure that you remove @generated or mark it @generated NOT
 +
        throw new UnsupportedOperationException();
 +
    }
 +
 +
    /**
 +
    * <!-- begin-user-doc -->
 +
    * <!-- end-user-doc -->
 +
    * @generated
 +
    */
 +
    public void setValue(String newValue) {
 +
        // TODO: implement this method to set the 'Value' attribute
 +
        // Ensure that you remove @generated or mark it @generated NOT
 +
        throw new UnsupportedOperationException();
 +
    }
 +
</pre>
 +
 +
Replace these with the following:
 +
 +
<pre>
 +
 +
    /**
 +
    * <!-- begin-user-doc -->
 +
    * <!-- end-user-doc -->
 +
    * @generated NOT
 +
    */
 +
    public String getValue() {
 +
        if (mixed != null) {
 +
            StringBuilder result = new StringBuilder();
 +
            for (FeatureMap.Entry cur : mixed) {
 +
                switch (cur.getEStructuralFeature().getFeatureID()) {
 +
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__CDATA:
 +
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__TEXT:
 +
                    result.append(cur.getValue());
 +
                    break;
 +
 +
                default:
 +
                    break;
 +
                }
 +
            }
 +
            return result.toString();
 +
        }
 +
 +
        return null;
 +
    }
 +
 +
    /**
 +
    * <!-- begin-user-doc -->
 +
    * <!-- end-user-doc -->
 +
    * @generated NOT
 +
    */
 +
    public void setValue(String newValue) {
 +
        getMixed().clear();
 +
        FeatureMap.Entry cdata = FeatureMapUtil.createCDATAEntry(newValue);
 +
        getMixed().add(cdata);
 +
    }
 +
</pre>
 +
 +
Don't forget to add "NOT" to the @generated annotation before each method to prevent having this code overwritten when you regenerate this file.
 +
 +
That's really all there is to it. To see how to handle creation, editing and deletion of a metaData element see the [https://git.eclipse.org/c/bpmn2-modeler/org.eclipse.bpmn2-modeler.git/tree/examples/plugins/org.eclipse.bpmn2.modeler.examples.customtask/src/org/eclipse/bpmn2/modeler/examples/customtask/MyDescriptionPropertySection.java?h=luna Property Detail Composite implementation] in the CustomTask sample plugin.

Revision as of 21:31, 10 March 2015

Introduction

There have been a lot questions on the BPMN2 Modeler Forum lately about serialization of BPMN2 extension elements, specifically concerning the serialization of text values in a CDATA block instead of an attribute value.

This tutorial deals more with the implementation details in EMF, rather than focusing on a specific BPMN2 Modeler extension API feature. This functionality has already been added to the Custom Task example plugin, so this tutorial will show how it was done.

For our CustomTask target runtime we wanted the ability to add an optional extension element, named "metaData" to any BaseElement type. Recall that the schema for BaseElement looks like this:

<xsd:element name="baseElement" type="tBaseElement"/>
<xsd:complexType name="tBaseElement" abstract="true">
  <xsd:sequence>
    <xsd:element ref="documentation" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="extensionElements" minOccurs="0" maxOccurs="1"/>
  </xsd:sequence>
  <xsd:attribute name="id" type="xsd:ID" use="optional"/>
  <xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:complexType>

Our requirement is to be able to add an element called "metaData" into the <extensionElements> list. This "metaData" element should have a "name" attribute and a text "value", which should be serialized as CDATA. Something like this for example:

    <bpmn2:extensionElements>
      <mm:metaData name="info"><![CDATA[Here's some information about this process.]]></mm:metaData>
    </bpmn2:extensionElements>

Start With The Ecore

Open the MyModel.ecore with the EMF Ecore editor and create a new EClass called MetaData.

BPMN2-Modeler-AddingCData-MyModel-ecore.jpg

Add an EAnnotation child to this EClass and set the "Source" to "http:///org/eclipse/emf/ecore/util/ExtendedMetaData".

BPMN2-Modeler-AddingCData-ExtendedMetaData-properties.jpg

Add a new Details Entry to this ExtendedMetaData element and set the "Key" to "kind" and "Value" to "mixed"

BPMN2-Modeler-AddingCData-ExtendedMetaData-details.png

This will define the "metaData" element as having mixed content. Add another Details entry and set Key="namespace" and Value="##targetNamespace". This declares that the "metaData" element belongs to the same namespace as that defined by the model.

Add an EAttribute named "mixed" to the MetaData class. This will represent the mixed contents of the serialized element and will hold the content for the "value" attribute. Create an ExtendedMetaData entry for "mixed" and add Details entries as shown in the MyModel.ecore above. Set the EType for "mixed" to "FeatureMap$Entry" and set its upper bound to "unbounded" (-1). The Properties for "mixed" should look like this:

BPMN2-Modeler-AddingCData-ExtendedMetaData-mixed.png

Add a EString attribute to MetaData and call it "name". Add another EString attribute called "value", but set the "Volatile" and "Transient" flags "true". The first will generate code that, when invoked from Java, will throw an UnsupportedOperationException. This will remind you that the bodies for MetaData#getValue() and setValue() must be implemented (more about this later.) The "Transient=true" condition will ensure that the "value" attribute itself will not be serialized as an attribute, but it will appear as CDATA. In other words, if we had "Transient=false" the generated XML would look like this:

    <bpmn2:extensionElements>
      <mm:metaData name="info" value="Here's some information about this process."><![CDATA[Here's some information about this process.]]></mm:metaData>
    </bpmn2:extensionElements>

The "value" properties should look like this:

BPMN2-Modeler-AddingCData-ExtendedMetaData-value.png

Save the ecore file, open your genmodel and generate the model code.

Edit The Model Code

Now open the java implementation class for MetaData. You should see that the generated getValue() and setValue() methods look like this:

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

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

Replace these with the following:


    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated NOT
     */
    public String getValue() {
        if (mixed != null) {
            StringBuilder result = new StringBuilder();
            for (FeatureMap.Entry cur : mixed) {
                switch (cur.getEStructuralFeature().getFeatureID()) {
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__CDATA:
                case XMLTypePackage.XML_TYPE_DOCUMENT_ROOT__TEXT:
                    result.append(cur.getValue());
                    break;

                default:
                    break;
                }
            }
            return result.toString();
        }

        return null;
    }

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated NOT
     */
    public void setValue(String newValue) {
        getMixed().clear();
        FeatureMap.Entry cdata = FeatureMapUtil.createCDATAEntry(newValue);
        getMixed().add(cdata);
    }

Don't forget to add "NOT" to the @generated annotation before each method to prevent having this code overwritten when you regenerate this file.

That's really all there is to it. To see how to handle creation, editing and deletion of a metaData element see the Property Detail Composite implementation in the CustomTask sample plugin.

Back to the top