The ANSI Containers add-in -------------------------- TABLE OF CONTENTS ======================= I) Why this add-in 1) Container used to contain objects of a custom class 2) Container used to contain fundamental types objects 3) Container used to contain unknown type objects II) How to use it III) A few useful to know details of the implementation 1) Where are the data stored 2) What does it do behind my back 3) Portability IV) Installation V) Disclaimer I) Why this add-in ------------------------ When reversing C++ source code using template classes with the ANSI C++ add-in, anonymous type classes are generated in the model. These classes are instantiated classes of the corres- ponding template class, have no name and have the stereotype anonymous_type. In their detail tab are the value given to the template class for the instantiation. These classes are often unwanted and for a big model the conversion is fastidious. Here follows the three main cases in what this add-in has to run. I.1) Container used to contain objects of a custom class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If the code is: template class Tab { ... }; class B { ... }; class A { private: Tab myTabOf10B; }; After reverse engineering, the model will contain: - A parameterized class Tab - An anonymous_type stereotyped class instantiating Tab - A class A having an aggregate association to the anonymous_type class Often, the user will not want to see the relation from A to the Tab class. He will rather want to see an association from A to B implemented using the Tab container. In most of the cases the container class shouldn't appear on the class diagrams. It is part of the implementation decisions and has nothing to do on class diagrams reflecting the application architecture. The ANSI Containers add-in allows to declare Tab as being a container class and transform the anonymous_type class into an association from A to B having a complex role (of name myTabOf10B) on the B side for specifying the type used for code generation (in this example: Tab). (Please see the help on complex roles if necessary). I.2) Container used to contain fundamental type objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Having this code: class A { private: Tab myTabOf10double; }; It is not possible to create an association to the class double because this class normally doesn't exist in the model but is considered as being a fundamental type. In that case, the ANSI Containers add-in will convert the anonymous_type class into an attribute of type Tab. In C++, the fundamental types are by default: bool;char;byte;short;int;long;float;double This add-in allows adding your own fundamental types to this list if you wish to. For instance, you may have a class ComplexNumber implementing the complex numbers. In that case you don't want this class to appear on each class diagram referring it. Declaring it as being a fundamental type makes the corresponding anonymous_type class transformed by the add-in as attribute. I.3) Container used to contain unknown type objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Let's start again with a code example: class A { private: Tab myTabOf10whatsthat; }; If whatsthat is not a class in the model and is not among the fundamental types, the add-in asks the user what to do: - Convert as attribute - Add to fundamental types and convert as attribute - Ignore II) How to use it ----------------------- The ANSI Containers add-in adds a submenu called Containers to the ANSI C++ Tools menu. This submenu has two items: - Convert annonymous_type classes This option basically does what is described above according to the settings entered in the preferences dialog box described below. This option applies on the selected classes. - Preferences... Selecting this option, makes the "Containers Conversion Preferences" dialog box appears. This dialog box contains the following widgets: ~ A list box: Displays the defined containers and allows to select one for editing The containers display format follows this grammar: The axiom of this grammar is , is a terminal -> <<> <>> -> $TYPE -> <> | , -> <> | , -> $IGNORE | $IGNORE , <> is the empty character string (nothing) is a non empty character string defining the name of the template class <<> is the < character <>> is the > character Note that this grammar allows to have one and only one $TYPE argument among zero or more $IGNORE arguments. Example: Tab<$TYPE,$IGNORE> is compliant with this grammar. $TYPE stands for the contained type. $IGNORE stands for any other template argument that is going to be ignored during the conversion. Note that for recognizing a container class the add-in checks the name of the container and the number of arguments but it doesn't check if the type of the contained elements is an existing class or a fundamental type. This could certainly be improved. i.e. if you define your containers list as: Tab<$TYPE,$IGNORE> Tab<$IGNORE,$TYPE> Tab<$TYPE> Only the first one will be useful because when converting an anonymous_type class corresponding to the type Tab, the conversion process will stop looking in the list when finding a container of name Tab and having two arguments. However, if the anonymous_type class corresponds to the type Tab then the matching container declaration will be Tab<$TYPE>. ~ A frame "Selected Container" This frame concerns the currently selected container declaration in the list. It contains the following widgets: ~ A text box For editing the name of the container ~ An "Update Name" button For validating the name of the selected container ~ A "+" button For adding a $IGNORE argument to the argument list ~ A "-" button For removing a $IGNORE argument from the argument list ~ A "<--" button For moving the $TYPE argument to the left ~ A "-->" button For moving the $TYPE argument to the right ~ A "Move Up" button For moving the currently selected container declaration of one position up in the list ~ A "Move Down" button For moving the currently selected container declaration of one position down in the list ~ A "Delete" button For deleting the currently selected container from the list ~ A "Insert New" button For inserting a container declaration at the current position in the list ~ A frame "Container list" This frame concerns the whole list It contains: ~ A "Save as default" button For saving the current list as being the default one when creating a new model. These information are stored in a file located in the add-in directory. The writing of this file is done when pressing this button. i.e. pressing Cancel won't undo the changes made in this file while pressing Save as default. ~ A "Load default" button For loading the saved default list ~ A fundamental types text box For defining the fundamental types. Its default value is "bool;char;byte;short;int;long;float;double" The fundamental types are separated by semicolons. ~ An "OK" button Pressing it, the list is saved in the ANSI C++ Project property Containers of the current model. The fundamental types are saved in the registry. The dialog box is closed. ~ A "Cancel" button Nothing is saved in the model nor in the registry. If the "Save as default" button has been pressed, the changes in the default saved list are not undone. (See the "Save as default" button description above). The dialog box is closed. III) A few useful to know details of the implementation ------------------------------------------------------------- III.1) Where are the data stored ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - The "Containers" model property When activated, the ANSI Containers add-in adds an ANSI C++ property at the model level meaning that there is only one container list per model (and it is saved in the model file). You can see it in the Model Properties, tab ANSI C++, type Project, property Containers. This property is writable by the user only because Rose doesn't allow having write protected properties. It shouldn't be edited by the user. It stores the information defining the containers list declaration according to this grammar: The axiom of this grammar is , is a terminal -> <> | -> , , <> is the empty character string (nothing) is a non empty character string defining the name of the template class is a number determining the number of arguments is a number determining the position of $TYPE among the $IGNOREs is the character of ASCII code 13 followed by the one of code 10 - The fundamental types These are stored in the registry under the key "HKLM\SOFTWARE\Rational Software\Rose\AddIns\ANSI C++\FundamentalTypes". This is the standard location of the fundamental types for the Rational Rose add-ins. - The default containers list This is stored in a file called DefaultContainers.txt located in the add-in directory. The add-in directory is named "ANSI Containers" and located in the ANSI C++ add-in directory named "ansi c++" itself located in the Rose directory (where rose.exe is). The default location of the Rose directory is C:\Program Files\Rational\Rose. III.2) What does it do behind my back ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The only thing that may not be obvious in its behavior is when creating a new model. It triggers the OnNewModel event for loading the default containers into the new model. III.3) Portability ~~~~~~~~~~~~~~~~~~~~ This add-in has been written using Rose Script for keeping it easy to modify. However, Rose Script doesn't provide any way of modifying the registry. For that (and only for that), I use the Windows Scripting Host via COM. I only use its RegRead and RegWrite methods. This makes the script not portable under UNIX. A workaround would be to modify the script to store the fundamental types in a file (as the default containers list). IV) Installation ---------------------- Close any running instance of Rose. Get the attached files: readme.txt Containers.reg ANSI Containers/ANSIFindClass.ebs ANSI Containers/ConvertAnonymousTypeClasses.ebs ANSI Containers/LoadDefaultContainers.ebs ANSI Containers/Preferences.ebs ANSI Containers/Containers.mnu ANSI Containers/Containers.pty ANSI Containers/DefaultContainers.txt Copy the whole "ANSI Containers" directory in the Rational Rose ANSI C++ directory. The default location of this directory is "C:\Program Files\Rational\Rose\ansi c++" (You should then have the "ansi c++" directory containing the "ANSI Containers" directory containing the 7 files listed above). If your Rational Rose directory is not "C:\Program Files\Rational\Rose\ansi c++" then you will have to edit the Containers.reg file with a simple text editor (such as notepad) and change the line "InstallDir"="C:\\Program Files\\Rational\\Rose\\ANSI C++\\ANSI Containers" according to your own Rational Rose directory. Merge the Containers.reg file in the registry (double click on the file should do it). Start Rose and check in the ANSI C++ Tools menu that the Containers menu is there. V) Disclaimer ------------------- THE MATERIAL AND/OR SOFTWARE IS PROVIDED ‘AS IS’. RATIONAL AND ITS THIRD PARTY LICENSORS DISCLAIM ALL WARRANTIES EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, THE WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT, TITLE OR FITNESS FOR A PARTICULAR PURPOSE OR ARISING OUT OF THE COURSE OF DEALING, USAGE OR TRADE PRACTICE, CONTENT OF THE MATERIAL OR SOFTWARE. RATIONAL MAKES NO WARRANTIES OR REPRESENTATIONS REGARDING THE ACCURACY OR COMPLETENESS OF THE MATERIAL AND/OR SOFTWARE PROVIDED OR THAT IT WILL MEET LICENSEE’S REQUIREMENTS OR THAT THE MATERIAL AND/OR SOFTWARE WILL BE ERROR FREE. IN NO EVENT SHALL RATIONAL OR ITS LICENSORS BE LIABLE TO LICENSEE OR A THIRD PARTY FOR ANY INDIRECT, DIRECT, NEGLIGENCE, SPECIAL, OR CONSEQUENTIAL DAMAGES INCLUDING LOST PROFITS, LOST DATA AND THE LIKE ARISING OUT OF OR IN CONNECTION WITH THIS RECEIPT OF MATERIAL AND/OR SOFTWARE EVEN IF RATIONAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.