Thursday, March 20, 2008

Code Generator Part IV: IOM

Following the previous post the current post will try to draw a picture of the design model of a code generator. All the objects included in the context of a code generation process (e.g. for a code generator that generates object-oriented source code, the building blocks of the IOM are class, attribute, operation, parameter etc.) has been designed as the Internal Object Model (IOM). There are two more layers included in the anatomy of the code generator - Importer and Exporter.

The IOM Layer

For the object-oriented code generation process the IOM has been designed borrowing UML concepts. Basically, the internal model can be a representation of the object-oriented concepts following the structure of UML model and notation. Therefore, a set of classes and associations has been designed representing UML classes, attributes, operations, parameters, and associations. Basically in this case the UML features and rules have been designed by using UML itself. As a convention, IOM classes start with the IOM prefix. Fig 3 shows a class diagram of the IOM classes. The IOMClass class models a UML class. It has an aggregation with the IOMAttribute and IOMOperation classes because classes have attributes and operations. Since operations have parameters, an aggregation is modeled between the IOMOperation and the IOMParameter classes. The IOMAssociation class represents a UML association. It has two roles (start and end) that are modeled by the IOMRole class. Then, that last class has an association with the IOMClass class (involved), which represents the start or the end class of the UML association. IOMOOController class acts a controller and stores the entire IOM (collection of all classes and associations included in the IOM) as a static aggregation. IOMOperationBody is an interface that represents the body of any operation to be defined at a later time. Any class that represents the body of an operation will have to implement the IOMOperationBody interface. For instance, ToXMLStringBody class contains the implementation of the “transform” method (a method to print out the values of all the attributes of a DTO) for all the generated DTOs. The descriptions of the classes involved in the IOM layer are given below. Fig 3 shows the classes involved in the IOM layer for the source code generation process.


Figure 3

IOMClass class represents a class in object-oriented scenario according to UML. It has ten attributes: name (the name of the class), stereotype (the UML associated stereotype), documentation (documentation for the class), packageName (the package in which the class belongs to), visibility (the visibility of the class, the values of this attribute can be private, public, protected.), isFinal (indicates whether the class is a final one), isAbstract (indicates whether the class is an abstract class), baseClasses (list of base classes of this class), baseInterfaces (list of base interfaces of this class) and imports (list of links to other libraries or APIs, e.g. “import” clause in Java). The aggregations with the IOMAttribute and IOMOperation classes are implemented by two ArrayList (attributes and operations) and related get/set/add methods. The class also contains the getAssociations() method that returns all the IOMAssociations in which the class is involved as a start or end role.

IOMAttribute class represents an attribute/member of a class in object-oriented scenario. It has twelve attributes: name (the name of the attribute), type (the type of the attribute, currently the code generator supports boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”), multiplicity (multiplicity of the attribute, if it’s a collection or array), documentation (documentation for the attribute), visibility (the visibility of the attribute/member, permitted values are private, public, protected.), defaultValue (the default value with which this attribute will be initialized, if not specified, the attribute will be initialized by it’s default value according to Java standards e.g. string type will initialized by “new String()”), isStatic (indicates whether the attribute is a static one), isFinal (indicates whether the attribute is a final one), isTransient (indicates whether the attribute is a transient, i.e. uses the transient keyword of Java), classParent (this is a reference to the IOMClass instance to which the attribute belongs), elementTag (XML tag in which the value of this attribute will be encapsulated during XML transformation) and groupTag (If the member is a collection of values i.e. multiplicity is more than one, the value of groupTag will be used as an XML tag encapsulating the group of values during XML transformation).

IOMOperation class represents an operation / method of a class in object-oriented scenario. It has sixteen attributes: name (the name of the operation), returnType (the return type of the operation, currently the supported types by the code generator are boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”), documentation (documentation for the operation), visibility (the visibility of the operation / method, the permitted values are private, public, protected.), isStatic (indicates whether the operation is a static one), isFinal (indicates whether the operation is a final one), isAbstract (indicates whether the operation is an abstract one), isConstructor (indicates whether the operation is a constructor. The constructor name will always be same as the class name for Java code generation), isDestructor (indicates whether the operation is a destructor. Currently this attribute is not used it’s kept for future uses for generation in other languages like C++.), exceptions (list of exceptions that this operation might throw while executed), isSynchronized (indicates whether the operation is synchronized), isNative (indicates whether the operation is native), classParent (this is a reference to the IOMClass instance to which the operation belongs), directive (this indicates any other options that might be required in future, not used currently), bodyClassName (the name of the class that returns the body content of this operation) and body (the body content of the operation as returned by the class whose name is mentioned in bodyClassName. The class with the given name will be loaded at the runtime by the code generator and invoked using reflection to get the body content of the operation), body (the body content of the operation that has been returned by the class mentioned in the bodyClassName) and classParent (the parent class to which the operation belongs). The usage of bodyClassName attribute makes the code generator independent of the business logic of an operation. This way the logic of an operation is externalized from the code generator.

IOMParameter class represents a parameter of an operation in object-oriented scenario. It has three attributes: name (the name of the parameter), type (the type of the parameter, currently the supported types by the code generator are boolean, char, byte, integer, float, double, long, string, date, short or any custom type like “MyClass”) and operationParent (the operation name that takes this parameter as the input).

IOMAssociation class represents an association with another Class in object-oriented scenario. It has two roles (start and end) that are modeled by the IOMRole class i.e. two IOMRole instances indicating start and end of the association. It has one attribute: name, which is the name of the Association. This class contains the get/set methods for the above-mentioned attributes.To explain the way in which the associations will be implemented we can consider an example. In this example, four different cases of relations between two classes have been considered. Fig 4 shows those cases.


Figure 4

As it has been depicted in the above figure, when the class A has a bi-directional (navigation is true on both sides) association with just one class, B, the generator creates the setXxx/getXxx methods for both A and B. If the association is unidirectional (navigation is true on one side and false on the other side), B won't have the setA and getA methods, because that navigation is not allowed. When the A class can be associated to more B classes, A contains addB and getAllB, while B contains setA and getA, if the association is bi-directional, and no method otherwise.

Since a role in an association is interpreted as an attribute of a class, the IOMRole class has been designed as a child class of IOMAttribute. The IOMRole class represents the role of a class in an UML association. It has three attributes in addtion to the attributes of IOMAttribute class: isNavigable (unidirectional or bi-directional), classInvolved (name of the IOMClass having this Role), isStart (indicates whether the role is indicating the start or end of an association). This class contains the get/set methods for all the above-mentioned attributes.
IOMOperationBody is an interface representing the body of an operation. This interface has only one method - getOperationBody(). The method takes an IOMClass object as the input and returns a string containing the content of body of an operation. The IOMClass object is considered as the parent to the operation whose body is returned. Once there is a need to describe an operation body, a new class has to be developed implementing this interface and the actual body content of the operation has to be returned from the getOperationBody() method of the child class. ToXMLStringBody is such a child of IOMOperationBody interface.

The root class of the model is IOMOOController, which is shown in Fig 3. It contains and provides the possibility of access to the instances of IOMClass and IOMAssociation involved in the model. This class is designed as a static class. Since the Code Generator System is not a part of any client-server system or product and it is to be used by a project team member/developer in stand-alone mode, this class has not been designed to run in a multi-threaded environment. In addition, the IOMOOController class implements the queryClass() method that may be useful to search a class by name. Importers and exporters start from that class respectively to create the IOM and to read metadata from it to write the output.