Skip to main content

Tips and tricks for C++ transformations using Rational Systems Developer and Rational Software Architect

Controlling the C++ code generated from a UML Model

Sandeep Kohli, Senior Software Engineer, IBM
Sandeep Kohli
Sandeep Kohli is a development lead and Architect with the Rational Software Architect / Rational Systems Developer team in Bangalore. He has worked on various Rational modeling tools like Rational Rose, Rational RoseRT, and Rational Software Architect. He has also worked on C/C++/Fortran/Ada compilers.
Sreerupa Sen, Senior Software Engineer, IBM
Sreerupa Sen
Sreerupa Sen is an architect with IBM working on Rational UML modeling tools. In the course of her career in software, she has worked on different domains, including banking applications, middleware, utility data centers, and modeling tools. In IBM, she has been working with IBM's Rational Software Architect/Rational Systems Developer offerings, specifically using C++.

Summary:  UML is a general-purpose language. IBM® Rational® Software Architect and IBM® Rational® Systems Developer allow you to extend UML modeling to support constructs that are specific to the C++ programming language. The UML to C++ Transformation in Rational Software Architect and Rational Systems Developer converts UML models to C++. This article discusses various tips on how to achieve finer control over the C++ code generated when you run the UML to C++ transformation. This article is divided into several sections, with each section describing a technique. You don't need to refer to the sections in any particular order.

Date:  12 Jun 2007
Level:  Intermediate
Activity:  554 views

Applying the C++ Transformation profile for modeling C++ constructs

The standard way to bridge a gap between the Unified Modeling Language (UML) and a particular domain is through the use of a UML Profile. A UML profile allows you to define additional semantics and characteristics for existing UML elements, such as class, operations, and so on. In order to model C++ specific elements like struct, unions, namespaces (and so on), you need a UML profile. The UML to C++ Transformation in Rational Software Architect and Rational Systems Developer comes with a C++ Transformation profile. The profile can be applied on a UML model as follows.

  1. Select the UML model on which the profile is to be applied in the Project Explorer.
  2. Switch to the Properties View with the model still selected in the Project Explorer and click the Profiles tab.
  3. Click the Add Profile button, as shown in Figure 1.

Figure1. Applying the UML to C++ Transformation profile
Applying the UML to C++ Transformation profile
  1. Select C++ Transformation from the Deployed Profile drop down list, as shown in Figure 2.

Figure 2. Selecting C++ Transformation
Sample UML2 Model

Importing the C++ type library

UML provides a limited set of predefined types. These are Boolean, Integer, String and UnlimitedNatural.. Most programming languages, including C++, provide a much richer set of primitives. When modeling in the C++ domain, you will often need to use a predefined primitive type specific to C++ (for example, when you assign a type to an attribute, a parameter, an operation return type, and so on). To import the C++ model library that is shipped with the C++ Transform, right-click the UML model in the Project Explorer and select Import Model Library, as shown in Figure 3 below.


Figure 3. Importing the C++ Type Library
Importing the C++ Type Library using the pop-up menu

Select C++ Types from the Deployed Library list, as shown in Figure 4.


Figure 4. Importing the C++ Type Library.
Importing the C++ Type Library

Creating C++ namespaces in a model

This section tells you how to model C++ namespaces in a UML model. To create a namespace in C++, you need to apply the cpp_namespace stereotype on a UML package. A UML package will, by default, be mapped to a folder by the UML to C++ transformation. To get a UML package to map to a namespace instead of a folder, you need to apply the cpp_namespace stereotype on it, and then set the NamespaceName property associated with this stereotype to the desired namespace name. All the classes, struct, enums (and so on) under this stereotyped UML package will be generated within this namespace in the generated code.

You might wonder why the namespace does not take the name of the stereotyped package as its own name. The reason is to support modeling anonymous namespaces in C++. So, if you leave the NamespaceName property blank, the namespace is assumed to be an anonymous namespace.


Modeling C++ typedefs

To model a C++ typedef, create a UML class and apply the cpp_typdef stereotype on it. This stereotype provides three property/value pairs:

  • arrayDimensions
  • ImplementationType
  • qualifier

To create a typedef such as typedef int const IntMatrix100_20_t [10][20];, create a UML class IntMatrix100_20_t and apply the cpp_typedef stereotype to it. Set the properties for this stereotype to be like those shown in Figure 5.


Figure 5. Creating a C++ typedef
C++ Typedef properties

To correlate the typedef definition with the properties provided by the profile, you can think of the typedef in the following manner: typedef <ImplementationType> <qualifier> <Class Name> <arrayDimensions>


Creating multi-dimensional array attributes

In this section, you will learn how to make an attribute a three-dimensional array of size [10][20][30]. Select the attribute that needs to be a multi-dimensional array in the Project Explorer. In the Properties view, click the Stereotypes tab. On the Stereotypes tab click the Apply Stereotypes button and select the cpp_type stereotype. This stereotype provides you with the following property/value pairs:

  • arrayDimensions
  • InitializerKind
  • isAuto
  • isMutable
  • isRegister
  • isVolatile
  • qualifier

In the arrayDimensions Value field shown in Figure 6, specify [10][20][30]. This will generate an attribute with array dimensions [10][20][30] in the source code.


Figure 6. Setting Multidimensional Attributes
Setting Mutidimensional Attributes

Qualifying a method's formal parameter as const

This trick applies the same principles as the last one (defining a multi-dimensional array). Select the method parameter that you want to be a const in the Project Explorer. In the Properties view, click the Stereotypes tab. On the Stereotypes tab, click the Apply Stereotypes button and select the cpp_type stereotype. This stereotype provides you with the following propery/value pairs.

  • arrayDimensions
  • InitializerKind
  • isAuto
  • isMutable
  • isRegister
  • isVolatile
  • qualifier

Each one of these is an interesting property, but for now you are interested in the qualifier property. In the Value field for qualifier, enter the value const (as shown in Figure 5 previously). This will generate a function signature in the source code with the const qualifier for the selected parameter, once the transformation is executed.

Note: Make sure to enter a valid value in this field. Failure to do so will lead to compilation errors that you will need to fix before rerunning the UML to C++ Transformation.

Note that the cpp_type stereotype is also applicable to attributes of a class. However, it is easier to simply mark an attribute as Read Only in order to generate a const attribute.


Making an entire method as a const method

Suppose you would like to declare your method as const so that it is generated with the const keyword as in )int Operation1(MyType Parameter1 const;. To do so, you need to select the Query qualifier on the General tab in the Properties view for the method in question, as shown in Figure 7. There is no need to apply a stereotype to get this capability.


Figure 7. Creating a const method
C++ Const Method

Adding an exception to a method

Exceptions are first class citizens in UML, and can be modeled without using profiles. In order to simplify and generalize the modeling experience, the UML to C++ Transformation uses UML properties wherever applicable, instead of using a profile. To generate a throw clause for a function, such as int Operation1() throw ( MyType);, you first need to create a parameter for the operation and set its Is Exception property to true.

The name of the parameter doesn't matter, because it is ignored during transformation, but it is better to select a name that properly identifies it as an exception being thrown. Figure 8 shows how to set a parameter's Is Exception property to true.


Figure 8. Setting the throw type for a method
Throw Clause for Method

Controlling include statements in the generated code

The UML to C++ Transformation is designed to pick up dependencies from the model on its own, and to generate proper include statements or forward declarations automatically. However, you may want to control include statement generation for specific situations. For example, you may know that you will use local variables of a certain type in your method body, and therefore want to generate include statements for that type in your body file.

You need to model such cases explicitly by creating a UML dependency between the two classes and applying the cpp_dependency stereotype to this dependency. This stereotype comes with a property named IsInclusionInHeader, which is set to false by default. If you want the include statement to be generated in the body file, then you should leave it as false. If you need to generate the include statement in the header, then either do not apply the cpp_dependency stereotype to your dependency at all, or apply the stereotype and set the IsInclusionInHeader property to true.


Using File level reapply preserve sections

If you need to use types from the standard library, or from some other library in your source code, you have to set such types as plain strings in your model. For example, if you want to declare an attribute to be a vector of integers, you would specify its type as vector<int> in the model. The transform would treat such types as primitive types, and would not generate any include statements or forward declarations corresponding to them. Therefore, you need to include these in your source files explicitly.

For the vector type, for example, you should put an explicit include statement for vector in your source code, such as #include <vector>. To support this, each generated file contains a section that will be preserved verbatim when you reapply the UML to C++ transformation, as shown in Listing 1 following. Note the //TODO: Add definitions that you want preserved line. Whatever you add here between the Begin section and End section comments will be preserved. Please add statements like #include <vector> here.


Listing 1. Generated Code for a class Car
                

#ifndef CLASS1_H
#define CLASS1_H
//Begin section for file Class1.h
//TODO: Add definitions that you want preserved
//End section for file Class1.h

#include "MyType.h"

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class Class1
{

    //Begin section for Class1
    //TODO: Add attributes that you want preserved
    //End section for Class1
    public:

        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        int Operation1()const  throw ( MyType);

};  //end Class Class1

#endif
	      


Removing the class level reapply preserve sections

Notice that in the code from Listing 1 previously, there is a //Begin section for Class1 ... //End section for Class1 . You can put all those C++ specific statements that you cannot model here, and these will be preserved until you delete them explicitly. When you rerun the UML to C++ Transformation, it will not overwrite statements in this section. In case you do not need this section in your generated code, you may want to delete it altogether. It will not be regenerated next time you run the UML to C++ Transformation. This is how you can get rid of those comments that you don't care about.

Delete the following section (Listing 2) if you don't need it, and it will not be regenerated. Should you want this section back, you will have to insert it manually at the same location later.


Listing 2. Generated Code for a class Car
                
    ...
    //Begin section for Class1
    //TODO: Add attributes that you want preserved
    //End section for Class1
    ...     


Changing the name of the generated package without modifying the UML model

To change the package name, double click your transformation configuration file to open it in the editor. Click the Mapping tab and select Enable mapping as shown in Figure 9.


Figure 9. Enable the mapping model
Enable Mapping Model

Click the New button to create a default mapping model and give it an appropriate name. Click the Edit Mapping button to bring up the dialog box shown in Figure 10.


Figure 10. Edit mapping model
Edit Mapping Model

Suppose you are working on the UML model shown in Figure 11. If you do not have a mapping model, then the Date class will be generated inside a folder called Package1. If, however, you want the Package1 to be generated as Folder1, then you need to use the mapping model. To do so, browse the mapping model to reach Package1, and then in the Mapped Name edit box at the bottom of the wizard type Folder1. In the generated code, the Date class will now be generated inside a folder named Folder1.


Figure 11. The UML model on which you are working
Mapping UML Model

Generating multiple classes in the same file

If you map a UML class in the mapping model to a different name, you change the name of the file in which it will be generated but not the generated class in the file. By default, a top-level class is generated into a file with the same name as itself. So for a UML class named MyClass, the UML to C++ Transformation will generate MyClass.h and MyClass.cpp.

However, you can choose to have a different filename for the UML class by using the mapping model. Just like you can rename a UML package in the mapping model to generate a differently named folder, you can map a UML class to a differently named file. The name of the class itself is not affected by the mapping model. To generate multiple classes in the same file, therefore, all you need to do is to give the same target name for them in the mapping model.


Resources

Learn

  • For technical resources, visit the developerWorks Rational Systems Developer area. You'll find technical documentation, how-to articles, education, downloads, product information, and more.

  • Stay current with Technical events and webcasts.

  • How to use the C/C++ Development Toolkit (CDT) : C/C++ development with the Eclipse Platform.

  • In the Architecture area on developerWorks, get the resources you need to advance your skills in the architecture arena.

  • In the Patterns area on developerWorks, get the resources you need to advance your skills in the patterns arena.

  • Enroll in RD101: Principles of Modeling with UML 2.0. This online course introduces the basic principles of object technology and visual modeling using the Unified Modeling Language (UML), version 2.0. You will learn the four principles of visual modeling and the basic building blocks of the UML, as well as the benefits of the use case-driven, architecture-centric process that the UML supports. This is self-directed, self-paced online learning with rich media content, including interactions, quizzes, and virtual labs .

  • Browse the technology bookstore for books on these and other technical topics.

Get products and technologies

Discuss

About the authors

Sandeep Kohli

Sandeep Kohli is a development lead and Architect with the Rational Software Architect / Rational Systems Developer team in Bangalore. He has worked on various Rational modeling tools like Rational Rose, Rational RoseRT, and Rational Software Architect. He has also worked on C/C++/Fortran/Ada compilers.

Sreerupa Sen

Sreerupa Sen is an architect with IBM working on Rational UML modeling tools. In the course of her career in software, she has worked on different domains, including banking applications, middleware, utility data centers, and modeling tools. In IBM, she has been working with IBM's Rational Software Architect/Rational Systems Developer offerings, specifically using C++.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, Architecture
ArticleID=228899
ArticleTitle=Tips and tricks for C++ transformations using Rational Systems Developer and Rational Software Architect
publish-date=06122007
author1-email=sandeep.kohli@in.ibm.com
author1-email-cc=clarkega@us.ibm.com
author2-email=sreerupa.sen@in.ibm.com
author2-email-cc=clarkega@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers