Content authoring demystified:

Authoring Rational Software Architect patterns and transforms

In this article, we will show how you can create a simple pattern and transform that leverage Java Emitter Templates (JET) to generate artifacts from the model. We will show how you can unit test them using IBM® Rational® Software Architect (RSA). Finally, we will show you how to package the pattern, transform and JET Templates into an asset so that they can be published to a repository for reuse.

Christina Lau, Senior Technical Staff Member, IBM Canada Ltd.

Christina LauChristina Lau is a Senior Technical Staff Member at IBM. Christina is an architect on the On Demand Development team focusing on next-generation technologies for the IBM On Demand Operating Environment. You can reach Christina at clau@ca.ibm.com


developerWorks Contributing author
        level

Jim Bonanno (bonanno@us.ibm.com), Senior Software Engineer, IBM Raleigh Lab

Jim BonannoJim Bonanno is a senior programmer at IBM working for the On Demand Development team. Jim's previous role was responsible for integrating the Jakarta Struts framework into the WebSphere Portal product. You can reach Jim at bonanno@us.ibm.com.



01 November 2005 (First published 01 November 2005)

Before you start

You should visit the Pattern Solutions page on developerWorks (see Resources) and learn about the role of Pattern Solutions and to download some of the IBM Pattern assets (e.g. Enterprise Patterns Asset) in order to get familar with the overall end user experience.

About this article

In this article, you will learn how to:

  1. Create a plug-in project for your pattern or transform
  2. Create the skeleton of a pattern using the New Pattern wizard
  3. Implement the pattern
  4. Create or extend an existing transform
  5. Create JET Template
  6. Integrate JET Templates with Transform
  7. Unit test your pattern and Transform
  8. Package the asset
  9. Other useful tips and techniques

The frameworks that are described in this article are used extensively in the Enterprise Patterns, WebSphere Platform Messaging Patterns, and the State Oriented Portlet Patterns assets. We will refer to the source code included in those assets as examples. A simple Getter Setter example will also be used throughout the article to illustrate the basic concepts.

Prerequisites

To run the examples in this article, you need to install Rational Software Architect 6.0.0.1 or later versions.


Create a plug-in project for your pattern or transform

Create a new plug-in for your RSA pattern or transform. Multiple patterns and transforms can be packaged together into a Reusable Asset Specification (RAS) asset and be grouped together under the same Pattern Group Name in the Pattern Explorer.

Eclipse plug-ins

To create a new plugin, go to the Plug-in Development perspective, and use the New Plug-in Project wizard as shown in Figure 1. There are many articles on eclipse.org (see Resources) that explain how to use the Plug-in Development Environment (PDE) to build your own plug-ins.

Figure 1. New Plug-in Project wizard
New Plug-in Project wizard

Creating a plug-in for RSA pattern authoring

If you want to create a RSA pattern, then select the project template Plug-in with Patterns to create a plug-in project pre-configured for RSA pattern development as shown in Figure 2.

Figure 2. Plug-in with Patterns template
Plug-in with Patterns template

Creating a plugin for RSA tranform authoring

If you want to create a RSA transform, then select the project template Plug-in with Transformation to create a plugin project pre-configured for RSA transform development as shown in Figure 3.

Figure 3. Plug-in with Transformation template
Plug-in with Transformation template

RSA Pattern Plug-in project

If you select to create a Plug-in with Patterns project, after you completed the wizard, an Eclipse plug-in project that extends the patterns frameworks will be automatically generated for you--see Figure 4. You can now use the New Pattern wizard to help you author a RSA Pattern.

Figure 4. My First Pattern Plugin
First Pattern Plugin

Create the skeleton of a pattern

RSA Patterns are added to the Pattern Explorer and allow you to interactively apply them to UML models. RSA provides a number of wizards that will assist you in your pattern construction. In the early design phases of your patterns, you will typically use the Pattern Authoring View to quickly prototype your pattern specifications including their names, overview diagrams and pattern parameters--see Figure 5.

Figure 5. Pattern Authoring View
Pattern Authoring View

Create a new pattern

To create a new pattern, invoke the New Pattern wizard as shown in Figure 6.

Figure 6. New Pattern wizard
New Pattern wizard

Pattern Parameters

Designing the Pattern Parameters is one of the most important steps in RSA pattern authoring. There are a number of factors to consider:

  • What is the pattern parameter type? There are a large set of UML2 types that you can choose from.
  • What are the constraints on the parameters?
  • What are the dependencies between parameters?
  • How can you design for composition?

We use the Pattern Parameter wizard to add parameters to the pattern. Typically we will need to iterate a few times before we can nail down the semantics of the parameters.

In this example, we define a pattern parameter with the name UMLAttributes--see Figure 7. The type of this parameter is of UML type Property with a 0..* multiplicity. This means you can bind multiple parameters of type Property to this pattern parameter.

Figure 7. Pattern Parameters
Pattern Parameters

For each Pattern Parameter, there is an inner class that gets generated into your Pattern class. There are two methods that you implement. We will explain how to implement these methods in Implementing Pattern Expansion code.

Pattern Parameter dependencies

You can specify dependencies between pattern parameters. In the above UMLAttributes parameter, if you turn to the Parameter Dependency page, you will be allowed to choose from the existing pattern parameters for this pattern, which parameter this parameter will depend on. In Figure 8, we selected the TargetClass parameter and used the ">" button to add it to the Supplier Parameters list. This means this UMLAttributes parameter is dependent on the TargetClass parameter.

Figure 8. Pattern Parameter Dependencies
Pattern Parameter Dependencies

When dependencies exist between pattern parameters, an additional inner class will be generated to allow you to add your own implementation to manage the dependencies between the parameters.

Pattern Overview Diagram

When designing a pattern, it is very useful to draw some conceptual UML digrams to show how the pattern artifact (e.g. class) is used in confunction with other artifacts. We typically use the UML Model Editor to draw these diagrams. After a few iterations, these diagrams typically become the overview diagram of the pattern.

To add the pattern overview diagram to the patten plugin, simply follow these steps:

  • Create a .gif file and import into the PatternFiles folder in your pattern plugin. Figure 9 shows the mypattern.gif file in the Package Explorer.
  • Go to the Properties view--Figure 10. Select the Overview Diagram Property and enter the .gif file as the value. The .gif file must be first added to the pattern project.
Figure 9. mypattern.gif file in the Package Explorer
mypattern.gif file in the Package Explorer
Figure 10. Pattern Properties View
Pattern Properties View

Pattern documentation

You can add pattern documentation and a short description to your pattern and pattern parameters.

To add pattern documentation, select the Generate Help Files as shown in the Pattern Authoring View in Figure 5. This will generate a number .html files in your pattern project that you can customize.

To add a short description to your pattern or pattern parameter, in the Pattern Properties View such as Figure 10, select the Short Description property and enter a short description for your pattern. The short description will appear in the Pattern Explorer Short Description view that is associated with the pattern.


Implement the pattern

After you use the base New Pattern wizard to create the base pattern project skeleton, it is time to implement some of the pattern logic. A pattern class extends the com.ibm.xtools.patterns.framework.uml2.AbstractPatternDefinition class. Each pattern parameter will result in an inner class being generated into the main pattern class. A dependency between two parameters will result in another generated inner class. What you need to do is to implement the behaviour when values are added or removed from a pattern parameter. You will implement this logic in specific methods that will be called by the pattern framework when the user gesture happens.

Pattern Parameter Inner Class

In our simple Getter Setter Pattern example, a GetterSetterPattern Java class is generated. In this class, you can find two inner classes, one for each pattern parameter: UMLAttributes and TargetClass. The following code shows the UMLAttributes inner class. It extends AbstratctPatternParameter.

 private class UMLAttributes extends AbstractPatternParameter {
 ...
  public boolean expand
  (PatternParameterValue value) {
    //TODO : implement the parameter's expand method when a parameter value is added
    return true;
  }
  public boolean expand
  (PatternParameterValue.Removed value) {
    //TODO : implement the parameter's expand method when a parameter value is removed
    return true;
  }
}

In the inner class, there are two expand() methods that you can choose to implement:

  • The expand(PatternParameterValue value) method is called when a new value is dropped to the pattern parameter.
  • The expand(PatternParameterValue.Removed value) method is called when a value is removed from the pattern parameter.

Pattern Parameters Dependency inner class

In our Getter Setter Example, the UMLAttributes parameter has a dependency on the TargetClass parameter. Therefore, an additional inner class is generated, as shown here. This inner class is nested inside the UMLAttributes class.

private class UMLAttributes_TargetClassDependency extends AbstractPatternDependency {
...
  public boolean update
  (PatternParameterValue value, PatternParameterValue dependencyValue) {
    //TODO: implement the dependency's update method
    return true;
  }
  public boolean update
  (PatternParameterValue.Maintained value, PatternParameterValue.Removed dependencyValue) {
    //TODO: implement the dependency's update method
    return true;
  }
  public boolean update
  (PatternParameterValue.Removed value, PatternParameterValue.Maintained dependencyValue) {
    //TODO: implement the dependency's update method
    return true;
  }
}

In this inner class, there are three update() methods that you can implement to manage the dependencies between the pattern parameters:

  • The update(PatternParameterValue value, PatternParameterValue dependencyValue) method is called when the value (e.g UMLAttribute value) is added and the dependency (e.g.TargetClass) is already added to the pattern.
  • The update(PatternParameterValue.Maintained value, PatternParameterValue.Removed dependencyValue) method is called when the dependency value (e.g. TargetClass) is removed from the pattern parameter
  • The update(PatternParameterValue.Removed value, PatternParameterValue.Maintained dependencyValue) method is called when the value (e.g. UMLAttribute value) is changed in the pattern parameter.

Pattern implementation tips

Now that you know where you can add your own logic, let's look at some common code snippets that you will write.

Getting the parameter value

In the expand() or the update() method, you might want to retrieve the value of the parameter. You can first do a safe cast to the UML parameter type and then retrieve its value. Here are some examples:

  // Cast the pattern parameter to an UML Property
  org.eclipse.uml2.Property inAttr = (org.eclipse.uml2.Property) value.getValue();
  inAttr.getName();
  // Cast the pattern parameter to an UML Class
  org.eclipse.uml2.Class inClass = (org.eclipse.uml2.Class) value.getValue();
  inClass.getName();

Updating an input UML parameter

You can programmatically update the UML element that is passed into a pattern parameter. The following snippet shows how to programmatically add an operation to an UML class, and then programmatically add a parameter to the operation.

Operation operation = inClass.createOwnedOperation(UML2Package.eINSTANCE.getOperation());
operation.setName("myMethodName");

Parameter parm = operation.createOwnedParameter(UML2Package.eINSTANCE.getParameter());
parm.setName("myParm");
parm.setType("string");

Updating an input UML parameter

You can programmatically update an UML class, interfaces or anything that extends org.eclipse.uml2.Classifier to add a keyword. The following snippet shows how to add the keyword GetterSetter to an UML class.

org.eclipse.uml2.Class targetClass = (org.eclipse.uml2.Class) dependencyValue.getValue();
targetClass.addKeyword("GetterSetter");

The result , Figure 11, is the <<GetterSetter>> being added to an example input class.

Figure 11. <<GetterSetter>> added to input class
&amp;amp;amp;lt;&amp;amp;amp;lt;GetterSetter&amp;amp;amp;gt;&amp;amp;amp;gt; added to input class

Adding a sterotype programmatically

From a visual perspective, a UML sterotype looks very much like a keyword in the UML Model Editor. For example, if you use the EJB profile and choose the Entity sterotype, you will get <<Entity>> added to your UML class. The following shows how to add a sterotype to the class.

  targetClass.apply(sterotype);

So how do you get the sterotypes? First you need to find the UML Profile. You can iterate through the list of UML profiles and locate yours by name.

Iterator descriptors = UML2ResourceManager.getProfileDescriptors().iterator();

while(descriptors.hasNext())
{
    UML2ProfileDescriptor descriptor = (UML2ProfileDescriptor)descriptors.next();
    if( profileName.equals(descriptor.getProfile().getName()))
    {
        profile = descriptor.getProfile();
    }
}

After locating your profile, you can get the sterotype from the profile using profile.getOwnedStereotypes() or if you want a stereotype with a specific name profile.getOwnedStereotype(sterotypeName).

Updating the relationship between the pattern instance and the UML element

Once you bound an UML element to a pattern instance, you can turn on the filters to show all relationships, such as dependencies. You will see an Abstraction relationship between the pattern instance and the UML element as shown in Figure 12.

Figure 12. Abstraction relationship
Abstraction relationship

In the com.ibm.xtools.patterns.content plug-in, there is a class called BasePatternLibrary. You can extend it instead of AbstractPatternLibarary to get this behaviour. This is also shown in the following code snippet:

Classifier a_from = (Classifier)value.getValue();
Object a_to = value.getOwningInstance().getBoundElement();
Package owner = (Package) EObjectContainmentUtil.findContainerOfAnySubtype
   (a_from, UML2Package.eINSTANCE.getPackage());

Abstraction patternAbstraction = (Abstraction)
   owner.createOwnedMember(UML2Package.eINSTANCE.getAbstraction());
patternAbstraction.getClients().add(a_from);
patternAbstraction.getSuppliers().add(a_to);

RSA Patterns Summary

RSA patterns are typically used to collect parameters and to mark up UML models. If you do a save after applying multiple RSA patterns to an UML model, you will notice that there is only one model file (.emx extension) in your project. Typically, what we will do next is to transform this model into different output artifacts such as code, scripts or doc. The transformation and code generation is the job of a RSA Transform married together with JET Templates. These topics are covered in seperate sections below.


Create or extend an existing transform

RSA transform converts all the markups on a model and generates resulting artifacts. RSA ships three transforms out of the box:

  • UML to Java
  • UML to EJB
  • UML to C++

These transforms provide the basic functions to generate the corresponding Eclipse projects and related artifacts from an UML model. For example, the UML to EJB transform will create an EJB project, whereas the UML to Java transform will create a Java project. You can extend these transforms to add extra behaviour, or you can write your own transform by extending the RSA transformation framework. We will show an example of how to extend the UML to Java transform, and an example of how to create your own RSA transform.

Extending an existing RSA transform

Extending an RSA tranform is very much like extending any other Eclipse plug-ins.

  • In your plugin.xml file, add an extension point to extend one of the RSA transforms.
  • Define a rule to specify the name of the class that will provide the implementation.
  • Optionally, define when this rule should be run.

As an example, the Session Facade pattern extends the UML to EJB transform to output additional code when converting an UML model to EJB artfiacts. In the com.ibm.xtools.patterns.content.j2ee.sessionfacade plugin.xml, the following extension point is added to extend the UML to EJB transform:

<extension point="com.ibm.xtools.transform.core.transformationExtensions">
    <TransformationExtension
     targetTransformation="uml2.ejb.transformation"
     name="Transformation Extension"
     id="sessionFacade.transformationExtension"
     version="1.0.0">
       <RuleDefinition
class="com.ibm.xtools.patterns.content.j2ee.sessionfacade.transform.rules.SBFGenerationRule"
         name="Session Facade Pattern Transformation"
         id="sessionfacade.transformationExtension.SBFGenerationRule" />

       <ExtendTransform
        targetTransform="com.ibm.xtools.transform.uml2.ejb.rules.SessionTransform">
          <AddRule
           id="sessionfacade.transformationExtension.SBFGenerationRule"/>
       </ExtendTransform>
    </TransformationExtension>
</extension>

Creating your own RSA transform

Sometimes you need to create your own RSA transform to target other project types (e.g. Portlet Project) or to generate other artifacts (e.g. scripts, documentation etc). For example, in the WebSphere Platform Messaging Patterns, an UML to JACL transform is used to generate WebSphere admin scripts (the output is stored in .jacl file) from the UML topology models.

In the com.ibm.xtools.transform.uml2.jacl plugin.xml, the following extension point is added to extend the core RSA transformation providers framework.

<extension point="com.ibm.xtools.transform.core.transformationProviders">
    <TransformationProvider
     class=

"com.ibm.xtools.transform.uml2.jacl.transformationProvider.UML2JACLTransformationProvider">
      <Priority name="Highest"/>
      <Transformation
       version="1.0.0" name="UML to JACL"
       groupPath="com.ibm.xtools.transform.uml2.jacl"
       author="IBM Corporation"
       sourceModelType="UML2"
       description="Transforms UML to JACL"
       targetModelType="Resource"
       id="com.ibm.xtools.transform.uml2.jacl.transformation">
        <Property
         readonly="true"
         name="system.transformation.property"
         value=

"ClassName=com.ibm.xtools.transform.uml2.jacl.transformationProvider.UML2JACLTransform;
IsUMLKind=true;"
         id="system.transformation.property">
        </Property>
      </Transformation>
    </TransformationProvider>
</extension>

The Getter Setter example

The Getter Setter Example extends the UML to Java transform to show how it can output a text file in addition to the Java class implementation that is automatically generated by the base UML to Java transform. Below we outline the steps you can follow to add the extension points to your plugin.xml to extend the UML to Java transform.

Open the plugin.xml using the Plugin Editor, go to the Extensions view and click on the Add button to add the transformation extension as shown in Figure 13.

Figure 13. Add transformation extension to plugin
Add transformation extension to plugin

Once you completed the wizard, an extension point will be added to your plugin.xml as shown here:

<extension point="com.ibm.xtools.transform.core.transformationExtensions">

  <TransformationExtension
   targetTransformation=
      "com.ibm.xtools.transform.uml2.java.internal.UML2JavaTransform"
   enabled="true"
   id="MyFirstPatternPlugin.TransformationExtension1"
   version="1.0.0">
    <ExtendTransform
     targetTransform="com.ibm.xtools.transform.uml2.java.internal.UML2JavaTransform
          ">
       <AddTransform id="my.first.transform"/>
    </ExtendTransform>

    <TransformDefinition
      class= "com.ibm.samples.patterns.transform.MyFirstTransform"
      name="My First Transform"
      id="my.first.transform"/>
  </TransformationExtension>
</extension>

The class com.ibm.samples.patterns.transform.MyFirstTransform extends the RSA Transformation Framework. In this class, you can add in one or multiple rules that will invoke JET Templates to generate the artifacts.


Create JET Templates

The Eclipse Modeling Framework (EMF) project contains two very powerful tools for generating source code: JET (Java Emitter Templates) and JMerge (Java Merge). With JET you can use a JSP-like syntax (actually a subset of the JSP syntax) that makes it easy to write templates that express the code you want to generate. JET is a generic template engine that can be used to generate SQL, XML, Java source code and other output from templates. It is located in the org.eclipse.emf.codegen plug-in as part of the EMF runtime download.

JET is leveraged by many Eclipse components to generate code. The following articles provide a quick introduction to JET:

JET and JMerge are both used by the RSA Transforms to generate output artifacts from the UML model and to support the synchronization of model changes with user-edits (aka Reapply Pattern or round tripping).

Creating a Jet Template

Create a templates directory in your RSA Pattern plugin to store all the JET Templates for that RSA pattern. In the directory, it should have a standard file called JET.skeleton. Each JET template should have a .javajet extension. A simple example to look at is the com.ibm.xtools.patterns.content.esb.messagedelegate plug-in.

Each JET Template has a start <%@ jet> directive that looks like this:

<%@ jet
package="com.ibm.xtools.patterns.content.esb.messagedelegate.transform.jetsrc"
        imports="java.util.Map"
        class="MessageDelegateTemplate"
        skeleton="JET.skeleton" %>

The package attribute specifies the Java package that the JET compiler will put the Java implementation of this template. The class attribute specifies the Java class that the JET compiler will put the Java code into.

Data model

The next section in the JET template is about extracting model values that are passed during a RSA transformation. Typically, this is done by passing in a Java collection, such as a java.util.Map. One can then extract parameter values from the Map by using a key.

The snippet below shows how we are extracting three values from the input Map.

<%
    final Map parameterMap = (Map) argument;
    if (parameterMap == null) {
	  return stringBuffer.toString();
    }
    // extract incoming map parameters
    final org.eclipse.uml2.Class messageDelegateClass = 
       (org.eclipse.uml2.Class)parameterMap.get(MESSAGEDELEGATECLASS);
    final String messageDelegateClassName = 
       messageDelegateClass.getName();
    final String connectionFactoryJNDIName = 
       (String)parameterMap.get(CONNECTIONFACTORYJNDINAME);
%>

Parameter substitution

To substitute a value in a JET template is similar to a JSP, where you will use the <%= %> directives. The following snippet shows an example:

public class <%=messageDelegateClassName%> {
}

If the value of the messageDelegateClassName is set to Hello, then this will be generated as output:

public class Hello {
}

Compiling Jet templates

We will now extend the MyFirstPatternPlugin project so that it is enabled for JET Nature.

The first step is to convert the project into a JET project by using the Convert Projects to JET Projects wizard as shown in Figure 14. This will add a templates folder into your project. You will store all the JET Templates in this folder.

Figure 14. Convert Projects to JET Projects wizard
Convert Projects to JET Projects wizard

Next, you want to set things up so that the source folder in your Java project is the destination folder of the translated templates. You can do that by using the JET Settings from your project Properties page as shown in Figure 15.

Figure 15. JET Settings
JET Settings

Now you are ready to create your own JET Templates. If you have Build Automatically turned on for your project, the JET Templates will be automatically compiled into Java code. Otherwise, you can select the JET Template and invoke the Compile Template manually.

The Getter Setter example

As described in the last section, the Getter Setter example uses the UML to Java transform to generate the Java class from an UML class, and adds an extension to generate an additional text file. The MyFirstTemplate.javajet file is located in the template directory and is highlighted in the following code.

<%@ jet package="com.ibm.samples.transform.jetsrc"
imports="java.util.* com.ibm.samples.transform.util.MyFirstConstants org.eclipse.uml2.*"
class="MyFirstTemplate"
skeleton="JET.skeleton" %>

<%
final Map parameterMap = (Map) argument;
if (parameterMap == null) {
    return stringBuffer.toString();
}

// extract incoming map parameters
final org.eclipse.uml2.Class myFirstClass = 
   (org.eclipse.uml2.Class)parameterMap.get(MyFirstConstants.CLASS);
final String package_ = myFirstClass.getNearestPackage().getName();
%>

package is <%= package_ %>

class name is <%= myFirstClass.getName() %>

class attributes
<%
List propertyList = myFirstClass.getAttributes();
for ( int i=0; i < propertyList.size(); i++ ) {
    Property property = (Property) propertyList.get(i);
    VisibilityKind vk = property.getVisibility();
%>

    Visibility is <%= vk.getName()%>
    Attribute name <%= property.getName()%>
    Attribute type <%= property.getType().getName() %>
<%
}
%>

The next section describes how we add a rule to marry this JET Template with the UML to Java Transform.


Integrate JET Templates with Transform

So far you have learned how to write a JET Template to describe the format of the output artifact. You also learned how to get parameter values in a JET Template so that you can substitute the values into your output artifacts. But how does the JET template get invoked, and where do the values come from? The answers are explained in the following sections.

Creating a rule

To marry a JET Template with a RSA transform, you have to create a rule that extends com.ibm.xtools.transform.core.AbstractRule . In this rule, you will create the data model for your JET Template (e.g. a Map, a List, or other Collections), and then invoke the Java class that is generated for the JET Template. The rule is added to the transform.

You can obtain the UML element in the rule from the context object that is passed into the createTarget method. A default implementation of the createTarget method is included in the BaseCodeGenRule helper class and is shown here:

protected Object createTarget(ITransformContext context) throws Exception {
      String methodName = "createTarget";

      List targetObjects =  getTargetsFromContext(context);
 
      if (!targetObjects.isEmpty()) {
         setContext(context);
         setProject();
 
         Iterator targetObjectsIt = targetObjects.iterator();
         while (targetObjectsIt.hasNext()) {
            Object targetObject = targetObjectsIt.next();
            String generatedSource = generate(targetObject);
            IFile targetFile = getTargetFile(targetObject);
            saveToFile(targetFile, generatedSource);
         }
      }
      return null;
   }

In the Getter and Setter example, we created a simple MyFirstTextRule that extends the BaseCodeGenRule. We import the Java class that gets generated from the JET Template--see section above. We populate a simple Map with the UML class that is passed in and then invoke the generate method passing in the Map object.

  import com.ibm.samples.transform.jetsrc.MyFirstTemplate
  // import Java class generated from JET Template

  public String generate(Object targetObject) throws Exception {
    Class myClass = (Class) targetObject;

    Map map = new HashMap();
    map.put(MyFirstConstants.CLASS, myClass );

    return new MyFirstTemplate().generate(map);
    // Invoke code generation class
  }

Adding the rule to the Transform

Now that we have created our rule, the last step is add the rule to the Transform. In the Getter Setter Example, MyFirstTransform extends com.ibm.xtools.transform.core.Transform. Invoke the addRules method to add the rule we defined earlier to the transform:

 protected void addRules()
 {
    UMLKindTransform dataTypesTransform = new
       UMLKindTransform(MyFirstConstants.DATATYPESTRANSFORM_ID);
    dataTypesTransform.addByKind(UML2Package.eINSTANCE.getClass_(), new MyFirstTextRule());
    add(new ListContentExtractor(getId()+".datatypeProcessRule", dataTypesTransform));
 }

Unit test your pattern and transform

The most populate way to test your RSA patterns and transforms is to create a new secondary run-time workbench. This will not require packaging of the pattern and transform as a RAS asset. The RSA pattern will appear in the Pattern Explorer and you can simply create a new UML model and apply the new pattern to see if it is achieving your desired results.

Create a new secondary run-time workbench

In the plugin.xml file, under the Testing tab, select one of the Launch options to launch a Runtime workbench for testing--Figure 16.

Figure 16. Runtime workbench
Runtime workbench

This will start a secondary Eclipse workbench. Once this is started, you can create a new UML model, and apply the RSA patterns or transforms.

If you have added System.out.printlns in your Java code, you can see those printlns in the original workbench Console view. You can use the Display Selected Console menu to choose which console data to display, as shown here--Figure 17

Figure 17. Display Selected Console
Display Selected Console

The runtime workbench can also be specified in Debug mode. This can be used to exploit the full debug environment where breakpoints can be specified and stepping through the code can be controlled.

Packaging as a RAS asset

You can also package your RSA patterns and transforms as a RAS asset and save it to the local file system. Then you can import it into your workbench and use it as if it is imported from any RAS respository. This will generally require you to restart your workbench.


Package the asset

The Reusable Asset Specification (RAS) is adopted as an OMG standard in 2004 as a standard way to describe and package an asset. Each reusable asset must contain a manifest file and one or more artifacts. Artifacts can be models, source code, scripts, documents deployment descriptors or test cases. A good asset should have points of variability and can be customizable. RAS is extensible via specialized profiles.

Exporting a RAS Asset

The easiest way to create a RAS package is to select the Export menu on the Pattern Plugin from the Pattern Authoring View. This will invoke the Export RAS Asset wizard as shown in Figure 18. Enter a file system location for this RAS asset.

Figure 18. Export RAS Asset wizard
Export RAS Asset wizard

Import RAS file

To import a RAS asset, you can use the Import RAS Asset wizard as shown in Figure 19. After you import the RAS asset, you have to restart your workbench, then you can start applying the patterns or transforms to your UML models.

Figure 19. Import RAS Asset wizard
Import RAS Asset wizard

Other useful tips and techniques

This section describes useful tip and techniques that can come in handy when developing, testing, and packaging your own RAS assets.

Uninstalling and -clean

To uninstall the asset, use the Manage Configuration dialog that can be launched from the Help->Software Updates menu. After uninstalling an asset, you should restart the Workbench with a -clean option. For example:

 rationalsdp.exe -clean

Always put your classes in a package

When you create a new model, always create a new UML package and put your UML classes into the package. This is because the UML to Java and UML to EJB transform assumes your classes are contained in a package. You will see an error, Figure 20, when you run the transform if your classes are not in a package. You can also drag and drop classes into a package after they are created.

Figure 20. Transform error
Transform error

UML Profiles

When you first design your RSA patterns, you probably should just use keywords to add UML markups. After you have settled on how your RSA patterns will work with the UML models, you might want to formalize the markups using an UML Profile. An UML Profile has a .epx extension and can be packaged together with your pattern asset.

RSA provides a UML Profile Authoring wizard and editor that you can use to create an UML Profile. With an UML Profile, you can extend any UML type with a stereotype (e.g. add your favorite stereotype to an UML Property) and also add additional attributes to that stereotype.


Download

DescriptionNameSize
My first pattern plugin zipmyfirstpatternplugin-dl.zip288 KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=97386
ArticleTitle=Content authoring demystified:
publish-date=11012005