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:
- Begin by creating a simple UML model in IBM Rational Systems Developer.
- Apply a C++ profile to the model so that you can use C++-specific data structures in modeling.
- Import the C++ type library into the model so that you can use C++ primitive types.
- Generate the code, and take a quick look at it.
- Then add a body to a method in a class.
- 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.
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.
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
- Make sure that you are in the Modeling perspective.
- Select a model, and then click the Properties view.
- Select Profiles from the list on the left in the Properties view.
- 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 2. Selecting the C++ profile
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:
- Right-click on the UML model in the Project Explorer.
- Select Import Model Library, as Figure 3 shows.
Figure 3. Importing the C++ type library
- 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
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
Create C++ elements in the model
- Next, create a UML package called
Strategyat the model level. - In
Strategy, define routes and starting points for buses. - Create a class named
Routeto represent a route, and a class namedAddressthat represents an address, such as the starting point of a bus route. -
Addressneeds to be a C++structelement instead of an ordinary class. - 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
Busclass inside of theVehiclespackage to classRoute, as shown in Figure 6. - One of the many properties of a route is its starting point. Therefore, add an attribute named
startingPointof typeAddressto theRouteclass.
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:
- Create a UML class, and name it
Address. - Apply the
cpp_structstereotype to the newly created class. - To apply a stereotype to a UML element, switch to the Properties view for the given element.
- Select Stereotypes from the list on the left, and then click Apply Stereotypes, as Figure 7 shows.
Figure 7. Applying a stereotype
- 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:
- Click File > New > Others, and then select the transformation configuration inside of the Transformations folder.
- When you are in the New Transform Configuration wizard, specify a name for this configuration file For this exercise, name it
tc1. - Choose the transformation type and the project to which this will be saved.
- You can select the transformation type by expanding the IBM Rational Transformations list and then selecting UML to C++.
- For this exercise, use the existing UML model project to store the transformation configuration file.
- Now, go on to the next screen by clicking Next.
- On the Source and Target tab:
- Select the source as the UML model.
- Create a new managed C++ project as the target.
- Make sure that the source and target are selected, and then click Finish.
Note:
You can edit transformation configuration later, if you wish.
This is going to be easy.
- 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.
- Look at the code generated for the
Routeclass. It containsstartingPointandendingPointattributes, as well as agetFare()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;
}
|
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.
- Set its return type to String.
- Notice that we have also modified the Route.cpp file by adding the method body
for the
getFaremethod. - Run the transformation by using the same transformation configuration (tc1.tc > Transformation > UML to C++).
- 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;
}
|
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.
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.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample UML Model project. | MyAutomobileFleet.zip | 7KB | HTTP |
| Final CPP Project | AutomobileFleetCode.zip | 33KB | HTTP |
Information about download methods
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
- Download a trial version of IBM Rational Systems Developer Version 7.0. The download is free but requires registration.
- Download a trial version of IBM Rational Software Architect Version 7.0. The download is free but requires registration.
- Download IBM product evaluation versions
and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- Participate in the author's developerWorks blog on software modeling and code generation.
- Check out developerWorks blogs and get involved in the developerWorks community.
-
Rational Software Architect, Data Architect, Software Modeler, Systems Developer, Application Developer and Web Developer: Ask questions about Rational Systems Developer, Rational Software Architect, and C++ transformation.

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 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)





