Index by title

Modelio C++ Designer User Guide

Introduction

Modelio C++ Designer tour

Prototyping an application

Managing projects and targets

Implementing an application

Documenting an application

Advanced Modelio C++ Designer features

Automatic guessing

Generating accessors

Variants

UML extensions

Modelio C++ Reverser


Variants step by step

Introduction

This section is a detailed tutorial indicating how to customize the C++ Designer generator. The goal of this example is to handle stereotyped classes to generate specific code.

The customization happens over five stages:

Creating a variant

To create a new variant, you only have to copy the structure of the standard variant directory, found in your project’s resources.


The “standard” variant directory

The “init.py” file is mandatory in the main variant’s directory, as well as in the “acts” directory, in order to make python act available to the engine. If this file is missing, your python ACT won’t be loaded.

The description file must be updated to indicate what your custom variant does.

Name the copied variant “CustomVariant”. For now, remove all content from the “acts” and “types” directories, and open the “products” directory.

Defining a new product

Our new stereotype is available on Classes, that is to say we have to edit the “Class.py” product file.

All we have to do is add a new generation task when an element has the <<CxxCustomClass>> stereotype.

 1# Product definition for Class
 2# Bound variables:
 3#   PRODUCT  the product being build
 4#   ELT      the element to generate
 5
 6import act
 7from java.util import ArrayList
 8from com.modeliosoft.modelio.api.mda.model import ObUtils
 9
10if (CXX.isCxxElement(ELT) and not act.isNoCode(ELT)):
11    # headerFile = CXX.makeNamespacePath(ELT) + "/" + CXX.makeCxxName(ELT) + "." + CXX.makeHeaderFileExtension(ELT)
12    headerFile = CXX.makeDefaultHeaderFilePath(ELT)
13
14    # bodyFile = CXX.makeNamespacePath(ELT) + "/" + CXX.makeCxxName(ELT) + "." + CXX.makeBodyFileExtension(ELT)
15    bodyFile   = CXX.makeDefaultBodyFilePath(ELT)
16
17    files = ArrayList()
18    if (ELT.isStereotyped("CxxCustomClass")):
19        PRODUCT.addFileGeneration(ELT, files, "CustomClassGen")
20    else:
21        if (act.isExternal(ELT)):
22            if (ObUtils.isTagged (ELT, "Cxx.GenerateHeaderFile")):
23                files.add(headerFile)
24        else:
25            files.add(headerFile)
26            files.add(bodyFile)
27        PRODUCT.addFileGeneration(ELT, files, "standard.ClassGen")

The new product file launches a generation using a new ACT, “CustomClassGen”, when the current class is stereotyped <<CxxCustomClass>>. Otherwise, the standard ACT, “ClassGen” is applied.

Using “standard.ClassGen” means the generator will take the “ClassGen” ACT from the standard variant. It is slightly different from entering only “ClassGen”, which would search an ACT with this name in the current variant before launching the standard one.

We now have to add the new ACT called from this product.

Defining a new python ACT

In the “acts” directory of the custom variant, just add a new file called CustomClassGen.py.

Here is a sample showing the content of this file:

 1#
 2# Template CustomClassGen
 3#
 4from com.modeliosoft.modelio.cxxdesigner.engine.act import IAct
 5from com.modeliosoft.modelio.api.model import *
 6from com.modeliosoft.modelio.api.mda.model import ObUtils
 7import act
 8
 9class CustomClassGen (IAct):
10
11    ################################################################################
12    # Generation code
13    #
14    def run(self, ctx, el):
15        hxx = ctx.getOutputs()[0]
16        cxx = ctx.getOutputs()[1]
17
18        hxx.println("// Write custom code for the header here")
19
20        cxx.println("// Write custom code for the header here")

It is usually a better idea to modify an existing ACT rather than to create a new one from scratch.

The variant will be ready to use as soon as it has been declared in your Modelio project.

Declaring the variant

Open the C++ project’s edition box, and select the generation tab.


The “Generation” tab of the project edition box

We have to select the variant in this tab, but this isn’t available right now.

Open the variant management box, in the upper right corner.


The “Variant management” box

Add a new variant, and select the directory corresponding to “CustomVariant”.

Here it is, the variant is available in your project. Once selected, it will be usable for the C++ generation.


XML schema for type guessing

All guessing files must be valid with the following XML schema, corresponding to the “standard/types/ type_guessing.xsd” file.

<?xml version=“1.0” encoding=“utf-8” ?>

<xs:schema attributeFormDefault=“unqualified” elementFormDefault=“qualified” xmlns:xs=“http://www.w3.org/2001/XMLSchema”>

  <xs:simpleType name=“pointer-type”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“” />

      <xs:enumeration value=“PTR” />

      <xs:enumeration value=“REF” />

    </xs:restriction>

  </xs:simpleType>

  <xs:simpleType name=“cli-pointer-type”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“” />

      <xs:enumeration value=“PTR” />

      <xs:enumeration value=“REF” />

      <xs:enumeration value=“CLIPTR” />

    </xs:restriction>

  </xs:simpleType>

  <xs:complexType name=“declaration”>

    <xs:sequence>

      <xs:element minOccurs=“1” maxOccurs=“1” name=“container” type=“xs:boolean” />

      <xs:choice minOccurs=“1” maxOccurs=“1”>

        <xs:element minOccurs=“0” maxOccurs=“1” name=“pointer” type= “pointer-type” />

        <xs:element minOccurs=“0” maxOccurs=“1” name=“cliPointer” type= “cli-pointer-type” />

      </xs:choice>

    </xs:sequence>

  </xs:complexType>

  <xs:complexType name=“typeDef”>

    <xs:sequence>

      <xs:element minOccurs=“0” name=“OptionalSimple” type=“declaration” />

      <xs:element minOccurs=“0” name=“MandatorySimple” type=“declaration” />

      <xs:element minOccurs=“0” name=“OptionalMultiple” type=“declaration” />

      <xs:element minOccurs=“0” name=“MandatoryMultiple” type=“declaration” />

      <xs:element minOccurs=“0” name=“Finite” type=“declaration” />

    </xs:sequence>

  </xs:complexType>

  <xs:complexType name=“types”>

    <xs:sequence>

      <xs:element minOccurs=“1” maxOccurs=“unbounded” name=“basicType”>

        <xs:complexType>

          <xs:complexContent mixed=“false”>

            <xs:extension base=“typeDef”>

              <xs:attribute name=“name” type=“xs:string” use=“optional” />

            </xs:extension>

          </xs:complexContent>

        </xs:complexType>

      </xs:element>

      <xs:element minOccurs=“1” maxOccurs=“unbounded” name=“primitiveType”>

        <xs:complexType>

          <xs:complexContent mixed=“false”>

            <xs:extension base=“typeDef”>

              <xs:attribute name=“name” type=“xs:string” use=“optional” />

            </xs:extension>

          </xs:complexContent>

        </xs:complexType>

      </xs:element>

      <xs:element minOccurs=“1” maxOccurs=“unbounded” name=“classType”>

        <xs:complexType>

          <xs:complexContent mixed=“false”>

            <xs:extension base=“typeDef”>

              <xs:attribute name=“name” type=“xs:string” use=“optional” />

            </xs:extension>

          </xs:complexContent>

        </xs:complexType>

      </xs:element>

    </xs:sequence>

  </xs:complexType>

  <xs:element name=“type-guessing”>

    <xs:complexType>

      <xs:sequence>

        <xs:element minOccurs=“1” maxOccurs=“1” name=“attribute” type=“types” />

        <xs:element minOccurs=“1” maxOccurs=“1” name=“association-end” type=“types” />

        <xs:element minOccurs=“1” maxOccurs=“1” name=“in-parameter” type=“types” />

        <xs:element minOccurs=“1” maxOccurs=“1” name=“inout-parameter” type=“types” />

        <xs:element minOccurs=“1” maxOccurs=“1” name=“return-parameter” type=“types” />

      </xs:sequence>

    </xs:complexType>

  </xs:element>

</xs:schema>


Introducing variants

Overview of variants

Variants are used to implement and/or customize advanced code generation from a UML model.

This chapter covers the concept of code generation using variants, the syntax of templates, type libraries and other elements, and common techniques used to make the most of the flexibility and customization capabilities of the C++ Designer engine.

Concepts

The C++ Designer engine is based on the following concepts:

Variant’s content example

A variant has a specific directory organization, to make the customization easier. The following image shows the content of the standard variant.


Standard variant content

The “acts” directory groups together all active code templates, the “products” directory contains product definition files, and the “types” directory contains all type libraries.

The “description.txt” file is mandatory, and must contain the variant’s description, which will be displayed at runtime when choosing the current variant for a project.

A variant may redefine only part of the module’s behaviour, as the standard behaviour will be taken into account in other cases.

Note: An empty “__init__.py” file must be created in a variant in order for python ACTs to work correctly.


Product file syntax

General structure

A product definition jython file defines behaviour when encountering an element according to its metaclass (represented by the product’s name).

For each particular model element being processed, the product definition associates the element with a particular ACT, and navigates to some other model elements (typically owned by the current element) to repeat the product process recursively.

File generation tasks

A file generation task contains the following parameters:

  1. The element you want to generate on.

  2. The relative path of at least one file to generate (usually both the “header” and “body” files).

  3. The ID of a template that must be used to generate the file contents. IDs can be relative (“PackageGen”) or absolute, with a specific variant name (for example, “standard.PackageGen”).

You must use the PRODUCTS.addFileGeneration method.

Subproduct tasks

A subproduct task contains a list of all model elements to process the products on.

The sub-elements must be given in a List as a parameter of the PRODUCTS.addSubElements method.

Example

 1# Product definition for Package
 2# Bound variables:
 3#   PRODUCT  the product being build
 4#   ELT      the element to generate
 5
 6import act
 7from java.util import ArrayList
 8from com.modeliosoft.modelio.api.mda.model import ObUtils
 9
10if (CXX.isCxxElement(ELT) and not act.isNoCode(ELT)):
11  # headerFile = CXX.makeNamespacePath(ELT) + "/" + CXX.makeCxxName(ELT) + "." + CXX.makeHeaderFileExtension(ELT)
12  headerFile = CXX.makeDefaultHeaderFilePath(ELT)
13
14  # bodyFile = CXX.makeNamespacePath(ELT) + "/" + CXX.makeCxxName(ELT) + "." + CXX.makeBodyFileExtension(ELT)
15  bodyFile   = CXX.makeDefaultBodyFilePath(ELT)
16
17  files = ArrayList()
18
19  if (act.isExternal(ELT)):
20    if (ObUtils.isTagged (ELT, "Cxx.GenerateHeaderFile")):
21      files.add(headerFile)
22  else:
23    files.add(headerFile)
24    files.add(bodyFile)
25
26  PRODUCT.addFileGeneration(ELT, files, "PackageGen")
27
28  subelements = ELT.getOwnedElement()
29
30  PRODUCT.addSubElements(subelements)

Template syntax

General structure

An Active Code Template definition consists of a python or java file found in a variant. It generally follows the text that needs to be generated, involving the navigation through the UML model, extraction of the information from it into the result text, and so on. Active code templates can refer to each other, to allow a better separation of concerns.

Let’s take the “AttributeGen.py” file as an example to show how a python ACT works. It is part of the standard variant, found in C++ Designer’s resources.

The start of an ACT

Every ACT file starts with a comment zone like this:

 1#
 2# Template AttributeGen
 3# Binded variables
 4#   CXX      facilities for Cxx specific production and navigation
 5#   GEN      facilities for code production
 6#   MDL      facilities for model navigation and condition testing
 7#   ENG      ACT ENG (used to call another template))
 8#
 9##############################################################################
10##
11
12# Local utilities functions
13#    naming rules:
14#       - if the utility function directly prints out the generated code it must be named printXXXXX
15#         where XXXX is expected to summarize the function role
16#       - if the utility function returns a piece of generated code as a
17
18string it must be named makeXXXXXX
19#         where XXXX is expected to summarize the function role
20#       - if the utility function is used to get some elements of the model and return a list of model elements (navigation convinience)
21#         it must be named modelGetXXXXX where XXXX is expected to summarize the function role
22#    other rules:
23#       - any utility function takes a model element as first parameter (name it el)
24#       - utility function must not define global variables of their own
25#

This comment indicates: * the current template’s name, AttributeGen * the available global variables for all python files, corresponding to service classes from C++ Designer, CXX, GEN, MDL and ENG * several rules about how functions in an ACT are created

The python module’s declaration then begins:

 1from com.modeliosoft.modelio.cxxdesigner.engine.act import IAct
 2from com.modeliosoft.modelio.api.model import *
 3from com.modeliosoft.modelio.api.mda.model import ObUtils
 4from java.util import ArrayList
 5import act
 6
 7INDENT = _"    "_             # four white spaces
 8
 9class **AttributeGen** (IAct):
10

A python ACT file must implement the com.modeliosoft.modelio.cxxdesigner.engine.act.IAct interface to become available in the engine. It defines only the main entry point of the ACT, which will be described below.

The run function

When evaluating an ACT file, the C++ Designer’s engine always launches run:

 1##############################################################################
 2#
 3# Generation code
 4#
 5
 6  def run(_self_, ctx, attribute):
 7    out = ctx.getOutputs()[0]
 8    self.printAttributeDeclaration(out, attribute)
 9

Three parameters are given to this function:

The first thing to do in the run function is usually to extract the current output from the execution context.

We then have to analyse the given model element to determine which code must be generated. In this example, it is done in a separate utility function.

Utility functions

 1def **makeMemberDeclaration**(_self_, att):
 2    # standard case
 3    # declaration syntax is build as:
 4    #  decl          = $specifiers $decoratedtype $namespacedname$bindings $init;
 5    #  decoratedtype = $containerpointers $container($type)
 6    #  type          = $basetype $pointers
 7    #
 8    # example:
 9    #  static std::vector<int*> C1::att;
10
11    # compute declaration
12    decoratedtype=GEN.makeHxxSignature(att)
13
14    # compute bindings
15    bindings=""
16    if (ObUtils.isTagged(att, "Cxx.Bind")):
17      bindings = "<"
18      for p in ObUtils.getTagValues(att, "Cxx.Bind"):
19        bindings = bindings + p + ", "
20      bindings = bindings.rstrip(", ")
21      bindings = bindings + ">"
22
23    # final assembly
24    decl = decoratedtype + bindings
25
26    return decl
27
28  def printAttributeDeclaration(self, out, el):
29    if act.hasDocumentation(el):
30      out.println(act.makeDocumentationComment(el))
31    out.print(INDENT + _self_.makeMemberDeclaration(el) + ";")
32

Utility functions are the core of the generation process, as they contain the code generation itself.

The naming rule quoted earlier is applied on those two functions; the first one creates a string from an attribute, whereas the second writes content in the output.

When customizing C++ generation, you only have to modify those functions and include the behaviour you need.

Calling another ACT

Active code templates are often divided into several sub-templates, to allow a better understanding and separation of concerns. The ACT engine, given as a global variable (ENG), allows another template to be run and its result obtained. Let’s take a part of another python file as an example,

ClassGen:

 1  def printBodyContent(self, out, el):
 2    out.println()
 3    self.printUseIncludes(out, el)
 4    out.println (_"//class header file"_)
 5    out.printf("#include \"%s\"\n", [CXX.makeHeaderFilename(el)])
 6    out.println()
 7    self.printBodyAutoIncludes(out, el)
 8    self.printIncludeNotes(out, el)
 9    self.printBodyTopNotes(out, el)
10    self.printOpenNamespace(out, el)
11    out.println(ENG.evalAct("ClassDefinitionCxx", el))
12    self.printCloseNamespace(out, el)
13    self.printBodyBottomNotes(out, el)
14

The printBodyContent method is the main part of the body file generation. Includes and notes are produced by several utility functions in ClassGen, but the core of the class content is generated by the ClassDefinitionCxx ACT.

The ENG.evalAct method executes this ACT on the given element, and returns its result (i.e. everything that had been printed in the output), which is itself printed in the current body file.


Type definition syntax

General structure and interpretation rules

An ACT type definition consists of the <type> XML element, which has a number of attributes containing important meta-information about the type, and which contains a <declaration> element defining the type declaration.

An ACT type definition may also contain one or more <include> elements, containing information about #include directives that may be required in order to use this type in generated code.

When Modelio C++ Designer generates code for a UML attribute, parameter or association end,  it considers the type definitions available in the current library path and matches them against the name of the UML element designated as being the type of the attribute/parameter/association end being generated, as well as other decorations (for example containers).

You can generate the type of your choice by creating a new type definitions file in a variant.

Defining a simple type

The following is an example of basic type definition, used when generating a “string” type (used for example by an attribute).

1    <type name="string">
2        <include path="string" />
3        <declaration>std::string</declaration>
4        <decoration>
5            <parameter-passing>REF</parameter-passing>
6            <return-passing>REF</return-passing>
7        </decoration>
8    </type>

With this definition, the generated type will be std::string, and its include also is generated at the beginning of the generated file.

The <decoration> XML element indicates additional C++ decorations that will be added if the type is used in a parameter or a return parameter. Here, a reference is added.

Defining a container

The following is an example of basic type definition, used when generating a “set” container (used for example by an attribute).

1    <type name="set">
2         <include path="set" />
3         <declaration>$containerTypeName&lt;$valueTypeName&gt;</declaration>
4         <container name="std::set" unique="true" ordered="true"/>
5         <decoration>
6              <class-storage>PTR</class-storage>
7         </decoration>
8    </type>

Here, the declaration contains some macros. $containerTypeName corresponds to the container name, defined in the next line, and $valueTypeName is the basic type of the element chosen from your model. Let’s assume this is a “string” attribute.

The <decoration> XML element indicates that an additional C++ decoration will be added to the type stored in the container.

With this definition, the generated type will be std::set<* std::string>, and its include is also generated at the beginning of the generated file.

The <container> XML element also contains two attributes, indicating whether or not the container is unique or order. There properties are used in the container mapping.

Container mapping

When choosing a container in automatic decoration mode, several properties of your UML model are used to choose the best matching container.

The container mapping part of a type definition file indicated how this corresponding container is chosen.

Container kind Has Key Ordered Unique
OrderedMap X X X
UnorderedMap X X
OrderedMultiMap X X
UnorderedMultiMap X
OrderedSet X X
UnorederedSet X
OrderedCollection X
UnorderedCollection

Here is an extract of the container mapping part of the STL type library file:

 1    <container-mapping>
 2        <OrderedMap>
 3            <containerref name="map" />
 4        </OrderedMap>
 5        <UnorderedMap>
 6            <containerref name="hash_map" />
 7            <containerref name="map" />
 8        </UnorderedMap>
 9        <OrderedMultiMap>
10            <containerref name="multimap" />
11        </OrderedMultiMap>
12        <UnorderedMultiMap>
13            <containerref name="hash_multimap" />
14        </UnorderedMultiMap>
15        <OrderedSet>
16            <containerref name="set" />
17        </OrderedSet>
18        <UnorderedSet>
19            <containerref name="hash_set" />
20        </UnorderedSet>
21        <OrderedCollection>
22            <!-- No ordered collection defined -->
23            <degradedKind>UnorderedCollection</degradedKind>
24        </OrderedCollection>
25        <UnorderedCollection>
26            <containerref name="vector" />
27        </UnorderedCollection>
28    </container-mapping>

The <containerref> XML element indicates directly which container should be used.

A <degradedKind> XML element indicates that no defined container respects all the properties, but that another one will be used instead.

In the example given above, when looking for an ordered container, it will correspond to the OrderedCollection kind. No direct match is found, but the UnorderedCollection kind is then chosen, leading to the usage of a “vector” container.


XML schema for type libraries

All type libraries must be valid with the following XML schema, corresponding to the “standard/types/ type_library.xsd” file.

<?xml version=“1.0” encoding=“utf-8” ?>

<xs:schema attributeFormDefault=“unqualified” elementFormDefault=“qualified” xmlns:xs=“http://www.w3.org/2001/XMLSchema”>

  <xs:simpleType name=“passing”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“VALUE” />

      <xs:enumeration value=“REF” />

    </xs:restriction>

  </xs:simpleType>

  <xs:simpleType name=“storage”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“PTR” />

      <xs:enumeration value=“REF” />

    </xs:restriction>

  </xs:simpleType>

  <xs:simpleType name=“cliStorage”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“PTR” />

      <xs:enumeration value=“REF” />

      <xs:enumeration value=“CLIPTR” />

    </xs:restriction>

  </xs:simpleType>

  <xs:simpleType name=“containerKind”>

    <xs:restriction base=“xs:string”>

      <xs:enumeration value=“OrderedMap” />

      <xs:enumeration value=“UnorderedMap” />

      <xs:enumeration value=“OrderedMultiMap” />

      <xs:enumeration value=“UnorderedMultiMap” />

      <xs:enumeration value=“OrderedSet” />

      <xs:enumeration value=“UnorderedSet” />

      <xs:enumeration value=“OrderedCollection” />

      <xs:enumeration value=“UnorderedCollection” />

    </xs:restriction>

  </xs:simpleType>

  <xs:complexType name=“containerDeclaration”>

    <xs:attribute name=“name” type=“xs:string” use=“required” />

    <xs:attribute name=“unique” type=“xs:boolean” use=“required” />

    <xs:attribute name=“ordered” type=“xs:boolean” use=“required” />

  </xs:complexType>

  <xs:complexType name=“containerRef”>

    <xs:choice minOccurs=“1” maxOccurs=“unbounded”>

      <xs:element minOccurs=“1” maxOccurs=“1” name=“degradedKind” type=“containerKind” />

      <xs:element name=“containerref”>

        <xs:complexType>

          <xs:attribute name=“name” type=“xs:IDREF” />

        </xs:complexType>

      </xs:element>

    </xs:choice>

  </xs:complexType>

  <xs:element name=“type-library”>

    <xs:complexType>

      <xs:sequence>

        <xs:element minOccurs=“0” maxOccurs=“unbounded” name=“type”>

          <xs:complexType>

            <xs:sequence>

              <xs:element minOccurs=“0” maxOccurs=“1” name=“include”>

                <xs:complexType>

                  <xs:attribute name=“path” type=“xs:string” use=“required” />

                </xs:complexType>

              </xs:element>

              <xs:element minOccurs=“1” maxOccurs=“1” name=“declaration”>

                <xs:complexType>

                  <xs:simpleContent>

                    <xs:extension base=“xs:string” />

                  </xs:simpleContent>

                </xs:complexType>

              </xs:element>

              <xs:element minOccurs=“0” maxOccurs=“1” name=“container” type=“containerDeclaration” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“decoration”>

                <xs:complexType>

                  <xs:choice minOccurs=“1” maxOccurs=“1”>

                    <xs:sequence minOccurs=“1” maxOccurs=“1”>

                      <xs:element minOccurs=“1” maxOccurs=“1” name= “parameter-passing” type=“passing” />

                      <xs:element minOccurs=“1” maxOccurs=“1” name= “return-passing” type=“passing” />

                    </xs:sequence>

                    <xs:choice minOccurs=“1” maxOccurs=“1”>

                      <xs:element minOccurs=“0” maxOccurs=“1” name= “class-storage” type=“storage” />

                      <xs:element minOccurs=“0” maxOccurs=“1” name=“cli- class-storage” type=“cliStorage” />

                    </xs:choice>

                  </xs:choice>

                </xs:complexType>

              </xs:element>

            </xs:sequence>

            <xs:attribute name=“name” type=“xs:ID” use=“required” />

          </xs:complexType>

        </xs:element>

        <xs:element minOccurs=“1” maxOccurs=“1” name=“container- mapping”>

          <xs:complexType>

            <xs:sequence>

              <xs:element minOccurs=“1” maxOccurs=“1” name=“OrderedMap” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“UnorderedMap” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“OrderedMultiMap” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“UnorderedMultiMap” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“OrderedSet” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“UnorderedSet” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“OrderedCollection” type=“containerRef” />

              <xs:element minOccurs=“1” maxOccurs=“1” name=“UnorderedCollection” type=“containerRef” />

            </xs:sequence>

          </xs:complexType>

        </xs:element>

      </xs:sequence>

      <xs:attribute name=“id” type=“xs:string” use=“required” />

    </xs:complexType>

  </xs:element>

</xs:schema>


Automatic guessing on association ends

Automatic guessing on association ends happens when C++ Designer is generating the code for an association end and when the automatic generation flag is set.

Association ends point to classes, therefore the automatic guessing algorithm will favor pointer declaration of objects and will avoid passing any object by value for performance reasons.

For an association end, the relevant information is as follows:

The following list shows the generated declaration for an association end named “assoc”.
Association end type: MyClass

Association end type: MyDatatype isPrimitive=false

Note 1:  As an association end is made to associate two complex classes, even primitive types are treated as complex.

Note 2: The std::vector is replaced by:


Automatic guessing on attributes

Automatic guessing on attributes happens when C++ Designer is generating the code for a single attribute for which the automatic generation flag is set.

For attributes, which in most cases are supposed to be primitive types (integer, float, char, boolean), the automatic guessing algorithm will favour declaration by value. However, pointer declaration will be used to deal with the 0 minimum cardinality cases.

For automatic guessing on attributes, the relevant information is as follows:

The following list shows the generated declaration for an attribute named “att”.





Note 1: Where the table states integer, this can be any basic type (integer, char, float, boolean).

Note 2: The std::vector is replaced by:

Note 3: An element typed undefined is generated as void*.


Generating accessors for associations

These are the accessors generated by C++ Designer when the “Create accessors” command is activated. These accessors are created in the model. They are automatically decorated for C++ generation.

Note:  Accessors with maximum cardinality “*” return a reference to the internal collection, so the user can directly manipulate the container contents using the accessors specific to the container type.  There are no “set” accessors for these cases and we recommend that you use the “get” accessor and the proper container API on the returned value.


Generating accessors for attributes

These are the accessors generated by C++ Designer when the “Create accessors” command is activated.  These accessors are created in the model, meaning they are created in the form of modeled methods.  They are automatically decorated for subsequent C++ generation.

Note 1: Where the table states integer, this can be any basic type (integer, char, float, boolean).

Note 2: Accessors with maximum cardinality “*” return a reference to the internal collection, so the user can directly manipulate the container contents using the accessors specific to the container type.  There are no “set” accessors for these cases and we recommend that you use the “get” accessor and the proper container API on the returned value.


Automatic guessing on parameters

Automatic guessing on parameters

Automatic guessing on parameters happens when C++ Designer is generating the code for a parameter for which the automatic generation flag is set.

For parameters, the automatic guessing algorithm selects the best way of passing a parameter, based on good practices:

The C++ Designer generator also takes care of the parameter passing mode (In or InOut) in order to further optimize the generated code.

Automatic guessing on “In” parameters

The following list shows the generated declaration for a parameter named “param”. Please note that the use of const values is favored due to the “In” mode.

Note 1: Where the table states integer, this can be any basic type (integer, char, float, boolean).

Note 2: An element typed undefined is generated as void*.

Automatic guessing on “InOut” parameters

The following liste shows the generated declaration for a parameter named “param”. Please note that no const values are used due to the “InOut” mode.

Note 1: Where the table states integer, this can be any basic type (integer, char, float, boolean).

Note 2: An element typed undefined is generated as void*.


Automatic guessing on return parameters

Automatic guessing on return parameters happens when C++ Designer is generating the code for a return parameter for which the automatic generation flag is set.

The following table shows the generated declaration for a return parameter.

Note 1: Where the table states integer, this can be any basic type (integer, char, float, boolean).

Note 2: Return parameters never return a collection, but simply a pointer to the first element of an array. This is because no assumptions can be made by C++ Designer about the internal implementation of the method returning the parameter. In real life, a reference to the container will most often be returned.

Note 3: For returned values with a minimum cardinality of 0, a pointer is returned, which allows the expression of the absence of any useful value (in which case a null pointer can be returned).


Generating and visualizing documentation

Introduction

With Modelio C++ Designer, you can conveniently browse doxygen documentation for particular model elements.

To generate documentation, simply select a doxygen target from the DeploymentData package, and launch the “Generate doxygen documentation” command.


Launching the “Generate doxygen documentation” command

Modelio C++ Designer lets you directly browse documentation using your default web browser for classes, interfaces and namespace producing packages. For attributes, operations, parameters and other structural features, Modelio C++ Designer presents the documentation of the owner class. Simply launch the  "Visualize doxygen documentation" command.


Documenting a model element

The Modelio C++ Designer GUI can be used to conveniently enter and modify brief summary and detailed documentation notes directly from the “C++” property view and from the dedicated tab of the C++ edition dialog boxes.

To document a model element, simply select it and then enter the associated documentation text in the “Summary” and “Documentation” fields of the “C++” property view.

Modelio C++ Designer translates the contents of notes as follows:

Documentation for UML operation parameters is automatically grouped with the operation doxygen comment.


The “Summary” and “Documentation” fields in the “C++” property view

The “C++” property view is very practical when entering single line notes, but less convenient for complex multi-line documentation notes.
For optimal comfort and convenience, you can enter multi-line documentation notes in the C++ edition dialog boxes.


The “Documentation” tab of a C++ edition dialog box

The “Documentation” tab is present in all C++ edition dialog boxes.

Documentation can also be entered without using the Modelio C++ Designer GUI. You can enter summary notes in “comment” notes and documentation notes in “Cxx.Doc.Doxygen” or “description” notes.

Modelio C++ Designer produces the following code for the “TaskWindow” class, where the summary and documentation notes are injected as a doxygen comment with automatically generated “brief” tag and our tags.

 1//includes for used library types
 2#include <cstringt.h>
 3#include <afxwin.h>
 4#include <afxtempl.h>
 5#include <afxcoll.h>
 6
 7//automatic includes (friends, associated classes, etc)
 8#include "MyPlanner/CWnd.h"
 9#include "MyPlanner/ITaskView.h"
10#include "MyPlanner/Task.h"
11
12namespace MyPlanner
13{
14    /**
15    \brief
16    Task visualization window
17
18    The class is used to graphically represent Task data.
19    Namely, the class is used to render:
20    - task information
21    - task status
22    - subtasks
23    - resources
24    \todo
25    Implement message handlers
26    **/
27    class TaskWindow : public CWnd, public ITaskView
28    {
29        //...
30        private:
31            CString displayTitle;
32
33        public:
34            CDC dc;
35
36        //associations
37
38        public:
39            Task* task;
40            CMap<CString,CString&,CBrush,CBrush&> brushResource;
41
42        //operations
43
44        public:
45            TaskWindow();
46            TaskWindow(const TaskWindow& value);
47            TaskWindow& operator =(const TaskWindow& value);
48            ~TaskWindow();
49            void formatDisplayTitle(std::string& FormatStr);
50            CDC getDc();
51            afx_msg int OnCreate(CREATESTRUCT* lpCreateStruct);
52
53        //non-modeled members
54
55        protected:
56            DECLARE_MESSAGE_MAP()
57    };
58
59}
60

Introduction to documenting an application

With Modelio C++ Designer, you can conveniently enter documentation for application models. Documentation is produced in doxygen HTML format, which is widely used in the C++ world.  This format is convenient for browsing and can be easily converted to other formats, such as CHM.

Modelio C++ Designer manages the documentation management process as follows:

Documentation generation targets provide the options used to drive doxygen behaviour. Modelio C++ Designer translates these options into the doxygen command file, which is processed by the doxygen binary.

Note: If you are using Windows, the Windows version of doxygen must be used. Don’t use the version of doxygen provided by the Cygwin tool.


Extensions on association ends

Tagged values on association ends

Name Label Parameters Behaviours
Cxx.BasicType Basic Type Type Indicates a basic type that will be converted to a specific type in the current type package.

Stereotypes on association ends

Name Label Behaviours
Cxx.CLI.AssociationEndProperty CLI Property Indicates that this element represents a CLI property.

Tagged values on <<CLI Property>> association ends

Name Label Parameters Behaviours
Cxx.CLI.Abstract Abstrac N/A Indicates that the property is abstract.
Cxx.CLI.GetterVisibility Getter visibility Visibility kind Specifies the visibility of the generated getter.
Cxx.CLI.Override Override N/A Indicates that this property overrides a virtual one.
Cxx.CLI.Sealed Sealed N/A Indicates that the property is sealed.
Cxx.CLI.SetterVisibility Setter visibility Visibility kind Specifies the visibility of the generated setter.

Notes on <<CLI Property>> association ends

Name Label Behaviours
Cxx.CLI.GetterCode Getter code Contains the code to insert in the generated getter.
Cxx.CLI.SetterCode Setter code Contains the code to insert in the generated setter.

Extensions on attributes

Tagged values on attributes

Name Label Parameters Behaviours
Cxx.BasicType Basic Type Type Indicates a basic type that will be converted to a specific type in the current type package.

Stereotypes on attributes

Name Label Behaviours
Cxx.CLI.AttributeProperty CLI Property Indicates that this element represents a CLI property.

Tagged values on <<CLI Property>> attributes

Name Label Parameters Behaviours
Cxx.CLI.Abstract Abstract N/A Indicates that the property is abstract.
Cxx.CLI.GetterVisibility Getter visibility Visibility kind Specifies the visibility of the generated getter.
Cxx.CLI.Override Override N/A Indicates that this property overrides a virtual one.
Cxx.CLI.Sealed Sealed N/A Indicates that the property is sealed.
Cxx.CLI.SetterVisibility Setter visibility Visibility kind Specifies the visibility of the generated setter.

Notes on <<CLI Property>> attributes

Name Label Behaviours
Cxx.CLI.GetterCode Getter code Contains the code to insert in the generated getter.
Cxx.CLI.SetterCode Setter code Contains the code to insert in the generated setter.

Extensions on classes

Stereotypes on classes

Name Label Behaviour
Cxx.CLI.Attribute CLI Attribute Indicates that this class defines a CLI attribute.
Cxx.CLI.Class CLI Class Indicates that this element is a CLI class.
Cxx.CLI.DelegateContainer CLI Delegate Container Indicates that this element is a container for delegates.
Cxx.CLI.Indexer CLI Indexer Indicates that this class is a CLI indexer.
CxxClass C++ Class Indicates that this element is a C++ class.

Tagged values on <<C++ Class>> classes

Name Label Parameters Behaviour
Cxx.Class.Friend Friend Class name Specifies the name of the friend class.
Cxx.ClassTemplate.Instantiate Instanciation parameters Specifies class template instanciation parameters.
Cxx.DeclarationSpecifier Declaration Specifier Declaration Specifier Declares a class import and export for Windows DLL. Puts the parameter value between the class keyword and the name of the class.
For example : the class MyFacade is tagged Cxx.DeclarationSpecifier("DLLExport").
The header will be generated with : class DLLExport MyFacade
Cxx.Struct Is a structure N/A Specifies that a class must be generated as a structure instead of a class.
Cxx.Union Is a union Extends clause Specifies that a class must be generated as a union instead of a class.

Notes on <<C++ Class>> classes

Name Label Behaviour
Cxx.Class.CopyConstructor.Code Copy constructor code Contains the code to insert into the copy constructor.
Cxx.Class.Destructor.Code Destructor code Contains the code to insert into the destructor.

Tagged values on <<CLI Class>> classes

Name Label Parameters Behaviour
Cxx.CLI.Visibility Visibility Visibility kind Specifies the visibility of this class.

Notes on <<CLI Class>> classes

Name Label Behaviour
Cxx.CLI.Attribute Attributes Contains all the attributes defined on that class.

Tagged values on <<CLI Attribute>> classes

Name Label Parameters Behaviour
Cxx.CLI.Attribute.AllowMultiple Allow Multiple N/A Allows multiple C# attributes on a field.
Cxx.CLI.Attribute.Inherited Inherited N/A Adds the attribute inheritance.
Cxx.CLI.Attribute.Targets Targets The targets of the attribute. Adds an attribute target to the class.

Extensions on datatypes

Stereotypes on datatypes

Name Label Behaviours
CxxDataType C++ DataType Indicates that this data type is generated as a typedef.

Tagged values on datatypes

Name Label Parameters Behaviours
Cxx.DataType.Anonymous Is anonymous N/A Indicates that the name of the DataType is never used, but rather its definition instead.

Extensions on dependencies

Stereotypes on dependencies

Name Label Behaviours
Cxx.FileGroup FileGroup Indicates that several classes must be generated in the same file.

Extensions on enumerations

Stereotypes on enumerations

Name Label Behaviours
Cxx.CLI.Enumeration CLI Enumeration Indicates this enumeration is a CLI enumeration.
CxxEnumeration C++ DataType Indicates this enumeration is generated.

Tagged values on <<CLI Enumeration>> enumerations

Name Label Parameters Behaviours
Cxx.CLI.EnumerationType Enumeration Type Type Specifies the enumeration's type.

Extensions on generalizations

Tagged values on generalizations

Name Label Parameters Behaviours
Cxx.Generalization.ParentVisibility Parent visibility A visibility Specifies the visibility of the super class. Can be public, protected or private.
Cxx.Generalization.Virtual Is virtual N/A Specifies a generalization as being virtual.

Extensions on general classes

Tagged values on general classes

Name Label Parameters Behaviours
Cxx.Class.Extends Extends Classes Textually specifies the extends clause of a class, including visibility and optional virtual clause.

Notes on general classes

Name Label Behaviours
Cxx.Class.Member.Private Private members Contains code to insert into the private declaration of the class.
Cxx.Class.Member.Protected Protected members Contains code to insert into the protected declaration of the class.
Cxx.Class.Member.Public Public members Contains code to insert into the public declaration of the class.

Extensions on interfaces

Stereotypes on interfaces

Name Label Behaviours
Cxx.CLI.Interface CLI Interface Indicates that this element is a CLI interface.
CxxInterface C++ Interface Indicates that this element is a C++ class containing only virtual functions.

Extensions on model elements

Tagged values on model elements

Name Label Parameters Behaviours
Cxx.Name C++ Name string Specifies a C++ name for the parameter.
Cxx.Bind Bind Type Specifies template instanciation parameters.
Cxx.Container Container Container name Specifies a container to use if the element has a cardinality of *.
Cxx.Container.Pointer Container pointer & or * Specifies the pointer modifier to use for the container declaration. Must be & or *.
Cxx.Container.Specifier Container specifiers C++ specifier Owns a specifier for the container of the element (for example, const).
Cxx.GenFullName Generate full name N/A Specifies that the element must be generated with a namespaced type.
Cxx.Lib Library N/A Specifies the name of the library to use to declare the element.
Cxx.Lib.ImportTypes Import type from library Type identifier Uses a specific type from a specific type library.
Cxx.NoCode Do not generate N/A Specifies that the element must not be generated by Modelio C++ Designer.
Cxx.Pointer Pointer & or * Specifies the pointer modifier to use. Must be & or *.
Cxx.Specifier Specifiers C++ specifier Owns a specifier for the element (for example, const).
Cxx.TypeExpr Manual declaration declaration Specifies the declaration to use for the element. You can use $name to automatically insert the name of the element into the declaration.
Cxx.Use.Class Use class Classes Adds an include towards a class in the body or the header.
Cxx.Use.Package Use package Packages Adds an include towards a package in the body or the header.

Notes on model elements

Name Label Behaviours
Cxx.Body.Bottom Body bottom Contains code to insert at the bottom of the body file.
Cxx.Body.Top Body top Contains code to insert at the top of the body file.
Cxx.Code C++ Code Contains the operation's implementation code.
Cxx.Doc.Doxygen Doxygen documentation Contains the text to insert in the doxygen comment.
Cxx.Header.Bottom Header bottom Contains code to insert at the bottom of the header file.
Cxx.Header.Top Header top Contains code to insert at the top of the header file.
Cxx.Use.Body Body uses Uses to add in the body file.
Cxx.Use.Header Header uses Uses to add in the header file.
Cxx.Value Default value Specifies a default value.

Stereotypes on model elements

Name Label Behaviours
Cxx.External External Indicates this element represents a class that is not modeled, usually to include it from another class.

Tagged values on <<External>> model elements

Name Label Parameters Behaviours
Cxx.GenerateHeaderFile Generate header file N/A Specifies that a header file containing the given includes must be generated.
Cxx.IncludePath Include paths File names Indicates the includes to be used for this element.

Extensions on operations

Tagged values on operations

Name Label Parameters Behaviours
Cxx.CLI.NewOperation CLI New N/A Indicates that this function does not override a base class method.
Cxx.Operation.Disposition Is inline inline Specifies the disposition of an operation (inline or not). The parameter must include “inline”.
Cxx.Operation.Explicit Is explicit N/A Specifies that the constructor must be generated as an explicit constructor.
Cxx.Operation.Throws Throws Exception name Specifies a set of exceptions thrown by the operation.
Cxx.TypeExpr.Body Content declaration Type Manual declaration.

Notes on operations

Name Label Behaviours
Cxx.Operation.Constructor.Base Constructor Base Contains code to insert at constructor transmission.
Cxx.Operation.Postcondition Postcondition Specifies a postcondition of the operation.
Cxx.Operation.Precondition Precondition Specifies a precondition of the operation.
Cxx.Operation.Returned Returned Contains the operation's return statement.

Stereotypes on operations

Name Label Behaviours
Cxx.Accessor Accessor Indicates this operation is an automatically managed accessor.
Cxx.CastOperator Cast Operator Specifies the operation as a cast operator redefinition.
Cxx.CLI.Delegate CLI Delegate Indicates this operation is a CLI delegate.
Cxx.CLI.StaticConstructor CLI Static Constructor Indicates this operation is a static CLI constructor.
Cxx.Operator Operator Specifies the operation as an operator redefinition.

Extensions on packages

Stereotypes on packages

Name Label Behaviour
Cxx.CLI.Package CLI Package Indicates this element is a CLI package.

All elements created in this package will be CLI elements by default rather than UML elements.
CxxPackage C++ Package Indicates this element is a C++ package.

All elements created in this package will be C++ elements by default rather than UML elements.

Tagged values on <<C++ Package>> and <<CLI Package>> packages

Name Label Parameters Behaviour
Cxx.Package.DirectoryName Directory name Include file Specifies a name for the directory corresponding to this package.
Cxx.Package.GenInterface Generate interface N/A Automatically generates forward declaration of the public element of the package in the package header file.
Cxx.Package.NoDirectory No directory N/A Specifies that the package must not be generated as a directory.
Cxx.Package.NoNamespace No namespace N/A Specifies that the package must not be generated as a C++ namespace.

Notes on <<C++ Package>> and <<CLI Package>> packages

Name Label Behaviour
Cxx.Body.NamespaceMember Header namespace member Contains code to insert into the namespace implementation in the package body file.
Cxx.Header.NamespaceMember Body namespace member Contains code to insert into the namespace declaration in the package header file.

Extensions on signals

Stereotypes on signals

Name Label Behaviour
Cxx.CLI.Event CLI Event Specifies this signal represents a CLI event.

Tagged values on <<CLI Event>> signals

Name Label Parameters Behaviour
Cxx.CLI.StaticEvent Static event N/A Indicates this event is static.

Notes on <<CLI Event>> signals

Name Label Behaviour
Cxx.CLI.Event.EventBlock Event block Contains the content of the event block.

Extensions on template parameters

Stereotypes on template parameters

Name Label Behaviour
Cxx.CLI.TemplateParameter CLI Template Parameter Adds a constraint clause to the template.

Tagged values on <<CLI Template Parameter>> template parameters

Name Label Parameters Behaviour
Cxx.CLI.ConstraintClause Constraint Clause Clause Adds a constraint clause to the template.

The Introduction topic

The Introduction topic of the Modelio C++ Designer user guide is where you’ll find everything you need to know about the main features of this module.

The Introduction topic contains the following sections:


The Modelio C++ Designer Tour topic

The Modelio C++ Designer Tour topic of the Modelio C++ Designer takes you on a detailed tour of all the features of this module.

Starting out by describing how you can prototype an application, this chapter goes on to describe in detail project and target management, application implementation and documentation.

The Modelio C++ Designer Tour topic contains the following chapters and sections:

Prototyping an application

Managing projects and targets

Implementing an application

Documenting an application


The Prototyping An Application topic

The Prototyping An Application topic of the Modelio C++ Designer user guide describes how to get started with the C++ Designer module, and details the main concepts it implements.

The Prototyping An Application topic contains the following sections:


The Managing Projects And Targets topic

The Managing Projects And Targets topic of the Modelio C++ Designer user guide is where you’ll find everything you need to know about build project and target management, including details on the different options you can use.

The Managing Projects And Targets topic contains the following sections:


The Implementing An Application topic

The Implementing An Application topic of the Modelio C++ Designer user guide brings you everything you need to know about how to implement your applications using the C++ Designer module.

The Implementing An Application topic contains the following sections:


The Documenting An Application topic

The Documenting An Application topic of the Modelio C++ Designer describes how to quickly and efficiently document your C++ application models with the C++ Designer module, before generating documentation in doxygen format.

The Documenting An Application topic contains the following sections:


The Advanced Modelio C++ Designer Features topic

The Advanced Modelio C++ Designer Features topic of the Modelio C++ Designer user guide describes in detail the advanced features provided by this module.

From automatic guessing, to accessor generation, this chapter is where you’ll find everything you need to know to use advanced C++ Designer features. Variants are described in detail, as are UML extensions.

The Advanced Modelio C++ Designer Features topic contains the following chapters and sections:

Automatic guessing

Generating accessors

Variants

UML extensions


The Automatic Guessing topic

The Automatic Guessing topic of the Modelio C++ Designer user guide describes exactly what happens to different elements during code generation when the automatic generation flag is set.

The Automatic Guessing topic contains the following sections:


The Generating Accessors topic

The Generating Accessors topic of the Modelio C++ describes the accessors generated by C++ Designer when the “Create accessors” command is activated. Accessors are created in the model, meaning they are created in the form of modeled methods, and they are automatically decorated for subsequent C++ generation.

The Generating Accessors topic contains the following sections:


The Variants topic

The Variants topic of the Modelio C++ Designer user guide presents in detail variants, which are used to implement and/or customize advanced code generation from a UML model. Among the concepts described are product file and template syntax, and XML schemas for type libraries and type guessing.

The Variants topic contains the following sections:


The UML Extensions topic

The UML Extensions topic of the Modelio C++ Designer user guide lists the various UML extensions (tagged values, notes and stereotypes) which can be used to annotate different elements.

The UML Extensions topic contains the following sections:


The Modelio C++ Reverser topic

The Modelio C++ Reverser topic of the Modelio C++ Designer user guide describes in detail the features provided by the Modelio C++ Reverser module.

From information on reverse modes and how to launch reverse operations to details on UML equivalence and restrictions, this chapter is where you’ll find everything you need to know to use C++ Reverser.

The Modelio C++ Reverser topic contains the following sections:


Customization

Variants

A variant is a customization unit for the C++ module that must be declared in a C++ project before being used.

Variants can be divided into the following categories:

You can create your own type variants by writing custom type definitions and ACTs, or use the standard one, already included in C++ Designer.

ACTs

The core of Modelio C++ Designer is an Active Code Template (ACT) processor.  An ACT is a python or java file to be used at generation, which groups together:

Generation products

ACTs are linked to model elements and output files by generation products. A generation product is a python script which links a UML metaclass, a condition defining when elements of this metaclass are translated, an ACT defining how these elements are translated, and the name of the output files containing the generated code.

You can define your own generation product by associating:

This means that you can define custom output, in addition to generated C++ code (IDL definitions or Java Native Interface wrappers, documentation in custom format, and so on).

Modelio C++ Designer can simultaneously support a number of generation product definitions.

Type libraries

A type library groups together definitions of types. A type definition associates a UML type with a C++ declaration, where the name of a UML structural feature or operation parameter will be substituted, and a list of include directives required to use the C++ type.

A UML type can be a primitive type, a data type or a collection type. Collection types are used to represent attributes and association ends with multiple cardinalities. The definition of a collection type also provides a high-level description of collection semantics – such as “OrderedCollection” – which is mapped to decorations automatically deduced from high-level UML model properties. This allows Modelio C++ Designer to automatically express high- level UML model semantics through particular C++ collection types.

When Modelio C++ Designer translates a structural feature or an operation parameter, it constructs the C++ declaration in accordance with its type and the current type library, and executes ACTs defined in the library, if they override the core ACTs defined for the element.


C++ modeling and code generation

Introduction

Code generation consists of producing C++ source files from UML model packages and classes. The actual rules used to map packages and classes to directories and files are presented later in this user guide.

UML model elements themselves are not enough to adequately describe C++ applications, for example, to describe the container (collection) types required to store multiple attributes or to describe pointer semantics.  This means that before proceeding with C++ generation, the UML model must be decorated using additional model elements, tagged values, stereotypes and notes, which describe its C++-specific semantics and behavior.

Modelio C++ Designer supports two usage modes:

Conception mode

In conception mode, you focus on high-level model properties: application entities (modeled by UML classes), their relations (modeled by associations and links) and attributes, and their contracts (modeled by UML operations). When conceiving a model, you do not want to be distracted by low-level C++ details, such as the representation of a given multiple association by a vector or hash map, or the passing of a given operation parameter by a pointer or by a value.

To help you get quality C++ code directly from high-level models, Modelio C++ Designer automatically deduces C++-specific model decorations (C++ properties) from high-level UML model properties. Modelio C++ Designer then analyzes UML attributes, such as ordering and uniqueness, and applies C++ expert logics and best practices to derive reasonable decorations and subsequently C++ code, which adequately expresses model semantics.

With Modelio C++ Designer, you can immediately check your application models, and supports advanced modeling concepts, such as agile modeling.  It tightens the link between application model and code, and extends the limits of UML model usage in the development process, thereby making UML models a practical development tool.

Implementation mode

In implementation mode, you manage C++-specific application properties yourself, and specify C++ properties by manually decorating the model. The C++-oriented GUI hides the underlying UML extensions, making it easy to work in C++ terms and to immediately observe the effects of decorations on the generated C++ code.

Modelio C++ Designer supports transparent switching between the conception and implementation modes. You can reinforce the results of automatic deduction by adding your own decorations. For instance, once a model is automatically decorated and prototype C++ code has been generated, you can create C++ code notes, specifying detailed application behavior.  You can indicate that a model element is to be ignored by automatic deduction and manually decorate it instead.  This can be very practical when the results of automatic deduction do not correspond to your needs, for example, when you need to override a function defined in an external library, such as a message handler.  Modelio C++ Designer transparently deduces decorations for high-level model parts and retrieves decorations specified by you.

Model-level accessors

The methods used to access the attributes of application classes provide an important part of the model semantics. However, these accessors are traditionally produced only at code level. Modelio C++ Designer is the first solution to support model-level accessors.

When you specify an “open” access mode (“read”, “write” or both) for an attribute or association end, Modelio C++ Designer automatically creates a UML operation in the respective class, which implements the respective access method, and then automatically deduces the C++ decorations of its return types and parameters, before automatically generating its [prototype] code.

The generation of accessors directly at UML model level lets you explicitly express access semantics at a high level, according to the access patterns you have chosen, thereby constituting a solid bridge between the application model and the code.

Model-level creation operations

C++ requires that the creation and destruction behavior of each class object be explicitly specified. Modelio C++ Designer is the first solution to maintain these semantics at model level.

When you create a class, Modelio C++ Designer automatically creates its default constructor, destructor, and assignment operator, in accordance with C++ best practices. It automatically deduces the C++ decorations of their parameters, and generates some of their code and “to do” notes, reminding you to implement the creation and destruction of the class objects.

Constructors are implemented by design patterns. A creation pattern defines a set, particular signature and creation operation code, and possibly other model elements, such as class factories. These patterns are dynamic, meaning that when a class is updated (its name is changed), the related creation operations are automatically updated according to the pattern.

The automatic generation of creation operations at model level simplifies the essential task of implementing creation behavior, and constitutes a solid bridge between the application code and the model.

Control and flexibility

Through the transparent support of the conception and implementation modes and the support of dynamic patterns for model-level accessor and creation operations, you can benefit from a high level of automation, simplicity and flexibility, as well as full control over C++ code generation from the early development process steps onwards.

Permanent model-code consistency

In addition to the conception and implementation modes and model-level dynamic patterns, the consistency of the UML model and the generated code is maintained through the model-driven generation mode.

This model-driven generation mode allows the generation of the entire C++ application from the model, as well as the retrieval of the code, inserted or edited externally using dedicated markers. This means that full model-code consistency is permanently ensured.


Other features

Compilation

Compilation consists of producing binary output from generated C++ files. With Modelio C++ Designer, you can run compilation in one click from the property view.

Generating documentation

This operation consists of producing documentation from generated C++ files. Documentation is produced in doxygen HMTL format, which is widely used in the C++ world. The doxygen format is convenient for browsing and can be easily converted to other formats, such as CHM.

UML model elements are documented by entering specific notes, which can contain doxygen tags.  The Modelio C++ Designer GUI lets you conveniently enter and modify brief summary and detailed description notes directly from the C++ property view and from the dedicated tab in the C++ edition dialog boxes.

Build projects and targets

Modelio C++ Designer natively supports the management of build projects and targets.

A build target defines a build rule – code generation, documentation generation or compilation – for a UML model part.  A target stores build options, such as the output path or default type library for C++ code generation.

A build project defines a set of build rules expressed by generation, documentation and compilation targets for the whole UML model or the model part, which is referred to as being manifested by the project.

A project can be associated with several build targets of the same type. You can easily run code generation and compilation for several target compilers, or generate debug and release code in different directories.

The UML model can be associated with several build projects, which can manifest intersecting model parts. This means that in one click you can generate code, produce documentation and compile only for necessary model parts, for instance to generate only library code or library tests.

Modelio C++ Designer provides a convenient project & target management GUI, which is used to create or modify projects, to associate model parts with projects, to create build targets and to specify their options.

Build projects and targets are represented at UML model level, meaning that they are handled directly as standard UML model elements.

The possibility of managing build projects and targets and expressing them in the UML model provides you with a simpler control application development process directly at UML level, thereby making the UML modeling environment ideal for C++ application development.


Introducing Modelio C++ Designer

Introduction

Welcome to the Modelio C++ Designer user guide!

Modelio C++ Designer is a solution for developing applications in UML 2 and C++ and for managing the development process. This user guide explains how to use the powerful application and platform development functions provided by Modelio C++ Designer.

Modelio C++ Designer functions

Modelio C++ Designer provides the following functionalities:

Prerequisites

The Cygwin tool must be installed on your workstation, in order for you to be able to use the following tools it provides:


Note regarding teamwork

Modelio C++ Designer works in a teamwork environment, with only simple restrictions to locked model elements.

In a common model, Modelio C++ Designer behaves as follows:

Consequently, the following two important rules must be respected:

If these two rules are not respected, Modelio C++ Designer will display an error message.


Creating and editing projects

Modelio C++ Designer provides a convenient project management GUI, which is used to create or modify projects, associate model parts with projects, create build targets and to specify their options.

To create a project, select the root package and run the ../cxx_images/mda_group_expl.png "Create C++ Designer element/Project" command from the context menu.


Creating a new project

All projects and targets are stored in the “DeploymentData” package. When a new project is created, Modelio C++ Designer automatically creates and associates three targets with the project:

Note: Default C++ code and doxygen documentation generation options and compilation options must be specified by Modelio C++ Designer parameters in order to properly initialize automatically created targets.

The project management dialog can also be accessed by selecting a target, and running the ../cxx_images/mda_group_expl.png "Edit project" command in the C++ Designer property view.


Accessing the project edition window through the property view

With Modelio C++ Designer, you can create several projects for the model and several targets for a project. However, only one project can be active at any given time.

In the UML model navigator, the active project is identified with a specific icon  . To change the active project, select another one and check the “Is active” tickbox in the C++ Designer property view.


C++ code generation options

Editing project generation options

The figure below shows the “Generation” tab of the project edition box, in which you can specify code generation options for the selected project.


The “Generation” tab of the project edition box

You can specify the following options:

Managing variants

Variants are used for advanced customization of the C++ Designer module.

The  "Manage Variant" command opens the variant manager, used to install new variants for the module, or uninstall existing variants.


The variant management box

1.: Opens a file chooser to install a new variant. You must select the variant directory itself, not the “act” or “product” directory.

2.: Removes the selected variant from the project. Obviously, it is impossible to delete the standard behaviour.

3.: Displays all variants available in this project.

4.: The directory corresponding to the selected variant. You should only use variants coming from the current project space, to avoid problems when exchanging your projects.

5.: The name of the selected variant, coming from the directory name.

6.: The extension of the body files produced by the target.

7.: The description of the selected variant.

Note 1:     See the “Active Code Template” section for more info about creating new variants.


Documentation generation target options

In the project edition box, the “Documentation” tab enables you to specify options for the documentation targets. To generate documentation, doxygen is used, and so these options are mapped to doxygen options.


The “Documentation” tab in the project edition window

In the left-hand part of the box, all documentation targets associated with the current project are shown. You can create a new target using the “Create documentation target” command, and delete a target using the “Delete target” command. The tickbox in front of each target allows the deactivation of this specific target. It will then be ignored when generating documentation from the project.

When a target is selected, the right part becomes active with its data, and you can specify the following options:


Build target options

In the project edition box, the “Build” tab enables you to specify options for the build targets. The build process uses makefiles, and so most of the options concern them.


The “Build” tab in the project edition window

In the left-hand part of the box, all build targets associated with the current project are shown. You can create a new target using the “Create build target” command, and delete a target using the  "Delete target" command. The tickbox in front of each target allows you to deactivate this specific target. It will then be ignored when building a project.

When a target is selected, the right part becomes active with its data, and you can specify the following options:


Introducing projects and targets

Modelio C++ Designer solution supports the management of build projects and targets.

A target defines a build rule (code generation, documentation generation or compilation) for part of a UML model. A target stores build options, such as the output path or default type library for C++ code generation.

A build project defines a set of build rules, which are expressed by generation, documentation, and compilation targets, for the whole UML model or a part of the model, which we say is manifested by the project. The key principle is that project targets process only the manifested part of the model.

A project can be associated with several targets of the same type, meaning that you can easily run code generation and compilation of the same model part for several target compilers, or generate debug and release code in different directories.

The UML model can be associated with several build projects, which can manifest intersecting model parts.  This lets you generate code, produce documentation and compile only those parts of the model which are necessary.

Build projects and targets are represented at UML model level through UML artefacts, allowing them to be handled directly in the same way as standard UML model elements.

Through the build project and target management feature, the application development process can be controlled directly from UML level, making the UML modeling environment a more solid basis for C++ application development.


Manifesting project content

To manifest the UML model elements to be processed by the project targets, simply edit a project and drag and drop the desired model elements from the Modelio model explorer into the “Project Contents” tab.

Only UML packages and classes can be manifested. Modelio C++ Designer creates manifestation links from the project artifacts to the dropped elements. As a result, the dropped elements will be processed by the C++ code generation, documentation and compilation targets associated with the project.

For example, we want to work separately with the Windows GUI part of our task management application.  We want its code and documentation to be generated in a separate directory hierarchy, and we want to obtain code for it without generating the rest of the model. For this, we create the “Windows GUI” project, edit it, and drag and drop the “Windows” package into the “Project Contents” tab.


Manifesting the “Windows” package

You can un-manifest a model element from the project by selecting it in the “Project Contents” tree and clicking on the  "Remove from project" icon.


Project options

The “Project” tab of the project edition box is where you can enter the project name, workspace, subdirectory and description.


Creating a project

You can specify the following options:


Automatic decoration

The automatic decoration flag

By default, Modelio C++ Designer automatically deduces C++ decorations for parameters, attributes and association ends. However, in certain cases, deduced decorations may not correspond to what you actually intended. For example, you may want to override an externally defined virtual function, whose prototype does not correspond to that deduced by Modelio C++ Designer.

Modelio C++ Designer lets you mark the model elements to be avoided by the automatic deduction procedure. For this, the “C++” property view contains the “Automatic Decoration” tickbox.


The “Automatic Decoration” tickbox in the “C++” property view for a parameter

By default, the automatic decoration flag is always on.

By switching off the flag, you indicate that the selected element should not be taken into account in the automatic deduction process.  In this case, Modelio C++ Designer only takes in account your decorations, and does not extrapolate new ones. To help you, deduced decorations are saved into the model, so that you can use them as a basis.

By switching on the flag, you indicate that the selected element is to be taken into account during the automatic deduction process.  In this case, any decorations you have previously created are removed, and Modelio C++ Designer deduces new decorations at generation according to the rules defined.

Note: The automatic decoration strategy is also called automatic guessing.
See the corresponding section in the advanced part of this guide for more information.

Note 2: Editing C++ properties in the corresponding edition box sets the automatic decoration to off.

Automatic decoration of structural features

Structural features are attributes and associations between UML classes. Many existing C++ generators translate these as C pointers. However, C pointers are a poor choice to represent the semantics of relationships between model elements. Consequently, you have to implement this at code level and the model then diverges from code, or else you are distracted by low-level details, such as collection types for multiple attributes, storage by pointer or by value, and so on.

Modelio C++ Designer lets you focus on the high-level properties of application entity relationships and attributes. It automatically deduces C++ decorations, which specify collection and storage type, by analyzing the high- level properties of structural features (multiplicity, uniqueness, ordering, and qualifying attributes). These properties are often used to represent semantics on UML models.

We are now going to continue by creating a more detailed model of our

application prototype.


A more detailed model of our application prototype

The “Management” association links a “Person” to a “SimpleProject”. One manager can drive several projects, and there is only one manager for each project, so multiplicity is set to “1” and “*”.  A manager can drive a project only once, and THE order of projects is not important, and we therefore specify uniqueness and no ordering for the “drivenProject” association end. For rapid access to a driven project, we qualify projects by project names, which are used as project keys.

By analyzing these properties, Modelio C++ Designer deduces that the “manager” association end is represented by simple pointer, and that the “drivenProject” association end is represented by “UnorderedMap”. Unordered maps are naturally represented by hash map collections, so Modelio C++ Designer automatically creates the respective declarations.


The model deduced by Modelio C++ Designer

In our example, an STL-type library is chosen by default.  Consequently, Modelio C++ Designer produces the following definition of the “Person” class.

 1    class Person
 2    {
 3         //...
 4    public:
 5         std::string FirstName;
 6         std::string LastName;
 7         std::string Email;
 8    //associations
 9
10    private:
11         std::hash_map<std::string,SimpleProject> drivenProject;
12
13    //operations
14
15    public:
16         Person();
17         Person(const Person& value);
18         Person& operator =(const Person& value);
19         ~Person();
20
21    //non-modeled members
22    };

Automatic decoration of operation parameters

Since C++ does not provide automatic memory management capabilities, you as a C++ user have to pay particular attention to the method you use to pass operation parameters, in order to avoid producing inefficient or incorrect code. For example, if a class parameter is passed by value, a copy constructor will be called, and the operation code will modify the copy, not the object itself, and so on.

Modelio C++ Designer lets you focus on high-level UML model properties without being distracted by low-level details, such as passing operation parameters by reference or by value or const qualifiers for “in” parameters.

Modelio C++ Designer analyzes a parameter’s type and sets the “by reference” passing modes for class or datatype parameters, as well as for parameters of non-primitive types defined in type libraries. In C++, this mode is implemented by adding a reference specifier to the parameter type.  Modelio C++ Designer adds const specifiers to “in” parameters in order to explicitly express the fact that these parameters cannot be changed by the operation body, and const specifiers to “in” operations in order to explicitly express the fact that these operations do not change object state.

Consider our application prototype model. Continue by creating the “addSubTask” operation in the “Task” class operation, which takes a subtask to add and its number in the task work breakdown structure.

Before generation, Modelio C++ Designer automatically creates C++ decorations for its parameters. It adds a reference specifier to the type of the “SubTask” parameter, since this type is a class.  It does not add a const specifier to this parameter, because it has “inout” semantics and can therefore be changed by the operation. It does not create a const specifier for the “wbsNum” parameter, because it is of primitive type. The integer type is translated to the C++ int type, which is passed by value, so there is no point in qualifying the “wbsNum” parameter as a const.


The “SubTask” parameter on the “addSubTask” operation

Modelio C++ Designer produces the following declaration of the “addSubTask” operation.

 1    class Task
 2    {
 3    //...
 4    public:
 5         std::string name;
 6         std::string wbsCode;
 7
 8    //associations
 9
10    protected:
11         SimpleProject* project;
12         std::set<Task> subTask;
13         Task* owner;
14         std::list<HumanResource> resource;
15
16    //operations
17
18    public:
19         Task();
20         Task(const Task& value);
21         Task& operator =(const Task& value);
22         ~Task();
23         bool addSubTask(int wbsNum, Task& SubTask);
24
25    //non-modeled members
26
27    };

Creating C++/CLI elements

Defining attributes

CLI attributes are defined through the C++ property view of a Class, by choosing the “CLI Attribute” value in the “Class kind” field.


CLI attribute property view

This view defines all options available on the CLI Attribute definition.

Defining indexers

Indexers are modeled through a UML class with two operations, “get” and “set”, to which the <<CLI Indexer>> stereotype is added.

A class stereotyped <<CLI Indexer>> will not be generated. It will simply be used to generate C# indexer get and set signatures and bodies.

To create an indexer, simply use the creation command from the contextual menu on a class, as shown below.


The “Create CLI Indexer” command

The following is a description of indexer accessors:

Defining events and delegates

CLI events are modeled throught a UML signal to which the <<CLI Event>> stereotype is added. This signal must be a part of a class. Once a signal is stereotyped as an event, you can manage new values such as visibility (using the C++ property view) and delegate association (using Signal UML properties tab’s base field). An event must refer to a model’s delegate.

To create a CLI event, simply use the creation command from the contextual menu on a class, as shown below.


The “Create CLI Event” command

Delegates can be operations issued from delegate containers (classes stereotyped <<CLI Delegate Container>>) or delegates (operations stereotyped <<CLI Delegate>>). The related reference can be created through a drag and drop operation.

Delegate containers (classes stereotyped <<CLI Delegate Container>>) are used as containers of C# delegate types (operations stereotyped <<CLI Delegate>>). The generated delegates belong to the current parent element.

Making an operation <<CLI Delegate>> through the C++ property page will enable delegate signature and skip generation of all code notes attached to the operation.

Defining properties

CLI properties are modeled throught a UML attribute or association end, to which the <<CLI Property>> stereotype is added.

To obtain the property declaration with simplified syntax, you must not define any associated code notes (“CLI Getter Code”/“CLI Setter Code”), as if you do, a normal property will be generated.

The generator will automatically generate the get or set accessors according to which access mode has been selected.


Example of an integer property


Editing C++ code

The user can view C++ code generated for a selected model element by using the  "Edit header" and  "Edit body" buttons in the “C++” property view.


The “Edit header” and “Edit body” buttons in the “C++” property view

Let’s use these buttons to view the code generated for our “SimpleProject” class. We can see C++ constructors, operators and destructors generated from the model-level Coplien pattern, as well as “TODO” notes.

First of all, click on the  "Edit header" button to view the header file code generated for the “SimpleProject” class.


Code editor on the header file

Next, click on the  "Edit body" button to view the body file code generated for the “SimpleProject” class.


Code editor on the body file

The //begin of modifiable zone.... type of comment provides the markup used to ensure model/code consistency. You can enter your code between markups, and this code is then transferred back into the model to the respective C++ code notes when the editor is saved. The code is read only outside the marked zone, preventing unwanted modifications in the model.

Note: We recommend that the “Edit header” and “Edit body” buttons be used to enter implementation code, and that the code preview function be used to examine how UML model elements and their C++ properties (entered manually or deduced automatically) are translated to C++ code.


Getting started

Model level creation operations

The first step in this tour is to create the model shown in figure below, by first creating the “My planner” package inside the root package, and then the “Task management” package inside the “My planner” package.


The model you are going to build

We are now going to continue by designating the main entities of our application (Project, Task, Human Resource and Person), and the relationships between these entities.

Let’s create a class to represent, for instance, projects.  For this, create the “Project” class in the “Task Management” package.


Creating the “Project” class in the “Task management” package

Steps:

C++ does not provide automatic memory management and garbage collecting features, and its syntax does not permit the initialization of class members in declaration points. In most cases, you have to manually specify the creation and destruction semantics of your classes by writing constructors, destructors, and so on.

In order to avoid you forgetting creation operations for your objects, and to explicitly represent creation semantics at model level, Modelio C++ Designer automatically constructs UML creation operations when a class is created in the model.  Modelio C++ Designer follows best C++ practices and uses a design pattern to create the so-called “Coplien form”:


Automatically constructed creation operations

For each operation, Modelio C++ Designer automatically creates C++ notes with “TODO” comments, suggesting that you provide their C++ implementation.

This model level pattern is dynamic, meaning that when you rename a UML class, its creation operations are renamed automatically.


The names of the creation operations are automatically modified when the class name is modified

First C++ generation

To generate C++ code from the application model, select the element to generate and click on the  "Smart generate" button in the C++ property view.


Launching C++ code generation using the button in the property view

If you have not created your own build project, Modelio C++ Designer automatically creates a default build project.

The default build project manifests the whole model, meaning that all model elements (except those marked by the “No Code” flag) are translated.

Its C++ code generation target uses the type library, compilation platform, output directories, header and body file extensions specified by Modelio C++ Designer parameters.

Its doxygen documentation target uses doxygen options and output directories specified by Modelio C++ Designer parameters.

Its compilation target uses makefile and compiler options specified by Modelio C++ Designer parameters.

Note: Default C++ code, documentation generation and compilation options must be defined using Modelio C++ Designer parameters, before using it for the first time.


Model level accessors

The methods used to access the attributes of application classes constitute an important part of model semantics. However, these accessors are traditionally produced only at code level, with the result that the model differs from the code.

Modelio C++ Designer is the first solution to support the automatic creation of model-level accessors for structural features.

To create accessor operations for an attribute or association end, simply select the element in question and change its access mode from the UML property or the C++ Designer view.


Creating accessors from the C++ Designer view

Modelio C++ Designer implements accessors through design patterns. The current accessor pattern creates the “get” accessor operation if the feature has a “read” access flag (which corresponds to get access), and the “set” accessor operation if the feature has a “write” access flag (which corresponds to set access).

For a single cardinality primitive-type attribute, the get operation returns the attribute and the set operation sets its value. For an association end with single cardinality or a complex-type attribute, the get operation returns the reference to the target class and the set operation sets the feature value from a given const reference.  For implemented collections with multiple cardinality features, get and set accessors are implemented by a single operation that returns the reference to the collection instance, which is a const if the “write” (set) access mode is not specified.

As an example, let’s run the “Create accessors” command on the “subtask” association end in the “Task” class, which has “*” multiplicity and read-only access semantics expressed by only the “read” (get) access mode. Modelio C++ Designer will then create the UML operation “getSubTask” in the “Task” class.


The result of running the “Create accessors” command on the “subtask” association end in the “Task” class

Modelio C++ Designer copies the C++ decorations (that were automatically deduced for the “subtask” association end from its uniqueness and ordering properties) to the return type of the created accessor, additionally decorating it with the const specifier to represent read-only semantics. Modelio C++ Designer also creates the C++ code note, which implements default accessor implementation.

Modelio C++ Designer produces the following code for the “Task” class, which implements get access to the “subTask” member.

 1    class Task
 2    {
 3    //...
 4        public:
 5            std::string name;
 6            std::string wbsCode;
 7
 8        //associations
 9
10        protected:
11            SimpleProject* project;
12            std::set<Task> subTask;
13            Task* owner;
14            std::list<HumanResource> resource;
15
16        //operations
17
18        public:
19            Task();
20            Task(const Task& value);
21            Task& operator =(const Task& value);
22            ~Task();
23            bool addSubTask(int wbsNum, Task& SubTask);
24            const std::set<Task>& getSubTask() const;
25
26        //non-modeled members
27    };
28
29    const std::set<Task>& Task::getSubTask() const
30    {
31        //modifiable zone @12953@30671900:493@T
32        return subTask;
33        //modifiable zone @12953@30671900:493@E
34    }

Model-level accessor management is dynamic, meaning that when an attribute is updated, its accessors are automatically updated too. If you rename an element, its accessors are automatically renamed. If you change an element’s access mode, the respective accessors are automatically created or deleted, and the const specifiers of collection accessors are automatically created or removed.

Generation of accessors directly at UML model level and their automatic synchronization with accessed elements is used to conveniently express access semantics at a high level, thereby creating a closer link between the application model and the code, starting from the prototyping stage.


Smart generation

Introducing smart generation

Modelio C++ Designer provides two different generation options:

Forced generation runs a complete generation of the selected element (a class, a package or an entire project).  In this case, all elements are generated.

To force the generation of C++ code, simply select the element you want to generate and then click on the  button in the “C++” property view.  C++ code is then generated for the selected element and its contents.

Smart generation accelerates the generation process.  When the smart generation option is used, Modelio C++ Designer looks at last modification dates and only generates elements that have been modified since the last generation operation, avoiding useless generation and speeding up the generation process.

To smart-generate C++ code, simply select the element you want to generate and then click on the  button in the “C++” property view. C++ code is then generated for any elements (the selected element or any of its sub-elements) that have been modified since the last generation operation.


Equivalence between C++ source code and the UML model

Basic types

C++ element UML element Tagged Values
Bool boolean
Char char
Int int
Long long
Signed Int
Short short
Unsigned int {unsigned}
Unsigned short int {short} {unsigned}
Unsigned char byte
Float float
Double double
Void* undefined
Qualifier volatile {volatile}
Qualifier const {const}
Qualifier mutable {mutable}

Qualifiers

C++ element UML element Tagged Values
Class Class
Enumeration Enumerated type
Enumeration elements Enumeration Literal
Structure Primitive class {struct}
Union Primitive class {union}

Namespaces

C++ element UML element
Namespace definition Package
Namespace alias Reference on a package
Namespace use (using) Use link on the class associated with the file
Namespace element use Textual note on the class associated with the file

Inheritance

C++ element UML element Tagged Values
Inheritance Generalization {private}
Public inheritance Generalization
Protected inheritance Generalization {protected}
Private inheritance Generalization {private}
Virtual inheritance Generalization {virtual}

Class member attributes

C++ element UML element Tagged Values Multiplicity
Simple type Attribute 1
Primitive class Attribute 1
Defined or enumerated type member Attribute 1
Non primitive class Association role
Composition
1
Pointer on char String type attribute 1
Pointer on simple type Attribute {*} 0..1
Primitive class pointer Attribute {*} 0..1
Defined or enumerated type pointer Attribute {*} 0..1
Non primitive class pointer Association role *
Reference on simple type Attribute {&} 1
Primitive class reference Attribute {&} 1
Defined or enumerated type reference Attribute {&} 1
Non primitive class reference Association role 1
Function pointer Attribute with a C++TypeExpr note 1
Member pointer Attribute with a C++TypeExpr note 1
Attribute member of table [n] of simple type Attribute multiplicity n
Attribute member of table [n] of primitive class Attribute multiplicity n
Attribute member of table [n] of enumerated or defined type Attribute multiplicity n
Attribute member of table [n] of non primitive class Association role multiplicity n

Member functions

C++ element UML element Tagged Values
Member function Operation
Virtual member function Operation {virtual}
Pure virtual member function Abstract operation
Inline member function Operation {inline}
Constructor <<create>> operation
Destructor <<destroy>> operation
Static member function Class operation
Const member function Operation whose passing mode is in

Function parameters

C++ element UML element Tagged Values
Parameter by value In/out parameter
Parameter by reference In/out parameter {&}
Const parameter by reference In parameter {&}
Pointer parameter In/out parameter {*}
Char* parameter String type in/out parameter
Ellipsis Not translated
Parameter default value Default value

Function return parameters

C++ element UML element Tagged Values
Void No return parameter
No return indicated "int" type return parameter
Return by value Corresponding type return parameter
Return by reference Corresponding type return parameter {&}
Return by pointer Corresponding type return parameter {*}

Declarations and definitions of variables not linked to a class

C++ element UML element Tagged Values
Declaration of global variable Class attribute
Declaration of external variable Class attribute {extern}
Declaration of global variable Class attribute
Declaration of static variable Private class attribute

Declarations and definitions of functions not linked to a class

C++ element UML element
Non static global function Class operation

Friendship declarations

C++ element UML element
Friend function declaration No translation
Friend class declaration No translation

Templates

C++ elements UML elements Tagged Values
Template class Class + template parameter
Template operation Operation + template parameter
Template static instantiation Typedef
Template dynamic instantiation Type of an attribute or operation parameter

Other constructors

C++ UML Defined on
#include C++BodyHeader or C++InterfaceHeader note Classes associated with the file
#define No translation
Compilation directives No translation
Directory structuring Package

Overview of C++ Reverse

Introduction

Reversing an application or a part of an application is the operation that consists of creating a project that represents the application.

However, the reverse operation is not defined or scarcely defined for certain code constructions, either because they are not directly in tune with the UML norm, because they are truly specific to C++ or simply because they are not recommended for an object-oriented approach.  This introduces some restrictions in the reverse tool’s ability to retrieve some parts of the code in the project.

The Modelio C++ Reverser reverse function is used to build a UML model from C++ source code. This UML model creation based on C++ code is carried out over several stages.  Each of these stages will be presented and explained in this chapter.

The C++ code is transformed into a UML model annotated by a set of notes and tagged values from C++ Designer.  Modelio uses specific modeling techniques for this model annotation.  For information on equivalents, see “Equivalence between C++ source code and the UML model”.

Modelio C++ Reverser is a specific module that depends on the C++ Designer module and that must be deployed before performing any reverse operation.

C++ Reverse functioning

The C++ Reverse functions over two stages:


Diagram of C++ Reverse functioning

Warning

A class reversed into a project receives an identifier just like an object created in the Modelio browser or graphic editor.

If two users reverse the same class into two different projecting projects, Modelio will consider them as two different objects.

To avoid losing the links towards the reversed classes during the import, it is necessary to run the reverse in a reference modeling project from which each user imports the used classes.


Reverse modes

Introduction to reverse modes

The Modelio C++ Reverser reverse tool provides three reverse modes, each of which corresponds to a specific result in the produced project.

The “Simple structure” reverse mode

The “Simple structure” reverse mode is used to reverse only the packages and classes of the application.

This level makes it possible to use the reversed classes so as to:

This reverse mode is the fastest.

The “Complete structure” reverse mode

The “Complete structure” reverse mode makes it possible to reverse not only the same elements as the “Simple structure” mode, but also all the attributes, operations and associations of the reversed classes.  However, operation contents and initializations (and code) are not reversed.

Reversed classes provide the same possibilities as with the “Simple structure” mode, but in this mode, it is also possible to:

The “Complete” reverse mode

The “Complete” reverse mode is used to reverse the application completely, including operation source code and attribute initialization.

This reverse mode creates a project from an application developed outside Modelio C++ Reverser, and allows you to continue its development within Modelio UML Modeler, thereby taking advantage of Modelio C++ Reverser generation.

Reversing comments

For all three reverse modes, if there exist comments describing the application’s elements, these are also reversed.

For example, a comment on a class will be reversed into the project from “Simple structure” level upwards, whereas operation comments will only be reversed when the “Complete” reverse mode is used.

The following table details the elements reversed into the project at each level.

Simple structure Complete structure Complete
Packages X X X
Classes X X X
Comments X X X
Attributes X X
Attribute comments X X
Attribute initializations X
Associations X X
Association comments X X
Association initializations X
Operations X X
Operation comments X X
Operation code X

Note: “X” indicates that the element is retrieved during the reverse operation.


Running reverse operations

Launching the Reverse command

The first step in the C++ reverse procedure is to select the model root and run the actual reverse command from the context menu.


Launching the “Reverse C++ application” command

The “C++ Reverse” window

After running the “Reverse C++ application” command, the “C++ Reverse” window then appears.  This window is used to:

Selecting the files to be reversed

The first window to appear when the “Reverse application” command is launched is used to select the files you wish to reverse.

This window contains three zones:


Selecting directories to be reversed

Steps:

  1. In the top zone, indicate the directory you want to reverse from.
    The “content” zone refreshes automatically to display the files in this directory.
  2. Change the body or header extensions if they don’t match those from your project to reverse. Select “cpp” files to reverse a complete application.
    “.h” is sufficient to carry out a structural reverse of a library.
  3. Check the files or directory to be reversed.
  4. Click on “Next” to continue.

Defining the includes

The second “C++ Reverse” window, which appears after you click on “Next” in the first window, is used to select any files or directories inside which you want to search for included files.  These files will not be reversed.

This window contains two zones:


Selecting external include files and directories

Steps:

  1. Click on the add directory button.
  2. In the directory chooser, select the directory to include, for example the include path from Visual Studio.
  3. Press OK.
  4. Click on the “Next” button to continue.

Defining reverse options

The third and final “C++ Reverse” window, which appears after you click on “Next” in the second window, is used to define the various options used during reverse operations.

This window contains two zones:


Defining reverse options

Steps:

  1. Select a granularity from those available in the dropdown list.
  2. Define any macros you wish to use.
  3. Click on “Reverse” to start the reverse.

Reverse reports

After the reverse operation has been completed, a window named “Report of the reverse” appears. This window provides you with information on the reverse operation, as well as indicating any errors which were encountered.


Tips for efficient C++ reversing

Introduction

C++ is a rich and complex language. Although it has been standardized by the ISO, its syntax and grammar remain very flexible, thereby allowing several different styles and variants in the code. Of course, these characteristics make it more complex to write C++ parsers and C++ reverse, with perfect parser reliability remaining a virtually impossible-to-reach goal. Even well-known C++ compilers introduce specificities and limitations of their own.This is also true for the Modelio C++ Reverser reverse tool.

Furthermore, the problem of reversing code to produce an equivalent UML model can encounter an additional difficulty, since C++ supports certain constructions that cannot easily be mapped to UML syntax, due to a lack of direct equivalence in UML.

To make the most of the Modelio C++ Reverser reverse tool, it is worth following some best practice tips. The following ten tips should help you improve the quality of your reversed model. Experience has proved that by taking these small precautions, you can reap significant benefits in the reversed model.

Divide your sources

Reverse operations can be very time-consuming. Due to system resources, it can be a good idea to divide application sources into separate subsystems, before reversing them one by one.

Between every reverse, save the project. This will force the use of the Modelio garbage collector, thus freeing up memory, which can improve reverse speed.

Last but not least, reversing smaller parts greatly facilitates the diagnosis of potential problems.

Respect dependencies between subsystems

When reversing a large application subsystem by subsystem (as described in the previous paragraph), dependencies between the different subsystems must be respected. In the subsystem dependency graph, subsystems that depend on no other subsystems should be reversed first, followed by subsystems depending only on them and so on. This process minimizes the number of partially instantiated objects, and reduces the risk of post-reverse object re- identification.

Look into your makefile to find specific options

In most applications, several parameters, mainly macro definitions and include paths, are passed to the compiler. These options have an influence on the code that is truly compiled.

This “on the fly code transformation” is carried out by the C preprocessor. The Modelio C++ Reverser reverse tool can manage these options in the same way as a preprocessor, which means that passing the right parameters is a key to success.  A good and pragmatic approach is to examine the options used when the application is compiled, for example, by looking at the makefile (or equivalent build file).

Reverse libraries and implementations differently

Reversing a complete application and reversing a compiled library are two different things.

In the case of reversing an application, the most important files are usually implementation files (*.cpp) . All the necessary header files are included in the implementation files, and only the implementation files themselves have to be selected in the “C++ Reverse” window.

For the reverse of a tier library, only header files should be selected. This will provide a structural UML model without C++ implementation notes that should be sufficient. Furthermore, in the case of tier libraries, implementation files are most often unavailable.

Use empty macros for specific keywords not implemented

Some compilers use specific keywords.  For example, Microsoft Visual C++ defines additional keywords such as “cdecl” or “stdcall”.  These additional keywords are not known by the Modelio C++ Reverser reverse tool parser, as it conforms to the ANSI norm and not to the Microsoft variant.

In this situation, the best thing to do is to ignore these useless keywords, by providing them as an empty macro using the configuration interface.

Use exclusions to limit model size

A complete model can be very large, but a complete model is not always needed! Using reverse options, the reverse can be limited to only the core of your application, without including, for example, technical libraries. This means you can concentrate only on the business part of the model. Identifying and defining the parts of the application that are not to be reversed (in the second window of the reverse wizard) greatly helps keep the model within manageable limits in terms of its size.

Save extensions in extension files to re-use them

The C++ reverse tool provides a set of extensions for some XML file compilers. Where several applications use the same specific extensions, it is recommended that these extensions be added to the configuration file for re-use.

The more standard the code, the better the reverse

The best reverse is achieved from the most standard code. The Modelio C++ Reverser reverse tool has been carefully designed to make the best use of the STL library. The use of STL containers gives the reverse tool the ability to rebuild correct associations.Non-standard constructs, although accepted by your compiler, can fool the Modelio C++ Reverser reverse tool parser and lead to poor results.

Work on your code again, in order to better reverse it

Sometimes simple modifications in the application code can significantly improve the quality of the model. For example, replacing a typedef by its expansion in its uses, or rewriting the declaration of an association can lead to a considerable enhancement of the model.

Where parsing errors occur, concentrate on the first error

The C++ language has state-full and irregular grammar. This means that a notion of state exists in every statement in a file. When the parser finds an error, it can be confused about the current state and report false errors. Thus, in the list of errors, always look at the first one and correct it, since subsequent errors can, in fact, be false negatives.


UML restrictions

Restriction on C++ code

During code analysis by C++ Reverser, errors are detected. These errors cause the analysis to fail, which means that no structure is visible in the “Show hierarchy” dialog box. You must therefore always make sure that the C++ code to reverse is compilable.

Restriction on comments

Comments for classes are contained in notes called “summary” and comments for attributes and operations are contained in notes called “description”.

Restriction on namespaces

C++ element UML element Remarks
Namespace alias Reference on a package Not handled
Namespace use (using) Use link on the class associated with the file Not handled
Namespace element use Textual note on the class associated with the file Not handled

Restriction on function parameters

C++ element UML element Remarks
Parameter default value Default value Not handled

Restriction on other constructions

Source element UML element Defined on Remarks
#include Use link Classes associated with the file Translated by a C++BodyHeader or C++InterfaceHeader note
Directory structuring Package Not handled

Building your application

To build your application using the Modelio build system, you need Cygwin to use Make and GCC in order to compute dependencies.

Modelio C++ Designer provides the propagation system, which can generate a makefile with elements that are used by the application. If the compilation artifact manifests a class or a set of classes, only elements directly used by these classes will be compiled. For example, if you manifest the main class, all necessary classes will be compiled by propagation. This system is useful when you are producing several executables from one set of source files, with each executable using a subset of these sources.


The property view when a Makefile is selected

To generate a makefile, select the makefile target in the “DeploymentData” package, and launch the  "Generate Makefile" command in the C++ Designer property view.

To build the application, launch the  "Build" command. This will build the application using the generated makefile. Dependency files are created first to minimize future buildings, making the compiler rebuild the minimum set of cxx files.

Note: If you need to use a specific library, you need the corresponding model component. You can import the model component into your project and then create a usage link between your compilation artifact and the compilation artifact of the provided library.


Creating an operation redefinition

Redefining a standard operator

In C++, you can redefine standard operators, and for this, Modelio C++ Designer lets you declare this construct. Coplien form defined on a newly created class contains such an example.

<<Cxx.Operator>> operator =(in value : OperatorRedefinition):OperationRedefinition

To redefine a standard equality operator, the following steps should be carried out:

Creating a cast operator

C++ also authorizes the creation of cast operators, to allow implicit conversion between types.

To define a cast operator, carry out the following steps:

The generated code will be as follows:

operator bool();

Editing the C++ properties of UML models

Introduction

The C++ properties of UML model elements can be edited through the “C++” property view and through C++ edition dialog boxes. The C++ edition dialog box for a selected model element can be accessed by pressing the  "Edit properties" button.


The “Edit properties” button in the “C++” property view

Structure of C++ edition dialog boxes

C++ edition dialog boxes vary according to the model element selected. The C++ edition dialog box for a given element presents its C++ properties, grouped into different categories:

The next figure shows the C++ edition dialog box for a package.


The C++ edition dialog box for a package


Entering implementation code

Introduction

To implement an application, application behaviour has to be described and implemented by attaching C++ code notes to UML operations.

Entering operations code

Modelio C++ Designer conveniently lets you input ?++ code for UML operations directly in the operation edition dialog box. You simply enter your C++ code in the “Note Content” field of the “Operation Code” tab of the operation edition box. Modelio C++ Designer injects code entered in this field into the operation definition and generates the markers required to retrieve the code back into the model, if it is modified in the external editor.

As an example, we want to implement the assignment operator for the “Task” class in our application. For this, we open the C++ edition dialog box for the respective UML operation and input the operator code in the “Code” field.


Inputting the operator code

The entered code is injected into the definition of the assignment operator in the body of the “Task” class.

The “Return expression” field is used to input a return expression, which is always generated for the function independently of the function code. In our example, the standard return expression for assignment operators is input here. This note is generated automatically by the model-level creation operation pattern.

The “Base Constructor Code” field is used to input base construction clauses. Modelio C++ Designer automatically activates this field if the operation is detected as being a constructor (as a result of its name matching the owner class name or of the attached <<create>> stereotype).

Here is the generated code for this class:

 1//class header file
 2#include "MyPlanner/TaskManagement/Task.h"
 3
 4namespace MyPlanner
 5{
 6    namespace TaskManagement
 7    {
 8        Task::Task()
 9        {
10            //modifiable zone @12366@30671900:196@T
11
12            //modifiable zone @12366@30671900:196@E
13        }
14
15        Task::Task(const Task& value)
16        {
17            //modifiable zone @12378@30671900:208@T
18            //TODO: write copy constructor code
19
20            //modifiable zone @12378@30671900:208@E
21        }
22
23        Task& Task::operator =(const Task& value)
24        {
25            //modifiable zone @12396@30671900:226@T
26            std::copy(value.getSubTask().begin(), value.getSubTask().end(), std::inserter(this.subTask, this.subTask.begin()));
27            std::copy(value.getResource().begin(), value.getResource().end(),   std::inserter(this.resource, this.resource.begin()));
28            this.owner = value.getOwner();
29            this.name = value.getName();
30            this.wbsCode = value.getWbsCode();
31            //modifiable zone @12396@30671900:226@E
32
33            //modifiable zone @12397@30671900:227@T
34            return *this;
35            //modifiable zone @12397@30671900:227@E
36        }
37        //...
38    }
39}

Entering class code and non-modeled class members

Modelio C++ Designer lets you input ?++ code to be injected into the class header and body files directly in the class C++ edition dialog box. This can be useful to initialize global variables and implement utility functions used by the class and class members, which are not relevant to the model but which need to be provided.

To enter class-level C++ code, you simply enter it in the “Code” tab of the class C++ edition dialog box.


The “Code” tab of the C++ edition dialog box for the “TaskWindows” class

The “Placement” hierarchy defines where the input code will be injected:

Therefore, to input C++ code in the intended position in the class header or body file, you simply select the respective node in the “Areas” hierarchy and then type the code in the “C++” field.

For example, we want to inject the standard MFC macro “DECLARE_MESSAGE_MAP” into the header of the “TaskWindow” class, because this class represents the specific window (and is therefore inherited from the “CWnd” class) and should intercept window messages. The macro should be injected as a protected “member” of the class.

We open the “Code” tab of the class C++ edition dialog box, select the “Header –> Class [Class Members] –> Protected” node of the “Placement” hierarchy and type the intended code.

Modelio C++ Designer produces the following code for the “TaskWindow” class. The code entered for the “Header –> Class [Class Members] –> Protected” node of the “Placement” tree is injected into the protected part of the class.

 1//includes for used library types
 2
 3#include <cstringt.h>
 4#include <afxwin.h>
 5#include <afxtempl.h>
 6#include <afxcoll.h>
 7
 8//automatic includes (friends, associated classes, etc)
 9#include "MyPlanner/GUI/Windows/CWnd.h"
10#include "MyPlanner/GUI/ITaskView.h"
11#include "MyPlanner/TaskManagement/Task.h"
12
13namespace MyPlanner
14{
15    namespace GUI
16    {
17        namespace Windows
18        {
19            class TaskWindow : public CWnd, public GUI::ITaskView
20            {
21            //...
22            private:
23                CString displayTitle;
24
25            public:
26                CDC dc;
27
28            //associations
29
30            public:
31                TaskManagement::Task* task;
32                CMap<CString,CString&,CBrush,CBrush&> brushResource;
33
34            //operations
35
36            public:
37                TaskWindow();
38                TaskWindow(const TaskWindow& value);
39                TaskWindow& operator =(const TaskWindow& value);
40                ~TaskWindow();
41                void formatDisplayTitle(std::string& FormatStr);
42                CDC getDc();
43                afx_msg int OnCreate(CREATESTRUCT* lpCreateStruct);
44                const CArray<CDC,const CDC&>& getAttr1() const;
45
46            //non-modeled members
47
48            protected:
49
50            //modifiable zone @16224@30671900:2404@T
51                DECLARE_MESSAGE_MAP()
52            //modifiable zone @16224@30671900:2404@E
53            };
54        }
55    }
56}

Editing code in Modelio

The  "Edit header" and  "Edit body" buttons are available for packages, classes, interfaces and operations.

For operations, the “Edit header” button opens the header of the owner class, and the “Edit body” button opens the body file of the owner file.

To edit C++ code in an editor, you simply select a model element and click on the  "Edit header" or  "Edit body" buttons in the “C++” property view.

The editor containing the header or the body file contents is then opened. You can write implementation code in the editor, between markers. Save the editor to transfer the input code back into the model.

Note: You may prefer to input implementation code in an external editor that you can specify via the “External editor” Modelio C++ Designer settings. The model is then updated when you close this editor.

Updating externally modified code

You can modify the application code outside the Modelio environment, for example, by editing it in your favorite IDE. Modelio C++ Designer lets you update the code notes belonging to model elements from externally modified code.

To update the code notes attached to a model element, just click on the  "Update" button in the “C++” property view.

Modelio C++ Designer reads the file (where the element’s code “lives”) and transfers the code between markers back into the respective notes.

Note: Only the code entered between markers generated by Modelio C++ Designer can be transferred back into the model. Any code input outside these markers is ignored!


Generating namespaces and directories

By default, Modelio C++ Designer translates each UML package into a C++ namespace and generates a directory such that the hierarchy of namespaces and directories corresponds to the package hierarchy. However, it may be unnecessary at generated code level to have the granularity introduced at model level. Modelio C++ Designer lets you avoid namespace and/or directory generation for arbitrary chosen packages.

To avoid namespace generation, simply select a UML package and switch off the “Is a namespace” flag in the “C++” property view.


The “Is a namespace” option in the “C++” property view

After the “Is a namespace” option has been switched off, Modelio C++ Designer puts all the classes, interfaces, datatypes, enumerations and sub-packages defined in the package into the namespace of the owner package. If the owner package does not produce a namespace either, these entities are generated in the owner of the owner package, and so on. The root package always corresponds to the global namespace.

For example, let’s imagine we want to put all the classes defined in our application model into the “MyPlanner” namespace, which corresponds to the “MyPlanner” package.  For this, we switch off the “Is a namespace” flag for the “TaskManagement”, “GUI” and “Windows” packages.

As a result, Modelio C++ Designer produces the following code, where all the classes represented in the model are defined in the “MyPlanner” namespace, for example, the “TaskWindow” class.

 1//includes for used library types
 2#include <cstringt.h>
 3#include <afxwin.h>
 4#include <afxtempl.h>
 5#include <afxcoll.h>
 6
 7//automatic includes (friends, associated classes, etc)
 8#include "MyPlanner/GUI/Windows/CWnd.h"
 9#include "MyPlanner/GUI/ITaskView.h"
10#include "MyPlanner/TaskManagement/Task.h"
11
12namespace MyPlanner
13{
14    class TaskWindow : public CWnd, public ITaskView
15    {
16    //...
17    private:
18        CString displayTitle;
19
20    public:
21        CDC dc;
22
23    //associations
24
25    public:
26        Task* task;
27        CMap<CString,CString&,CBrush,CBrush&> brushResource;
28
29    //operations
30
31    public:
32        TaskWindow();
33        TaskWindow(const TaskWindow& value);
34        TaskWindow& operator =(const TaskWindow& value);
35        ~TaskWindow();
36        void formatDisplayTitle(std::string& FormatStr);
37        CDC getDc();
38        afx_msg int OnCreate(CREATESTRUCT* lpCreateStruct);
39
40    //non-modeled members
41
42    protected:
43        //modifiable zone @16224@30671900:2404@T
44        DECLARE_MESSAGE_MAP()
45        //modifiable zone @16224@30671900:2404@E
46    };
47}

To avoid directory generation, simply select a UML package and switch on the “No directory flag” in the “C++” property view. This will result in Modelio C++ Designer putting all the files produced for the package (the header and body files of its classes, interfaces and sub-packages) into the directory of the owner package. If the owner package does not produce a directory, the files are created in the directory of the owner of the owner package, and so on. The root package corresponds to the directory specified in the active generation target output path.

For example, let’s imagine that we want to put all the files generated for our application model into the “MyPlanner” directory, which is produced for the “MyPlanner” package.  To do this, we simply switch on the “No directory” flag for the “TaskManagement”, “GUI” and “Windows” packages.

As a result, Modelio C++ Designer puts all the produced files into the “MyPlanner” directory.


All the produced files have been put into the “MyPlanner” directory


Generating parts and ports

Introduction

Modelio C++ Designer provides a system used to generate C++ code for part and ports. Parts and ports are UML 2 features designed to represent limited connexions in component architecture, as well as their integration through the connection of predefined plugs.


Modeling parts and ports

Modeling a class with connection ports

Some classes can publish or require certain information, declared by an interface. In the example provided in the figure above, the “Camera” class publishes an “iVision” interface as a provided interface. Thus, the camera publishes all this information to this channel. The “Arm” class publishes an “iControl” interface to obtain the information necessary for its use by a normalized channel.

To create a generable port on a class, simply create a port, name it and then specify required or provided interfaces, represented by lollipops. A single port can simultaneously have provided and required interfaces, as in the “Brain” example shown below.

Note: Don’t forget to specify interfaces to type the plug by selecting the lollipop and clicking on the UML properties.

Using generated code in a class with ports

Internally, every port is a class, which is automatically generated and does not appear in the model. The name of this class is normalized through the concatenation of the class name, the port name and the “Port” keyword.

Class Port C++ name of the port
Brain Cmd BrainCmdPort
Camera Vis CameraVisPort
Arm Ctrl ArmCtrlPort

Every operation on the connection point must therefore be carried out using this port. This generated class is the access point to interfaces.

The port class provides access to provided and required interfaces. To retrieve the interface, an accessor is automatically created from “get”, the “Required” or “Provided” keyword and the type of the interface. For example, the “CameraVisPort” class contains an accessor named “getProvidedIVision ()”. Using these accessors, the class does not know the linked element. This system provides important separation of issues.

For example, if the brain takes the information from the vision device through the “Command” port, and in order to call the “move” command via the same port, a method must contain the following code:

 1Void Brain::move () {
 2    // Retrieving the command port
 3    BrainCmdPort *cmdPort = getCmdPort ();
 4
 5    // getting the required plug
 6    IVision vision = cmdPort->getRequiredIVision ();
 7    Data d = vision.getData ();
 8
 9    // getting the provided plug
10    ICommand command = cmdPort->getProvidedIControl ();
11    Command.move (d);
12}

Creating an internal structure for part/port integration

In a part/port model, a class will instanciate all classes for component assembly within its internal structure, and you, the user, just have to connect them. However, these elements must be coherent with the static model. For this reason, Modelio C++ Designer contains a wizard to help you to create this model.

To create an internal structure model, create an integration class. In the internal structure, simply create parts and set their type to instanciated classes. Next, launch the “Complete internal structure model” command. This command will complete the model by creating attributes in the class to refer to instances, by adding ports and provided/required interfaces relative to the static model of these classes, and by keeping the model consistent.

Once all these elements are instanciated, you should simply connect the elements in order to initialize the parts. When the class containing an internal structure is generated, this will automatically lead to generation of the instanciation and connection code. This means that you can concentrate on business code instead of integration code, which is totally generated.


Running the “Complete internal structure model” command

Note: The “Complete internal structure model” command can also update the internal structure model. If you change the static model of a class containing ports, for example by adding a new lollipop, the launch of this command will update those internal structures which use it.


Modeling element usage

Overview

In C++, there are many way to specify the usage of a class. These can be separated into two parts:

When you explicitly link two UML elements, either by typing an attribute or a parameter, or by creating an association, a usage is generated in the source code. Depending of the kind of usage, a forward declaration or an inclusion is generated. Modelio C++ Designer will always prefer forward declaration, in order to limit the dependencies of the generated file.

File inclusion

When you need to explicitly create an include, element imports are used. Element imports are the UML link that provides an element with visibility of another importable element. In the C++ language, this notion is expressed through #include directives.

The visibility of the element import designates the file where the include is to be generated:


Previewing element code

Modelio C++ Designer provides a convenient new feature used to preview the C++ code that will be generated for a selected model element.

The preview field renders the C++ code according to the element properties that are currently set in the dialog box in real time. This means that you can immediately observe the effect of your input on the generated code and consequently avoid errors during the early stages of C++ application development.

For example, let’s edit the properties of a package.  We will first preview the code that will be generated for this element.


Previewing the code that will be generated for a package

Note: The code preview function is implemented by specific code preview templates. These preview templates are consistent with code generation templates, so preview is always consistent with the generated code, even if the generation templates are modified.


C++ Designer settings

Introduction

To open the window in which Modelio C++ Designer settings are defined, run the “Modules” command from the “Configuration” menu.

Modelio C++ Designer provides seven sets of parameters, used to define options in the following areas:

The “General” parameter set


The “General” parameter set

The list of paramters:

The “Automation” parameter set


The “General” parameter set

The list of parameters:

The “External edition” parameter set


The “External edition” parameter set

The list of parameters:

The “Makefile generation” parameter set


* The “Makefile generation” parameter set

The list of parameters:

The “Projects default values” parameter set


The “Projects default values” parameter set

The list of parameters:

The “Doxygen documentation” parameter set


The “Doxygen” parameter set

The list of parameters:

Note: Use Doxygen for Windows, not Doxygen from Cygwin.

The “Model components” parameter set


The “Model components” parameter set

The list of parameters:


Working with external sources

Introduction

When implementing applications, you often need to refer to external sources, such as large external libraries, without explicitly representing them at model level or by type libraries. For example, you may want to re-use external code or plug your applications to an external environment by implementing/overriding external interfaces.

Modelio C++ Designer provides features that let you conveniently use external sources in application UML models.

Using external headers

You can specify the external headers to use in a model class in the “Externals” tab of the C++ edition dialog box for a class.


Specifying external headers in the “Externals” tab of the C++ edition dialog box on a class

Modelio C++ Designer injects the text entered in the “Header includes and using namespaces” field into the header file of the selected class, right after automatically generated include directives. Similarly, the text entered in the “Body includes & using namespaces” field is injected into the body (C++ source) file of the selected class, also after automatically generated include directives. Arbitrary C++ constructions are possible in those fields.

For example, let’s imagine that we want to use our custom logging service in the “TaskWindow” class. We do not want to represent the “MyLogger” class, which implements the service, at model level, because it is not relevant to our application, so instead we write the code in the “Body includes & using namespaces” field of the “TaskWindow” class edition box. We want our code to be injected into the body file to isolate usage of the logging service from other application parts. For this, we are going to enter our code in the “Body includes and using namespaces” field.


Entering our code in the “Body includes and using namespaces” field

The code entered in this text field is injected into the body file of the “TaskWindow” class.

 1#include "MyPlanner/GUI/Windows/TaskWindow.h"
 2
 3//modifiable zone @13927@30671900:980@T
 4#include "MyLog/MyLogger.hpp"
 5
 6#ifdef DEBUG
 7#define MY_LOGGING_LEVEL 9
 8#endif
 9
10using namespace MyLogger;
11//modifiable zone @13927@30671900:980@E
12
13namespace MyPlanner
14{
15    namespace GUI
16    {
17        namespace Windows
18        {
19            TaskWindow::TaskWindow()
20            {
21                //modifiable zone @13351@30671900:701@T
22
23                //modifiable zone @13351@30671900:701@E
24            }
25
26            TaskWindow::TaskWindow(const TaskWindow& value)
27            {
28                //modifiable zone @13363@30671900:713@T
29                //TODO: write copy constructor code
30
31
32                //modifiable zone @13363@30671900:713@E
33            }
34
35            TaskWindow& TaskWindow::operator =(const TaskWindow& value)
36            {
37                //modifiable zone @13381@30671900:731@T
38                //TODO: write assignment operator code
39
40                //modifiable zone @13381@30671900:731@E
41
42                //modifiable zone @13382@30671900:732@T
43                return *this;
44                //modifiable zone @13382@30671900:732@E
45            }
46
47            TaskWindow::~TaskWindow()
48            {
49                //modifiable zone @13388@30671900:738@T
50                //TODO: write destructor code
51
52                //modifiable zone @13388@30671900:738@E
53            }
54
55            void TaskWindow::formatDisplayTitle(std::string FormatStr)
56            {
57                //modifiable zone @13845@30671900:918@T
58
59                //modifiable zone @13845@30671900:918@E
60            }
61        }
62    }
63}

Note: The “Externals” tab page is available only in the class C++ edition dialog box. To use external sources required for model operations or structural features, these must be specified for the owner classes.

Inheriting external classes

You can specify a selected class to be inherited from an external non-modeled class in the “Externals” tab of the class C++ edition dialog box.

Modelio C++ Designer injects the text entered in the “External inheritance” field after the colon token in the selected class definition, thus producing the inheritance declaration. To include headers with the definition(s) of the specified external class(es), the “Header includes & using namespaces” field can be used.

We want the “TaskWindow” class to be a child of the “CWnd” class from the MFC library, which represents a window and provides services for windows management. It is not wise to define this class in the “MFC” type library, because inheritance from a datatype (which would represent the “CWnd” class on the model) does not seem semantically correct.

Therefore, we enter public inheritance declaration and include the external headers with the “CWnd” definition in the respective fields of the “TaskWindow” class C++ edition dialog box.


Entering public inheritance declaration and including external headers

Modelio C++ Designer produces the following code for the “TaskWindow” class. External inheritance declaration and headers are injected. By clicking the “Preview” button in the class C++ edition dialog box, we can obtain this code immediately.

 1//includes for used library types
 2#include <string>
 3#include <cstringt.h>
 4#include <afxwin.h>
 5#include <afxcoll.h>
 6
 7//automatic includes (friends, associated classes, etc)
 8#include "MyPlanner/GUI/ITaskView.h"
 9#include "MyPlanner/TaskManagement/Task.h"
10
11//modifiable zone @13936@30671900:989@T
12#include "afxwin.h"
13//modifiable zone @13936@30671900:989@E
14
15namespace MyPlanner
16{
17    namespace GUI
18    {
19        namespace Windows
20        {
21            class TaskWindow : public CWnd, public GUI::ITaskView
22            {
23            //...
24            private:
25                CString displayTitle;
26
27            public:
28                CDC dc;
29
30            //associations
31
32            public:
33                TaskManagement::Task* task;
34                CMap<CString,CString&,CBrush,CBrush&> brushResource;
35
36            //operations
37
38            public:
39                TaskWindow();
40                TaskWindow(const TaskWindow& value);
41                TaskWindow& operator =(const TaskWindow& value);
42                ~TaskWindow();
43                void formatDisplayTitle(std::string FormatStr);
44
45            //non-modeled members
46
47            };
48        }
49    }
50}

Representing external classes

To explicitly represent relations with external classes, it can be useful to include them in the model. These classes may have quite a complex structure, which ?an make them difficult to reverse or irrelevant to the modeling context.

To represent an external class in the model without specifying its full structure, you can set the “External code” flag in the class C++ edition dialog box. You then specify the code required to use the external class (include directives, macro commands) in the “External headers for external code” field. Instead of translating the modeled class structure, Modelio C++ Designer simply injects the code specified in the field into the class header file.

As a result, you can specify only the relevant parts of external classes. These parts do not need to be specified to exactly correspond to the external class sources.

For example, we want to explicitly model the fact that the “TaskWindow” class is the child of the “CWnd” class from the MFC library. We create the “CWnd” class in the model and create UML operations to explicitly represent certain message handlers that we want to override. We do not define exact message handler signatures, but rather simply show their names in the model.


The newly created “CWnd” class with its operations

To specify the “CWnd” class as being external, we set the “External code” flag and provide the headers required to use the “CWnd” class from the MFC library in the class C++ edition dialog box.


Specifying that the “CWnd” class is external

Modelio C++ Designer produces only the following code for the “CWnd” class (despite the fact that the “OnCreate” and “OnPaint” UML operations are presented in the model).

 1#ifndef __CWnd_15265_H_INCLUDED
 2#define __CWnd_15265_H_INCLUDED
 3/*
 4 * File type:   Class header
 5 * Class: CWnd
 6 */
 7
 8#include "stdafx.h"
 9#include "afxwin.h"
10#endif __CWnd_15265_H_INCLUDED

This header is included when the “CWnd” class is used, so the “CWnd” class external definition (provided in the “afxwin.h” file) is available to all the class clients. For example, the “CWnd” class external definition is available in the code generated for the “TaskWindow” class.

 1//includes for used library types
 2#include <afxtempl.h>
 3#include <cstringt.h>
 4#include <afxwin.h>
 5#include <afxcoll.h>
 6
 7//automatic includes (friends, associated classes, etc)
 8#include "MyPlanner/GUI/Windows/CWnd.h"
 9#include "MyPlanner/GUI/ITaskView.h"
10#include "MyPlanner/TaskManagement/Task.h"
11
12namespace MyPlanner
13{
14    namespace GUI
15    {
16        namespace Windows
17        {
18            class TaskWindow : public CWnd, public GUI::ITaskView
19            {
20            //...
21            private:
22                CString displayTitle;
23
24            public:
25                CDC dc;
26                                   
27            //associations
28
29            public:
30                TaskManagement::Task* task;
31                CMap<CString,CString&,CBrush,CBrush&> brushResource;
32
33            //operations
34
35            public:
36                TaskWindow();
37                TaskWindow(const TaskWindow& value);
38                TaskWindow& operator =(const TaskWindow& value);
39                ~TaskWindow();
40                void formatDisplayTitle(std::string& FormatStr);
41                CDC getDc();
42
43            //non-modeled members
44            };
45        }
46    }
47}

Overriding external functions

To interface the application with an external environment, it can be necessary to override certain virtual functions defined in external sources. It is often necessary to override message handlers defined in the external GUI library, such as MFC.

To override an external virtual function, carry out the following steps:

To match the parameter type with an external one, you should simply switch off the automatic decoration flag in the C++ edition dialog box for the parameter, before specifying the intended type specifiers in the same dialog box.

Note: If you change the deduced values of the “Pointer type”, “Container type” and “Collection pointer type” properties in the parameter edition dialog boxes, the automatic decoration flag is switched off by Modelio C++ Designer.

For example, in the “TaskWindow” class we want to override the “OnCreate” message handler defined in the “CWnd” parent external class.

The “OnCreate” message handler has the following declaration:

1class CWnd : public CCmdTarget
2{
3//...
4public:
5    afx_msg int OnCreate(CREATESTRUCT* lpCreateStruct);
6//...
7};

We create the “OnCreate” operation in the “TaskWindow” class, and then set its “lpCreateStruct” parameter to the “CREATESTRUCT” dummy datatype (this structure is defined in the “afxwin.h” header, so it is available as a result of inheritance from the external “CWnd” class).

Then, we manually specify the C++ properties of the “lpCreateStruct” parameter, to set its type as the pointer, and remove the const specifier.


Manually specifying the C++ properties of the “lpCreateStruct” parameter

As a result, Modelio C++ Designer switches off the automatic decoration flag for the “lpCreateStruct” parameter and instructs that automatic deduction for this model element should be skipped and that only C++ decorations specified by us should be used.

The last remaining action is to define the “afx_msg” specifier for the “OnCreate” operation. This specifier is set in the operation C++ edition dialog box.


Defining the “afx_msg” specifier for the “OnCreate” operation

As a result, Modelio C++ Designer produces the correct code for the “TaskWindow” class, where the “OnCreate” function does override the “OnCreate” message handler defined in the external “CWnd” class.

 1//includes for used library types
 2#include <cstringt.h>
 3#include <afxwin.h>
 4#include <afxcoll.h>
 5
 6//automatic includes (friends, associated classes, etc)
 7#include "MyPlanner/GUI/Windows/CWnd.h"
 8#include "MyPlanner/GUI/ITaskView.h"
 9#include "MyPlanner/TaskManagement/Task.h"
10
11namespace MyPlanner
12{
13    namespace GUI
14    {
15        namespace Windows
16        {
17            class TaskWindow : public CWnd, public GUI::ITaskView
18            {
19            //...
20            private:
21                CString displayTitle;
22
23            public:
24                CDC dc;
25
26            //associations
27
28            public:
29                TaskManagement::Task* task;
30                CMap<CString,CString&,CBrush,CBrush&> brushResource;
31
32            //operations
33
34            public:
35                TaskWindow();
36                TaskWindow(const TaskWindow& value);
37                TaskWindow& operator =(const TaskWindow& value);
38                ~TaskWindow();
39                void formatDisplayTitle(std::string& FormatStr);
40                CDC getDc();
41                afx_msg int OnCreate(CREATESTRUCT* lpCreateStruct);
42
43            //non-modeled members
44            
45            };
46        }
47    }
48}

Working with typedefs

In C++, typedefs are intensively used to introduce compiler-controlled simple types used as short names for complex types. Modelio C++ Designer lets you easily create typedefs of arbitrary complex types.

To create a C++ typedef, you simply create a UML datatype with the intended typedef name in the model. To specify the represented C++ type, the datatype is decorated by the “Cxx.TypeExpr” tagged value, and the C++ type expression is provided in the in the first tagged value parameter.

Because C++ permits very complex recursive type definitions, you can put the “$name” ACT macro in the type expression to specify exactly where the typedef name should be injected. If the “$name” macro is not specified, it is automatically added at the end of the type expression.

Modelio C++ Designer translates the UML datatype into the C++ typedef declaration by adding the “typedef” keyword and substituting the “$name” macro by the typedef name. The datatypes defined in a class are generated in the class definition, while the datatypes defined in a package are generated in the package namespace in the package header file.

For example, we want to define the task handlers in the “Task” class. Task handlers are specific functions that run when certain conditions in the task are satisfied, for example, when the task is completed or delayed. A task handler is represented by the pointer to a function, which takes the “Task” instance as a parameter and returns a Boolean status.

To represent the task handlers, we introduce the “TaskHandler” typedef in the “Task” class, which expresses this pointer to a handler function. We then create the “TaskHandler” datatype in the “Task” class and decorate this datatype by the “Cxx.TypeExpr” tagged value with the following expression:

1bool (*$name)(Task* theTask)

The next figure illustrates these operations:


The result of the operations you have just carried out

We are now going to continue by defining the newly-created datatype as having public visibility. Modelio C++ Designer produces the following code for the “Task” class.

 1//includes for used library types
 2#include <string>
 3#include <set>
 4#include <list>
 5
 6//automatic includes (friends, associated classes, etc)
 7#include "MyPlanner/TaskManagement/SimpleProject.h"
 8#include "MyPlanner/TaskManagement/HumanResource.h"
 9
10namespace MyPlanner
11{
12    namespace TaskManagement
13    {
14        class Task
15        {
16        //typedefs
17
18        public:
19            typedef bool (*TaskHandler)(Task* theTask);
20
21        //attributes
22
23        public:
24            std::string name;
25            std::string wbsCode;
26
27        //associations
28
29        protected:
30            SimpleProject* project;
31            std::set<Task> subTasks;
32            Task* owner;
33            std::list<HumanResource> resource;
34
35        //operations
36
37        public:
38            Task();
39            Task(const Task& value);
40            Task& operator =(const Task& value);
41            ~Task();
42            bool addSubTask(int wbsNum, Task& SubTask);
43            std::string getName();
44            void setName(std::string value);
45            std::string getWbsCode();
46            SimpleProject* getProject();
47            std::list<HumanResource>& getResource();
48            std::set<Task>& getSubTasks();
49            Task* getOwner();
50            void setOwner(Task* value);
51
52        //non-modeled members
53
54        };   
55    }
56}

After this, we can easily create attributes of “TaskHandler” type. For example, let’s create the “handlers” attribute that models the mapping of handlers assigned to the given events for the task, and then create its model- level accessor. With the help of the accessor, we can assign our handlers to given events for a given task, and our code is concise due to the use of typedef.


The “handlers” attribute and the “getHandlers” accessor

Modelio C++ Designer produces the following code for the “getHandlers” accessor definition, where the typedef defined in the “Task” class is correctly referred to.

 1//class header file
 2#include "MyPlanner/TaskManagement/Task.h"
 3
 4namespace MyPlanner
 5{
 6    namespace TaskManagement
 7    {
 8        //...
 9        std::hash_map<std::string,Task::TaskHandler>& Task::getHandlers()
10        {
11            //modifiable zone @16423@30671900:2486@T
12            return handlers;
13            //modifiable zone @16423@30671900:2486@E
14        }
15    }
16}

Working with type libraries

Introduction

A type library groups together type definitions, which guide the translation of primitive types, data types and collection types used when modeling C++ implementations.

Selecting a type library

A type library can be selected on two levels, a project build targets or individual structural features or parameters.

To set a type library for a chosen model element, you simply select it in the library selector in the element’s C++ edition dialog box.


Setting a type library on the “TaskWindow” class

Modelio C++ Designer automatically uploads new type libraries and visualizes them in the library selector. The “Default” choice uses the current project’s type library for generation.

Let’s consider a more detailed model of our task management application. First we model the application GUI for the Windows platform, which uses the MFC library to implement GUI functionalities. We then design the “TaskWindow” class, which represents the window used to graphically visualize of task information (owner, subtasks, resources, and so on).

Let’s say that this class has the “Brush Resources” association with the “CBrush” class, which represents the display (GDI) brushes used to render tasks of various different statuses. To rapidly access brush resources, brush instances are associated with brush names.


The more detailed model of our task management application

We will now continue by selecting the “MFC” type library for the current project.


Selection of the “MFC” type library for the current project

As a result, Modelio C++ Designer produces the following code for the “TaskWindow” class. The “OrderedMap” semantics of the “browserResource” association end correspond to the “map” collection type provided by the MFC type library and are implemented by the “CMap” type. The include directives required to use this type are automatically generated.

 1//includes for used library types
 2#include <afxcoll.h>
 3
 4//automatic includes (friends, associated classes, etc)
 5#include "MyPlanner/TaskManagement/Task.h"
 6
 7//modifiable zone @13936@30671900:989@T
 8#include "afxwin.h"
 9//modifiable zone @13936@30671900:989@E
10
11namespace MyPlanner
12{
13    namespace GUI
14    {
15        namespace Windows
16        {
17            class TaskWindow
18            {
19            //...
20            public:
21                TaskManagement::Task* task;
22                CMap<CString,CString&,CBrush,CBrush&> brushResource;
23
24            //operations
25
26            public:
27                TaskWindow();
28                TaskWindow(const TaskWindow& value);
29                TaskWindow& operator =(const TaskWindow& value);
30                ~TaskWindow();
31
32            //non-modeled members
33
34            };
35        }
36    }
37}

Multiple type libraries

It is possible to specify type libraries up to particular structural features and parameters, thereby making it possible to have multiple type libraries defined for members of a single class.

Let’s continue by modeling the fact that the “TaskWindow” class implements the “ITaskView” interface, designed to support cross-platform GUI. This interface uses the “STL” type library due to STL portability.

The “ITaskView” interface defines the “formatDisplayTitle” operation used to format the task display title according to a given formatting string.


The latest developments we have made to our model

We are now going to create the string type “displayTitle” attribute in the “TaskWindow” class, which represents the task title rendered in the window. In this class, we will implement the “formatDisplayTitle” operation from the “ITaskView” interface.

If we simply generate the code, the “formatDisplayTitle” function defined in the “TaskWindow” class will not override the interface operation, because its string parameter type will be translated to the “CString” type, which implements it in the “MFC” type library.

To make the operation override the interface method, we will now specify the “STL” type library individually for its parameter.


Changing the library on the FormatStr parameter

Modelio C++ Designer now produces the following code for the “TaskWindow” class. Implementations of string types and include directives for their headers from both the “MFC” and “STL” type libraries are presented.

 1//includes for used library types
 2#include <cstringt.h>
 3#include <string>
 4#include <afxcoll.h>
 5
 6//automatic includes (friends, associated classes, etc)
 7#include "MyPlanner/GUI/ITaskView.h"
 8#include "MyPlanner/TaskManagement/Task.h"
 9
10//modifiable zone @13936@30671900:989@T
11#include "afxwin.h"
12//modifiable zone @13936@30671900:989@E
13
14namespace MyPlanner
15{
16    namespace GUI
17    {
18        namespace Windows
19        {
20            class TaskWindow : public GUI::ITaskView
21            {
22            //...
23            private:
24                CString displayTitle;
25
26            //associations
27
28            public:
29                TaskManagement::Task* task;
30                CMap<CString,CString&,CBrush,CBrush&> brushResource;
31                                
32            //operations
33
34            public:
35                TaskWindow();
36                TaskWindow(const TaskWindow& value);
37                TaskWindow& operator =(const TaskWindow& value);
38                ~TaskWindow();
39                void formatDisplayTitle(std::string FormatStr);
40
41            //non-modeled members
42
43            };
44        }
45    }
46}

Note 1: You can also create your own type libraries using Modelio C++ Designer platform development features, by editing open ACT type library definitions. Type library selectors are fed dynamically, so when a new type library is installed, it is immediately visible and available for selection.

Note 2: When a type library is selected for a particular model element, this only suggests that it be used for type translation, but does not force Modelio C++ Designer to use only type implementations from this library. Therefore, when the type or collection type of a model element cannot be translated with a type library selected for it, the type library selected for its owner applies.

Using non-primitive types

A type library can define non-primitive types, which are not semantically compatible with basic UML types, such as string or integer. To use such a type, create an empty datatype with the same name in the model, and then assign this datatype to the attribute or parameter type in the usual way. Modelio C++ Designer automatically substitutes it for the library definition, inducing include directives and applying ACTs specified there.

It can be useful to create these data types in a dedicated package specified not to produce the namespace and not to produce C++ code.

For example, the “MFC” type library provides the “CDC” type expressing the respective “MFC” class, which represents the device drawing context.

Create the “dc” attribute used to store the device context to draw the task window in the “TaskWindow” class. This attribute should have the “CDC” type.

It would not be wise to model the “CDC” class from MFC, because it defines a huge number of member functions. In order to use the CDC type defined in the “MFC” library, create the “CDC” datatype in the dedicated “Win32Types” package, marked as no code and no namespace.


The “CDC” datatype you have just created

Please note that the data type has been automatically decorated with the <<C++ DataType>> stereotype.

Continue by assigning the “CDC” datatype as being the type of the “dc” attribute in the “TaskWindow” class, by dragging it into the “Class” field in the standard attribute dialog box.

Modelio C++ Designer produces the following code for the “TaskWindow” class. Translation of the datatype to the “CDC” class and include directives required to use this class are presented.

 1//includes for used library types
 2#include <cstringt.h>
 3#include <string>
 4#include <afxwin.h>
 5#include <afxcoll.h>
 6
 7//automatic includes (friends, associated classes, etc)
 8#include "MyPlanner/GUI/ITaskView.h"
 9#include "MyPlanner/TaskManagement/Task.h"
10
11namespace MyPlanner
12{
13    namespace GUI
14    {
15        namespace Windows
16        {
17            class TaskWindow : public GUI::ITaskView
18            {
19            //...
20            private:
21                CString displayTitle;
22                CDC dc;
23                                
24            //associations
25
26            public:
27                TaskManagement::Task* task;
28                CMap<CString,CString&,CBrush,CBrush&> brushResource;
29
30            //operations
31
32            public:
33                TaskWindow();
34                TaskWindow(const TaskWindow& value);
35                TaskWindow& operator =(const TaskWindow& value);
36                ~TaskWindow();
37                void formatDisplayTitle(std::string FormatStr);
38
39            //non-modeled members
40
41            };
42        }
43    }
44}