Skip to main content

UML to C++ transformation using IBM Rational Systems Developer and Rational Software Architect

Iterative development from a UML model to C++ code with enhancements to both the model and the code

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:  Learn how to use UML modeling in IBM® Rational® Software Architect and Rational® Systems Developer tools to develop C++ applications. This article describes features introduced in Version 7.0 that support C++ domain-specific modeling. The programming assumption of this article is that you are enhancing both your model and your code continuously, and you want to preserve changes in both of them over repeated application of the UML-to-C++ transformation. You need only a basic knowledge of UML and these Rational software products for this article to be useful to you, but the authors assume that you know how to run a transformation and how to apply profiles and stereotypes.

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

Prerequisites and process overview

This article explains how, as a C++ programmer, you can continue to design by using C++ data structures, even while using the Unified Modeling Language (UML) for modeling. You need only a basic knowledge of UML and of IBM® Rational® Software Architect and IBM® Rational® Systems Developer for this article to be useful to you, but the authors assume that you know how to run a transformation and how to apply profiles and stereotypes. The process follows these basic steps:

  1. Begin by creating a simple UML model in IBM Rational Systems Developer.
  2. Apply a C++ profile to the model so that you can use C++-specific data structures in modeling.
  3. Import the C++ type library into the model so that you can use C++ primitive types.
  4. Generate the code, and take a quick look at it.
  5. Then add a body to a method in a class.
  6. Add a few of the more conveniently forgotten details to the model to see that repeated application of UML-to-C++ transformation preserves your modifications to the code and the model.

Create a simple UML model

A UML profile is a mechanism to extend UML in a standard way, so that certain domain-specific features can be modeled in UML without burdening UML with the entire knowledge of existing and future languages and technologies. The authors of UML could not have anticipated all of the domains that UML will be used to model; therefore, they wisely provided an extension mechanism to support such cases without making UML any bigger than it already is.

Apply the C++ profile

For example, to model certain C++-specific elements, such as struct, union, typedef, and so on, you need to apply a C++ profile to your UML model. The C++ profile is included with the UML-to-C++ transformation tool. To apply the profile, follow these steps

  1. Make sure that you are in the Modeling perspective.
  2. Select a model, and then click the Properties view.
  3. Select Profiles from the list on the left in the Properties view.
  4. Click Add Profile, and select the C++ Transformation profile under Deployed Profile in the Select Profile dialog. (See Figure 1and Figure 2.)

Figure 1. Applying the C++ (CPP) profile
Figure 1. Steps in applying the C++ (CPP) profile


Figure 2. Selecting the C++ profile
Figure 2. Selecting the C++ profile

Import the C++ type library

UML provides a very limited set of predefined types. These are basically Boolean, Integer, String, and UnlimitedNatural. Most programming languages, including C++, provide a much richer set of primitives. When modeling for C++, you will often need to use predefined primitive types specific to C++ when you assign a type to an attribute, a parameter, a return type, and so forth. To import the C++ model library that is included with the C++ transformation tool:

  1. Right-click on the UML model in the Project Explorer.
  2. Select Import Model Library, as Figure 3 shows.

Figure 3. Importing the C++ type library
Importing C++ Type Library

  1. In the Import Model Library screen, under Deployed Library, select C++ Types from the drop-down list , as shown in Figure 4.

Figure 4. Selecting the C++ types library to import
Selecting C++ Type Library

Now you are ready to model some of the C++-specific elements that have no equivalence in UML. You will see an example next.

Create a simple UML model of a car factory

Now you'll create the simple UML model shown in Figure 5. There are various ways of creating this model, but you can follow what this diagram illustrates. For example:

  • This sample model has Vehicle as a base class for Bus and Car.
  • The Bus, Car and Vehicle classes are created inside of a UML package named Vehicles, which is not shown.
  • Similarly, Engine and Wheels classes are created inside of a UML package named Parts, also not shown.
  • Car has a composition relationship to Engine.
  • In this theoretical factory, Car and Engine are inseparable, because a car needs an engine.
  • Both Car and Bus have an aggregation relationship to Wheels.
  • In this example, wheels can exist outside of a car, and a car can exist without wheels -- at least while it is being assembled.

Figure 5. Simple UML model of a car factory used here as an example
Figure 5. Simple UML model of a car factory used here as an example

Create C++ elements in the model

  1. Next, create a UML package called Strategy at the model level.
  2. In Strategy, define routes and starting points for buses.
    1. Create a class named Route to represent a route, and a class named Address that represents an address, such as the starting point of a bus route.
    2. Address needs to be a C++ struct element instead of an ordinary class.
  3. Now, enhance your UML model to specify that a route is assigned for every bus. You can do this by creating an aggregation relationship from the Bus class inside of the Vehicles package to class Route, as shown in Figure 6.
  4. One of the many properties of a route is its starting point. Therefore, add an attribute named startingPoint of type Address to the Route class.

Figure 6. Contents of the new UML package called Strategy
Figure 6. Contents of the new UML package called Strategy

In Figure 6, notice that Address is a <<cpp_struct>> class. To create a stereotyped element called Address of type <<cpp_struct>>, follow these steps:

  1. Create a UML class, and name it Address.
  2. Apply the cpp_struct stereotype to the newly created class.
    1. To apply a stereotype to a UML element, switch to the Properties view for the given element.
    2. Select Stereotypes from the list on the left, and then click Apply Stereotypes, as Figure 7 shows.

Figure 7. Applying a stereotype
Figure 7. Applying          a stereotype

  1. Select the cpp_struct from the list of stereotypes applicable to this element. Also notice the other choices, just for future reference.

You will soon see that, when you transform this model to code, the UML class of Address with the stereotype of <<cpp_struct>> will be generated as a struct element, rather than as a class.


Configure the transformation and generate the code

Before you can generate C++ code from your model, you need to specify parameters for the UML-to-C++ transformation by creating a transformation configuration.

Create a transformation configuration

One way that you can do this is to complete these tasks:

  1. Click File > New > Others, and then select the transformation configuration inside of the Transformations folder.
  2. When you are in the New Transform Configuration wizard, specify a name for this configuration file For this exercise, name it tc1.
  3. Choose the transformation type and the project to which this will be saved.
    1. You can select the transformation type by expanding the IBM Rational Transformations list and then selecting UML to C++.
    2. For this exercise, use the existing UML model project to store the transformation configuration file.
  4. Now, go on to the next screen by clicking Next.
  5. On the Source and Target tab:
    1. Select the source as the UML model.
    2. Create a new managed C++ project as the target.
  6. Make sure that the source and target are selected, and then click Finish.

Note:
You can edit transformation configuration later, if you wish.

Generate the code

This is going to be easy.

  1. You have already done most of the hard work, so you can generate the just by right-clicking on tc1.tc and selecting Transform > UML to C++ from the pop-up menu. This will generate code in the project that was selected as the target when you created the transformation configuration.
  2. Look at the code generated for the Route class. It contains startingPoint and endingPoint attributes, as well as a getFare() method (see code Listing 1).

Listing 1. Route.h generated code for the Route class
                

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

struct Address;

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

    private:
  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_Hk7qMACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        float runningCost;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_hKd58ACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        float expectedProfit;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_ieiw8ACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        Address * startingPoint;

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_jkEOkACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        Address * endingPoint;
    public:

	  //@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_kawmAACuEdy9t-_gdCbefQ"
        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"

        float getFare()const ;

};  //end Class Route

#endif    
      

The default body of the getFare method has been generated, as shown in Listing 2.


Listing 2. Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp


float Route::getFare() const 
{
    //TODO Auto-generated method stub
    return 0;
}    
      


Modify the code

As you must have noticed, the default body is not of much use, because the fare is always 0 (zero). That would make it not a very profitable business to be in! So you need to replace the body of the getFare method with the code in Listing 3.


Listing 3. Route.cpp
                
float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}
      


Develop the model and rerun the transformation

Now, add another method called print_disclaimer() to the Route class in the UML model.

  1. Set its return type to String.
  2. Notice that we have also modified the Route.cpp file by adding the method body for the getFare method.
  3. Run the transformation by using the same transformation configuration (tc1.tc > Transformation > UML to C++).
  4. Accept the default choices that are presented to you, which warn about the target files being updated.

Now, look at the updated code (Listing 4).


Listing 4. Updated Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp


float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer() 
{
    //TODO Auto-generated method stub
    return 0;
}
      

About the @generated tag

You'll notice an <<@generated>> tag in the method comment. Method bodies are preserved automatically. However, if you delete the method from the model and run the C++ transformation again, then this method will be deleted, along with the body of your code. This ensures that your code will not be littered with all possible methods that you ever designed in your model that you would have to manually delete from the generated code.

If you don't want this to happen and want to preserve the method in the code, then you need to remove the <<@generated>> tag from the method comment. That way, you will have taken control of this method, and it should be left as it is when the transformation is run again.

Notice that the modified method body for the getFare() method is preserved. At the same time, the new method called print_disclaimer that was added to the model has produced new code in the Route.h and Route.cpp files. This way, you can continue to implement your methods in the code and, at the same time, make incremental modifications to the model. This gives you the very useful capability of doing model-driven iterative development.


Add a custom include statement to the preserved sections

We code the body of print_disclaimer method as Listing 5 shows. Notice that we use the cout operator. C++ transformation doesn't know anything about this. However, for the reapply action to work properly, it is important that the code can be parsed, so that the code structure and method bodies can be preserved when the transformation is reapplied. To make this code compileable, you need to add #include <iostream> and using namespace std; in the cpp file. These statements should be preserved in repeated runs of the UML-to-C++ transformation. This can be achieved by inserting these two statements within the comments:

//Begin section for file Route.cpp
//End section for file Route.cpp

Whatever you add to this section is preserved verbatim and is not interpreted by the C++transformation.


Listing 5. Route.cpp
                
#include "Route.h"
//Begin section for file Route.cpp
#include <iostream>
using namespace std;
//End section for file Route.cpp


float Route::getFare() const 
{
    // Calcualte the fare
    return runningCost * expectedProfit;
}

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer() 
{
    const char *s = "No Refund once the ticket is purchased\n";
    cout << s;
    return s;
}
      

Note about the downloads:

  • Sample UML Model and C++ projects: These zipped projects can be imported into the Eclipse workspace by selecting File > Import, and then invoking the Import Existing Projects into Workspace wizard.


Summary

This article has shown you the basics of using Rational Systems Developer to create a UML model for generating C++ code and a way of working on the code and the model in parallel. For more information, see the links in Resources.



Downloads

DescriptionNameSizeDownload method
Sample UML Model project.MyAutomobileFleet.zip7KB HTTP
Final CPP ProjectAutomobileFleetCode.zip33KB HTTP

Information about download methods


Resources

Learn

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

  • Stay current with Technical events and webcasts.

  • Learn 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 .

  • Subscribe to the developerWorks Rational zone newsletter. Keep up with developerWorks Rational content. Every other week, you'll receive updates on the latest technical resources and best practices for the Rational Software Delivery Platform.

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
ArticleID=229109
ArticleTitle=UML to C++ transformation using IBM 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