Click here to Skip to main content
Click here to Skip to main content
Go to top

Customizing Code Generation of Telelogic Rhapsody in C with .NET

, 30 Aug 2007
Rate this:
Please Sign up or sign in to vote.
A detailed guide on how to extend the Rhapsody code generator in C#

Introduction

Telelogic Rhapsody in C is a UML modeling tool with strong support for embedded systems. While its built-in code-generator fits many environments nicely, embedded domains like automotive systems do have their specific needs which are rarely satisfied by off-the-shelf code-generators. So either you pay the tool vendor a lot of money to implement your domain requirements or - if the tool allows - you do it yourself. This article describes how code generation in Rhapsody in C (short: RiC) works and what can be customized and how exactly this is done. You may see this article as an extension to RiC's documentation which is not very exhaustive on this topic.

Background on Code Generation in RiC

RiC's code generator produces C source code from a UML model, from now on called the user model. This user model may contain modeling concepts like classes and statemachines that have no direct equivalent in the target programming language C. The RiC code generator therefore applies a set of well-known patterns mapping, e.g. classes, their attributes and methods to C.

The Two Steps of Code Generation

While e.g. for Rhapsody in Ada, this is done in a single step, RiC separates the mapping from actual source code generation and therefore consists of the following two steps:

  1. During Simplification, object-oriented concepts like classes and statemachines are mapped to concepts available in the target programming language. In C, these are concepts like structures and functions. The output of this step is still a UML model with a limited set of used UML features.
  2. In a model-to-text transformation, source code is generated from the simplified model by applying a declarative ruleset consisting e.g. of text templates for structures and operations.

Both steps may be customized. So if you want to change the generated output, you have to make the important design decision very early as to which approach to take. Use the following guideline as a rule of thumb: If you want to add new or change the semantics of existing modeling concepts (e.g. in the form of stereotypes), modify the simplification step. On the other hand, if instead of semantics the location or appearance of a concept in source code matters most, modify the ruleset.

This two step approach nicely fits OMG's MDA philosophy: If the target programming language C is what MDA calls a platform, then the simplification step transforms a platform-independent model (PIM) to a platform-specific model (PSM) and the rules-based step then transforms the PSM to code.

Customization Technologies

Unfortunately the two approaches rely on different underlying technologies, thereby making the integration not easy:

  • The simplification step relies on Rhapsody's COM API. For customization, a new simplifier is implemented invoking Rhapsody's metamodel through COM. Therefore all COM-aware technologies and programming languages may be used, including .NET and C#.
  • The rules-based step is realized by invoking RiC's rules-player. The rules-player executes a certain ruleset, which may be modified in a tool called the rules-composer. Such a ruleset consists of templates and scripts generating the output text. As of today, scripts may be written in proprietary Java-like languages defined by the rules-composer, in Java or as ATL transformations. The underlying metamodels are themselves based on the Eclipse Modeling Framework.

To summarize: simplification lives in the COM world while rules-based code generation lives in the Java/Eclipse world. What is common is the structure of RiC's metamodel: if you know in COM where to find classes you won't have any issue with that in a ruleset either.

This article solely deals with modifying the simplification step in C#. As you most of the time add or change semantics of modeling concepts, this already gets you quite far. Changing the ruleset is out of scope as it would resemble documentation of the rules-composer application.

Preparing the Model

screenshot CustomizableCG

To allow changing or replacing the built-in simplifier, the model must be set up correctly. The user is assumed to know what Rhapsody properties are and where to change them. First of all custom code generation must be enabled by setting the property C_CG::Configuration::CustomizableCG to true as shown in the screenshot.

After this, model elements can be specifically chosen to have custom simplification applied. As this again is done through RiC properties, the typical Rhapsody ways of inheriting properties from parent model elements or stereotypes may also be used. The property names to look for typically start with Simplify.

screenshot Simplify properties

The screenshot shows the corresponding properties for the model element Class. You notice the Default: by changing this to one of the following values, a custom simplification can be switched on for the model element in scope:

  • None simply omits the model element during simplification. Obviously this will lead to the element missing in generated source code as long as the default ruleset is used. A custom ruleset still may access this element through the metamodel.
  • Copy will put a copy of the model element into the simplified model.
  • ByUser leads to invoking a user-defined simplifier that is given the corresponding model element as input.
  • ByUserPostDefault will also call the user-defined simplifier but after the built-in simplifier has done its job.

So to invoke a custom simplifier, a model element's Simplify property must be set to either ByUser or ByUserPostDefault, depending on whether the custom transformation is a replacement or an extension of the built-in transformation step.

The screenshot also shows different types of what exactly is simplified for the model element and thereby gives a finer granularity when applying custom transformations to very specific aspects of the current model element. Also note that even though simplification is changed for a parent element like a class, its child elements like operations still have their own simplification settings. This is a very flexible approach, which in some cases may lead to confusion about which simplify property of which metaclass needs to be changed. In that case nothing will spare you a little trial and error session...

Building your Own Simplifier

You can build your own transformation plugin very easily by using the base class I provided in this article. The base class already realizes the interfaces needed by Rhapsody and also implements a clean connect/disconnect protocol.

You use the base class by doing the following:

  1. Download the source file and drop it into your project.
  2. Add a dependency to the COM server rhapsody.exe to your project. This way, RiC's COM API becomes available.
  3. Add a new class MySimplifier to the project and derive it from the base class CodeGenSimplifier.
  4. Implement a constructor for your new class that calls the base class constructor thereby passing a simplifier name that will show up when printing output to Rhapsody's console.
  5. Override the transformation functions as needed. The base class already provides default implementations that have no effect on the model.

Eventually, a very simple simplifier will look like the following example code (you can copy and paste this code, it is complete):

public class MySimplifier : RicTools.CodeGenSimplifier.CodeGenSimplifier
{
    public MySimplifier( )
        : base( "MySimplifier" )
    {
    }

    protected override void OnPostSimplify( RPModelElement userElement, 
	RPModelElement mainSimplifiedElement, string simplificationRequested )
    {
        TraceInformation( "user element = {0}", userElement.getFullPathName() );
        TraceInformation( "main simplified element = {0}", 
			mainSimplifiedElement.getFullPathName() );

        // just a test:
        if( !ShouldAbortGeneration )
        {
            WriteCodeGenMessage( "Applying transformation of description." );
            mainSimplifiedElement.description = 
			"This element has been simplified. Dig this!";
        }
    }
}

The example simply changes the description of a model element after it has been transformed by the built-in generator. You also notice a few convenience functions being called: WriteCodeGenMessage writes output to Rhapsody's build console, TraceInformation and other trace methods write output to trace listeners that may have been set up. The flag ShouldAbortGeneration indicates whether the user hit the abort button in Rhapsody.

For a complete overview of all methods provided by the base class, take a look at the help file I provided with the source code. To connect to a running Rhapsody instance, instantiate your new class and call Connect(). If you then regenerate code with a model prepared as described earlier, your simplifier will be invoked and the generated code will eventually contain the changes you triggered inside implementations of OnSimplify or OnPostSimplify.

Summary

After giving a brief overview of Rhapsody in C's code generation process, the article showed what needs to be done to implement a new custom code generation simplifier in C# built on top of a generic base class. While RiC is used for modeling and code generation in a lot of places, application of advanced features like customization of its code generator does not seem to be widely spread. Partially this may be caused by the lack of in-depth documentation, which is what I tried to address in this article.

While this article explained the technical background and provided a simple tool to get a simplifier going in the first place, nothing was said about how the actual transformation code should work. Depending on interest, I will write about this in follow-up articles.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Mike Pagel
Software Developer (Senior) BMW AG
Germany Germany
No Biography provided

Comments and Discussions

 
GeneralRhapsody Rules Composer PinmemberTheLetti30-Oct-07 13:03 
GeneralRe: Rhapsody Rules Composer PinmemberMike Pagel30-Oct-07 21:22 
QuestionRe: Rhapsody Rules Composer PinmemberTheLetti2-Nov-07 3:04 
AnswerRe: Rhapsody Rules Composer PinmemberMike Pagel2-Nov-07 3:12 
QuestionRe: Rhapsody Rules Composer PinmemberTheLetti6-Nov-07 4:41 
AnswerRe: Rhapsody Rules Composer PinmemberMike Pagel6-Nov-07 9:18 
QuestionRe: Rhapsody Rules Composer PinmemberTheLetti6-Nov-07 12:22 
AnswerRe: Rhapsody Rules Composer PinmemberMike Pagel7-Nov-07 1:52 
QuestionRe: Rhapsody Rules Composer PinmemberTheLetti13-Nov-07 11:17 
AnswerRe: Rhapsody Rules Composer PinmemberMike Pagel13-Nov-07 20:09 
QuestionRe: Rhapsody Rules Composer PinmemberTheLetti14-Nov-07 10:44 
AnswerRe: Rhapsody Rules Composer PinmemberMike Pagel14-Nov-07 21:06 
GeneralRe: Rhapsody Rules Composer PinmemberMike Pagel14-Nov-07 21:33 
GeneralRe: Rhapsody Rules Composer PinmemberTheLetti24-Nov-07 23:37 
GeneralRe: Rhapsody Rules Composer PinmemberTheLetti11-Dec-07 12:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140905.1 | Last Updated 30 Aug 2007
Article Copyright 2007 by Mike Pagel
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid