Copyright © 2001-2007 innoQ GmbH, Cham, Switzerland
This documentation is part of innoQ's iQgen product suite and licensed under the terms of the accompanying license agreement.
iQgen is accompanied by, or makes use of third party software. The corresponding license agreements can be found here.
Januar 2007
| Revision History | ||
|---|---|---|
| Revision 3.0.2 | Januar 2007 | innoQ |
| Revision 2.1 | March 2006 | innoQ |
| Revision 2.0 | April 2004 | innoQ |
Abstract
This is the product documentation for iQgen, innoQ's model driven software generator.
Table of Contents
List of Figures
List of Tables
First of all: Thank you for using iQgen, innoQ's model driven software generator.
We have tried to make this manual as comprehensive, understandable and useful as possible. Unfortunately errors aren't completely avoidable. Should you find one - please let us know.
After you have installed iQgen, the user guide will help you with your first steps. To provide you with some hands-on experience, many sections of this guide will refer to samples you installed as part of the iQgen distribution. The most important of these samples is Tutorial_1, which will be referred to throughout the documentation. Once you have mastered Tutorial_1 the reference at the end of this document will be a helpful companion while working with iQgen.
Enjoy.
We are very interested in your experiences with iQgen. Therefore we invite you to let us know about your suggestions, problems or praise via email. Just write to <support@innoq.com>
Please remember to include the following information in your email:
Operating System
JDK manufacturer and version
iQgen version
CASE tool manufacturer and version, XMI exporter
XMI version
The following features are new in iQgen 3.0:
MacOS 10.4+ support
iQgen Plugin for Eclipse 3.1+
JDK 1.4+ compatible
The Plugins for iQgen introduce a new infrastructure to support more and different types of models. Previous versions officially only supported UML 1.X compliant models which were stored in XMI files. As the core of iQgen now handles any type of models, other model sources can be easily processed. With the right plugin iQgen can generate from any source of information, whether this is an UML model or not. The following list contains some examples of already implemented extensions based on iQgen 3.0:
Ecore (www.eclipse.org/emf)
Mapping between Ecore and UML 1.X
Instances of Ecore models (with Dynamic EMF)
UML2 (www.eclipse.org/uml2)
Mapping between UML2 and UML 1.X
JAXB (Java XML Data Binding)
WSDL (Web-Service Description Language)
XML-DOM (XML Document Object Model)
Databases (both schema and content)
To give you the opportunity to evaluate these capabilities please download the free "plugin pack" (iQgen-plugins-1.0.zip) with some plugins for our webpage. It contains these plugins:
ecore
ecore library sample (the library sample from Ecore)
uml2
xml (for XML-DOM)
For installation instructions please read the included readme.txt.
The following features are new in iQgen 2.1:
The iQgen Eclipse integration has been updated to work with Eclipse 3, the latest version of the leading Open integrated development environment.
Previous versions of iQgen generated files whenever the source model changed. With Smart Generation, iQgen checks whether the file's contents would change when generating, and only updates the file when necessary. While generation is seldomly, if ever, a performance problem, some configuration management systems and almost all build tools mistakenly check only for the timestamp of input files, and performed unnecessary work. With Smart Generation, build and check-in/check-out times are thus significantly reduced in larger projects.
To ease support for CASE tools and other software emitting XMI, the XMI reader associated with a particular XMI generator is configurable in an external XML file.
iQgen 2.1 has been bundled as a Mac OS X application, supporting simple drag & drop installation and the native Mac OS X look & feel (i.e. the menu bar where a Mac user would expect it to be, quit, preferences and about menus in the right places, storage of user preferences in the appropriate location etc.).
The following features are new in iQgen 2.0:
Plugin for the Eclipse platform
Enhanced user interface
Hooks for model validation
Properties to control transformation settings
Improved logging for command line and Ant integration
Updated and enhanced documentation
In addition to the stand-alone user interface, iQgen is now fully integrated with the Eclipse platform. The iQgen Eclipse plugin enables you to edit templates, start the generation process, and edit the resulting artifacts - all without leaving the IDE. Combined with an Eclipse-integrated modeling tool such as TogetherEC, all of your MDA toolset can be combined in a single environment.
We have made numerous improvements to the user interface, including the ability to view stereotypes and tagged values.
Based on customer feedback, we have created hooks that allow iQgen users to validate their UML models, e.g. to check compliance to the UML profile being used. As this is a programmatic interface, there is virtually no limit to what can be checked. Validation errors can be defined to emit warnings, errors or fatal errors (the last of which will terminate the code generation process).
Not all information should be stored in the UML model; with advanced template sets, there is often a need for an easy way to provide parameters. Transformation settings are an easy-to-use solution to this problem.
Log filters that have been available in the UI only in previous versions of iQgen are now usable from both the command line and from Ant scripts that use the iQgen Ant task.
Table of Contents
Before you install iQgen please take some time and verify that your system meets the system requirements laid out in the next section. Then you should decide which distribution format best fits your needs. iQgen comes in three different flavors:
as a ZIP archive, extractable with WinZip™ and other, similar tools
as a GZIP-compressed tar archive (for Unix™ or Cygwin™ users)
as a self-extracting installation program for Windows operating systems
As a Mac OS X 10.x application compressed in .tar.gz format.
The Windows installer is the easiest way to get iQgen up and running if you are on a Windows platform. If you plan to use iQgen on both Windows and Unix boxes, you may want to use the same .zip or .tar.gz archive for both installations. The Mac OS X distribution is the easiest way to get up and running on this fine platform.
Like any other tool iQgen requires a certain execution environment. The following sections list these requirements.
You can install iQgen on any machine capable of running a Java Development Kit (JDK) version 1.3 or higher. iQgen has been successfully tested on the following platforms:
Microsoft Windows NT 4.0 with Service Pack 5
Microsoft Windows 2000 Professional
Microsoft Windows XP
SuSE Linux 7.1, 8.0, 9.0
Apple Mac OS X 10.3, 10.4
Eclipse 3.2
Before you install iQgen, you should have a working Java Development Kit (JDK) installation on your system.
Note that the Java Runtime Environment (JRE) is not sufficient, because iQgen needs to compile Java source code it generates, even if you do not use Java as your programming language.
You can get the JDK from Sun's web site at http://www.java.com/.
Start the installation process by double-clicking on the .exe file in Explorer and follow the instructions.
Extract all files from the .zip file to a directory of your choice, e.g. c:\Program Files\iQgen. You can use any location you like, just make sure that you remember to replace your installation root directory wherever we refer to it throughout the documentation. In the root directory, you will find scripts called iqgen.bat (for Windows platforms) and iqgen.sh (for Unix or Cygwin installations). The file iqgen.bat assumes, that Java was correctly installed and java.exe is part of the %PATH% variable. For iqgen.sh, modify it and set JAVA_HOME to the appropriate value, e.g. c:\jdk1.3.1.
First decide where you want to install iQgen. We assume that you choose /usr/local, but you can use anything you like - just make sure that you remember to replace your installation root directory wherever we refer to it throughout the documentation. Change to the directory you just created and extract the archive's contents using the following command:
gzip -d -c iQgen-x.x.tar.gz | tar xvf
This will create a directory called iQgen under the current directory. In the root directory, you will find a script called iqgen.sh. Edit this file and set JAVA_HOME to the appropriate value, e.g. /usr/local/jdk1.3.1
To install iQgen for Ant, just execute the local_ant_install.xml file that is located in your iQgen home directory. It will copy all necessary files to your Ant directory. Please note that for this to work, the environment variable ANT_HOME must be set.
The Eclipse plug-in is not yet a standard component of iQgen. Before installing, please download it from our website.
Then simply unpack the .zip archive into your Eclipse/plugins directory. The unpacked directory structure is shown in the figure below.
Table of Contents
This guide is designed to help you getting started with iQgen, innoQ's model driven software generator. If you have no idea what Model Driven Architecture is, we suggest you spend some time to read up on the topic on the Object Management Group's (OMG) website: http://www.omg.org/mda/ For the impatient developer, here is a short summary taken from the OMG's site:
The MDA is a new way of writing specifications and developing applications, based on a platform-independent model (PIM). A complete MDA specification consists of a definitive platform-independent base UML model, plus one or more platform-specific models (PSM) and interface definition sets, each describing how the base model is implemented on a different middleware platform. A complete MDA application consists of a definitive PIM, plus one or more PSMs and complete implementations, one on each platform that the application developer decides to support.
MDA development focuses first on the functionality and behavior of a distributed application or system, undistorted by idiosyncrasies of the technology or technologies in which it will be implemented. MDA divorces implementation details from business functions. Thus, it is not necessary to repeat the process of modeling an application or system's functionality and behavior each time a new technology (e.g., XML/SOAP) comes along. Other architectures are generally tied to a particular technology. With MDA, functionality and behavior are modeled once and only once. Mapping from a PIM through a PSM to the supported MDA platforms will be implemented by tools, easing the task of supporting new or different technologies.
To put this into context: Actually MDA is a successor to the model driven generative approach which has been around since the early nineties. In the mid-nineties, this generative approach failed partly due to the fact that code generators often had problems re-generating and merging artifacts. But that was only one reason for the artifacts of the development process to become inconsistent. The divergence of artifacts was a big problem, and still is. It has to be addressed carefully with an appropriate process.
The novelty of MDA, which makes it so powerful and promising, is the fact that there are well defined middleware standards like J2EE and CORBA. They and MDA together enable us to separate modeling concerns on the conceptual level rather than on a project or enterprise level. This means that there is a new chance for all of us to achieve long term technology independence and protection of investments. As mentioned by the OMG, tools are needed to support this process.
iQgen is one of these tools. With iQgen you can map your platform-independent model (PIM) to a platform-specific model, i.e. a model specific to a platform like .NET or J2EE.
Not surprisingly, you need to create the PIM somehow. The easiest way to do this is to use a CASE tool. Just create a model with one of the supported case tools and export it as an XMI file.
Your platform independent model is transformed to a platform specific model by means of a transformation, which is defined as a set of code generation templates.
In iQgen, there is no explicit PSM other than the code of your generated system. Conceptually, you can think of iQgen creating the PSM in a transient form. We have found this approach to work extremely well, although we consider adding model-to-model transformation to a future version of iQgen.
Once you have a PIM and at least one set of templates, you can simply hit iQgen's generate button and your application will be generated for a given platform. How well this works depends on the quality of both the PIM and the templates.
In order to successfully work with iQgen you need to understand how to specify your transformation, i.e. how to write templates. But before we delve into template creation, you should first get a better understanding of how code generation with iQgen works. This will be covered in the next section of this tutorial.
To get some hands-on experience with iQgen we recommend to run the tutorial that comes with the iQgen distribution. You will find the templates in the directory samples/getting_started/tutorial_1/templates and the XML models in XMI format in directory samples/getting_started/tutorial_1/model.
The UML profile for Tutorial 1 is extremely simple - essentially, it doesn't use any stereotypes or tagged values at all.
Tutorial 1 uses the model depicted in the figure below. It will not result in a complete application, but in the end you will have source code which can be compiled and you will have obtained a deeper knowledge of how to develop templates.
To give you an overview of the templates in Tutorial 1, here's an overview table with some short comments.
Table 2.1. Files in Tutorial 1
| Directory | File | Comment |
|---|---|---|
| ./ | build.xml | Ant script for generation |
| model | Tutorial_1.xml | XMI v1.0 model file |
| model | Tutorial_1.mdl | Rational Rose model file |
| templates | main.jsp | Model element to template mapping |
| templates | interface.jsp | Simple example that demonstrates how to generate a Java interface |
| templates | class.jsp | More complex example that generates Java class files. Uses other templates like associations, attributes, and operations |
| templates | attributes.jsp | Used by class.jsp. Generates attribute declarations, getter and setter methods. |
| templates | operations.jsp | Used by class.jsp. Generates methods. |
| templates | associations.jsp | Used by class.jsp |
| templates | build.jsp | PostProcessTemplates example |
| templates | copyright.jsp | Copyright text |
| templates | drop_and_create.jsp | Simple SQL script |
| templates | params.jsp | Utility JSP that is included by other templates. |
| templates | utilities.jsp | Utility JSP that is included by other templates. |
In order to generate the files for the Tutorial 1 model, simply start iQgen and select the tutorial's model file. Then set both the target and template directory and start the generation. You will find the generated file in the output directory you chose. The next paragraph will guide you through the process step-by-step.
When you start iQgen you should see the screen below. This is the main screen. All settings necessary for generation can be found right there. The numbers (1-10) in the figure correspond to the 10 simple steps necessary for code generation.
Just follow these steps and you will generate some sample code (for this example we suggest that you have installed iQgen under c:\iQgen):
Project Root Path. Enter your project root path here: C:\iQgen\samples\getting_started\tutorial_1
Source Model File. Here you need to set the location of the model file: C:\iQgen\samples\getting_started\tutorial_1\model\tutorial_1.xml
Target Generation Path. This is where the generated files can be found after successful generation: C:\iQgen\samples\getting_started\tutorial_1\out
Template Path. Directory containing the templates: C:\iQgen\samples\getting_started\tutorial_1\templates
Master Template. Select your master template: main.jsp
Load Model. Now that all paths and files are set, you have to load model by clicking the toolbar button.
Generate. Start the generation by clicking the toolbar button.
Output. The output window should now contain the lines shown in the screen shot.
Technically the generation is now complete. The following two steps are entirely optional.
Open Generated File. Click on the tab Generated Files and double-click on one of the files. It will be opened in the editor.
New Transformation. Finally you can create a new transformation via . Just specify a location and a file name (e.g. tutorial_1).
Done. You have successfully created your first set of artifacts from the provided model file.
The GUI is not the only way you can use iQgen. You may also generate artifacts from the command line or from an Ant build file.
XMI, like many other standards, is unfortunately not a guarantee for interoperability. Different CASE tools export to XMI differently, and this can lead to interoperability problems. iQgen tries to minimize these by streamlining the differences by means of the MetaModelFacade API. Nevertheless, iQgen allows you to access everything that your CASE tool has exported. If you need to make sure that you can change CASE tools in the future, we strongly encourage you to use the MetaModelFacade as much as possible.
iQgen uses an embedded Java Server Pages (JSP) 1.1 engine to execute your templates. If you are familiar with JSP syntax, developing templates with iQgen should be a piece of cake. However, as not everybody can be fluent in JSP, we will give a short introduction.
A JSP's content is a mixture of literals, directives, declarations, scriptlets, and actions. Sun's JSP syntax card gives an excellent overview of which syntactic elements are legal in a JSP. The following paragraphs cover the most important of these elements. If you are familiar with JSP, you may skip this section and continue with how JSP are used in iQgen.
To understand the concept of JSP a little bit better it often helps to know that each JSP is compiled into a Java class. Like any other class this class has methods and fields. Not surprisingly you can also declare methods and fields in a JSP. This is done like this:
<%! declaration; [ declaration; ]+ ... %>
I.e. if you wanted to declare a method getDate() which returns the current date, you could write:
<%! public java.util.Date getDate() { return new java.util.Date(); } %>You might have noticed that instead of simply writing Date, we used the fully qualified classname java.util.Date. Of course this is very tedious, if you have to use classnames like com.great.company.with.a.very.long.name.util.MasterUtility. No one likes to write classnames like this. Therefore, each JSP can import packages. The mechanism is exactly the same as in Java - just the syntax is different:
<%@ page import="{package.class|package.*}, ... " %>Example:
<%@ page import="java.util.*,java.net.URL" %>
Ideally you place such a page directive at the top of your page. In addition to the packages you want to import, the page directive lets you specify a class you want to extend. As mentioned before, a JSP will be compiled into a special Java class. This class may inherit some of its behavior from a superclass. To specify this superclass, you may place a page directive with an extends attribute in your page:
<%@ page extends="package.class" %>
Example:
<%@ page extends="com.innoq.generator.jsp.JspBase" %>
You probably have guessed that you cannot simply subclass any class. Contrary to ordinary JSP engines, iQgen restricts you to extend com.innoq.generator.jsp.JspBase or any of its subclasses. This ensures that certain functionalities expected from iQgen are always available in your templates. If you do not specify a class you want to extend, iQgen will automatically use com.innoq.generator.jsp.JspBase as default class.
Of course declaring methods and inheriting functionality does not get us very far. At least it does not generate any output. Therefore we want to explore means of generating...
Everything you write in a JSP that isn't marked with special tags (usually starting with <% and ending with %>) will be copied to the output of your template literally. And everything means everything - in particular this rule applies also to whitespace such as tabs, spaces, and newlines.
Expressions provide you with a way of inserting the value of objects or primitives ( int, float, boolean, ...) into the output. In the case of primitives the value is printed, in the case of an object either null is printed or the result of the toString() method. The syntax is as follows:
<%= any kind of Java expression %>
Example:
<%= new java.util.Date() %>
This prints the current date. Of course you can also use other Java expression such as the conditional ? : operator, a method invocation, or any combination of valid expressions.
<%= i>100 ? "i is greater than 100" : "i is not greater than 100" %> <%=someObject.someMethod() %>
With the means we introduced so far, we cannot use control structures like loops or embed a great deal of logic in our templates - or at least not in a reasonable way. Scriptlets offer you a way to easily embed any valid Java code, you could otherwise write in a method, in your template. Note that you cannot declare methods here.
<% code fragment of one or more lines %>
And this is how you can write a loop with a scriptlet:
<%
// this is a comment in Java code
// first scriptlet
for (int i=0; i<100; i++) { %>
Number: <%=i%>
<%
// second scriptlet
} %> In the first scriptlet the block that shall be executed 100 times is opened with a curly brace; in the second scriptlet it is closed again. In between we placed a literal ( Number:) and an expression ( <%=i>). They will both be evaluated, i.e. printed, 100 times.
Please note that this might look very practical and simple, but is actually a maintenance nightmare. Often taglibs (we will talk about them later) do a much better job at encapsulating control structures like conditional execution ( if) or repeated execution ( for, while).
JSP are capable of including other files, which are statically compiled into your template and executed as if they have always been part of your template. Syntax:
<%@ include file="relativeURL" %>
This is often very useful, if you have a lengthy import section in all your JSP or a copyright notice that always stays the same. Simply include it, where you need it. Example:
<%@ include file="copyright.txt" %> <%@ include file="imports.jsp" %>
Please note that you can include files containing literals as well as scriptlets or any other element of a valid JSP.
Of course JSP aren't executed in a vacuum. To access your environment you can use a number of implicitly declared variables. Some of them are listed in the table below.
Table 2.2. Some of the implicit objects available in a JSP template
| Name | Type | Comment |
|---|---|---|
| request | javax.servlet.ServletRequest | The request from the generator. |
| response | javax.servlet.ServletResponse | The response to the generator. Not typically used by iQgen authors. |
| pageContext | javax.servlet.jsp.PageContext | You can store objects in this context. |
| out | javax.servlet.jsp.JspWriter | The Writer the output is written with. |
As mentioned above, taglibs provide a much cleaner way of encapsulating certain tasks or logic. In order to use a taglib, you first have to register it with the page you want to use it in. This can be done with the taglib directive. Syntax:
<%@ taglib uri="taglibURI" prefix="prefix" %>
iQgen comes with a default taglib with the URI iqgen. To use a custom taglib you need to place it in the taglibs directory. The uri refers to the name of the taglib Jar file without the .jar suffix. Once you have registered the taglib, you can use it with the prefix you chose in the taglib directive:
<tagPrefix:tagName attribute="value"+... /> <tagPrefix:tagName attribute="value"+... > ... </tagPrefix:tagName>
iQgen comes with a pre-built taglib, which we will be mentioned again later.
Since JSP aren't brand new anymore there are plenty of books and online tutorials around.
iQgen uses JSP for two purposes:
the mapping of model elements to templates
the templates themselves.
As you know, a model consists of different model elements such as classes, interfaces, associations, diagrams and so forth. Usually a single model element cannot be mapped one to one to a generated file. Instead often a single model element leads to the generation of multiple files, e.g. a SQL script, a configuration file, a deployment descriptor and a couple of classes. Therefore you need to specify which files should be generated for a given model element. To allow you to specify this in a very flexible and powerful way, this is done with a special JSP - the file main.jsp - a.k.a. the master template.
There are three things you need to do, to write your own main.jsp:
Extend the class com.innoq.generator.jsp.JspMain
Implement the method public String[] getTemplates(MBase)
Implement the method public String getName()
So the most basic main.jsp looks like this:
<%@ page extends="com.innoq.generator.jsp.JspMain"
import="ru.novosoft.uml.MBase" %>
<%!
/**
* For performance reasons this array is declared as static
* final and can be reused for every invocation of getTemplates.
*/
private static final String[] TEMPLATE = {"template.jsp"};
/**
* Returns the names of the templates to execute for a specific
* model element.
*
* @param element The model element to return the template names for
* @return Array of template names for a element
*/
public String[] getTemplates(MBase element) {
return TEMPLATE;
}
/**
* Name of this modelelement-template mapping.
*/
public String getName() {
return "My first main.jsp";
}
%> This main.jsp would return the name of the template template.jsp for every model element. Of course this only makes sense in the most simple case. You cannot to generate a SQL script and a Java class file for a persistent object with a single template. Our next example shows a slightly more complex, but a lot more realistic mapping:
<%@ page extends="com.innoq.generator.jsp.JspMain"
import="ru.novosoft.uml.MBase" %>
<%!
private static final String[] PERSISTENT = {"class.jsp", "drop_and_create.jsp"};
private static final String[] INTERFACE = {"interface.jsp"};
private static final String[] DEFAULT = {"class.jsp"};
public String[] getTemplates(MBase element) {
String s = getMetaModel().getStereotype(element);
String name = getMetaModel().getName(element);
if ("Persistent".equals(s)) {
return PERSISTENT;
} else if (getMetaModel().isInterface(element)) {
return INTERFACE;
} else {
return DEFAULT;
}
}
public String getName() {
return "My second main.jsp";
}
%> Instead of always returning the same template name for every model element, we return PERSISTENT for all model elements marked with the stereotype Persistent, INTERFACE for all interfaces and DEFAULT for all other madel elements. This allows us to generate SQL scripts with the template drop_and_create.jsp and class files with class.jsp for all persistent madel elements. All other elements lead to the generation to either an interface or a class file.
Let's look how this is done in detail. In every iQgen JSP you can obtain access to the model by invoking the method getMetaModel(). This will return an object of the type com.innoq.generator.metamodel.IMetaModelFacade, which can help you inspecting the current modelelement. The three methods we use in this example are getStereotype(MBase), getName(MBase), and isInterface(MBase). Additionally the metamodel offers many more methods to obtain detailed information about the current element. All methods are covered in the API reference section.
So far we can invoke templates for and with specific model elements. Often some templates need only be invoked once per model and even without a specific model element. Such cases can be covered with the method public String[] getPostprocessTemplates(). Just overwrite this method in your main.jsp to provide the names of all templates that should be executed after all model element-specific templates have been executed:
<%@ page extends="com.innoq.generator.jsp.JspMain"
import="ru.novosoft.uml.MBase" %>
<%! [...]
private static final String[] POST = {"build.jsp"};
public String[] getPostprocessTemplates() {
return POST;
}
%> Our example always returns the name of the template build.jsp which generates an XML file that can be used as an Ant build script. Another useful application of this feature is a template for deployment descriptors.
There are several hook methods you can overwrite to control your generation process. The following sequence diagram should help you to get an overview about the calling order. MyJspMain means your JspMain specialization. The writeToFile method should be used very carefully and at the end of this method you must call super.writeToFile(filename, inoutstream).

Figure 1: JspMain Sequence
For a complete description of JspMain 's API, take a look at the API reference section page.
The second use for JSP in iQgen is to write the actual templates.
Probably the most important methods already defined in iQgen templates are getElement() and getMetaModel(). getElement() allows you to access the model element this template was invoked for. getMetaModel() grants you access to the model - just like in main.jsp. Additionally there are some other methods already defined, mainly dealing with how to compute the name for the file to generate and other path related tasks.
As an example we will take a look at a template for generating Java interfaces.
<%@ page import="ru.novosoft.uml.MBase,java.util.Collection,java.util.Iterator"
extends="com.innoq.generator.jsp.JspBase" %>
<%@ taglib uri="iqgen" prefix="iqgen" %>
<%! private String getClassname() {
return getMetaModel().getName(getElement());
}
private String getExtendsString() {
Collection superclasses = getMetaModel().getAllSuperclasses(getElement());
if (superclasses.isEmpty())
return "";
StringBuffer sb = new StringBuffer(" extends ");
for (Iterator i=superclasses.iterator(); i.hasNext();) {
sb.append(getMetaModel().getName((MBase)i.next()));
if (i.hasNext())
sb.append(", ");
}
return sb.toString();
}
public String getPrefix(char pSeparator, MBase m) {
return "com"+pSeparator+"innoq"+pSeparator+"tutorial_1"+pSeparator;
}
%>
package <%=getPath()%>;
<iqgen:import prefix="<%=getPrefix()%>" collectiontype="java.util.List"/>
/**
* Interface <%=getClassname()%>
*/
public interface <%=getClassname()%><%=getExtendsString()%> {
[...]
} This excerpt from the complete template generates the package statement, import statements, and the interface declaration complete with extend clause. In the first part we register the taglib iqgen and declare three methods. Let's look at the first of these three methods.
getClassname() is a simple helper method that returns the name of the interface. To obtain the model element this template is executed for we simply call the getElement() method. This method is automatically declared in every template. Using the metamodel, we find out the name of the particular element. In the case of an interface this is also the classname.
getExtendsString() works similar to getClassname(). Through the metamodel we obtain a collection of the interface's the superclasses. If this collection is empty, the method simply returns an empty string. Otherwise the names of all superclasses are appended to a StringBuffer which starts with extends.
getPrefix() is already declared in the superclass JspBase. In its default implementation it simply returns an empty string. In our example it is overwritten to return the package name. Note that the package separator is provided as a parameter. This is necessary, because this method is called for computing the filename, too. By overwriting getPrefix() in the given way we achieve that the method getPath() automatically returns the right package name and the generated file is written into the right directory, i.e. [OUTPUT_PATH]/com/innoq/tutorial_1/.
Which file the output is written to, is determined by the JspBase method getFilename(). By default this method is implemented like this:
public String getFilename() {
return getDirectory() + File.separator
+ getPath(File.separatorChar,
getElement())
+ File.separator + getName()
+ "." + getFileExtension();
}
getPath() in turn is implemented like this:
public String getPath(char pSeparator, MBase m) {
return getPrefix(pSeparator, m)
+ getMetaModel.getNamespaceName(m, pSeparator)
+ getPostfix(pSeparator, m);
}
You can also find a complete description of JspBase's API, here in the API reference section.
So far we provided methods to easily access the classname, write the extends clause, and compute the package name. Before we write the whole interface with all its methods, it makes sense to import the classes we use in the method's signatures. Alternatively we could simply always use fully qualified classnames - but who would do this in real code? And shouldn't the quality of generated code be at least the same as the quality of handwritten code?
To gather all the import-classes we need to look at every method parameter, every superclass, every interface, every association and so forth. This is rather tedious, repetitive, and error prone work and therefore a perfect candidate for a custom tag. Custom tags allow you to encapsulate tasks like computing import tags and easily re-use their functionality. The import tag provided in the standard iQgen tag library provides the functionality to automatically generate all necessary import statements for the current class or interface. In order to keep the imports in sync with other generated files you can specify a prefix for all imports. Also, if your model contains associations with undefined multiplicity, you may specify a collectiontype that will always be included in your import statements:
<iqgen:import prefix="<%=getPrefix()%>" collectiontype="java.util.List"/>
Let's finish our interface-example. We still need to generate the method section. Here's how it works:
<%@ page import="ru.novosoft.uml.MBase,java.util.Collection,java.util.Iterator"
extends="com.innoq.generator.jsp.JspBase" %>
<%@ taglib uri="iqgen" prefix="iqgen" %>
[...]
/**
* Interface <%=getClassname()%>
*/
public interface <%=getClassname()%><%=getExtendsString()%> {
<iqgen:foreach group="<%=getMetaModel().getOperations(getElement())%>" item="method">
<%
String methodName = getMetaModel().getName(method);
Object retType = getMetaModel().getReturnType(method);
String retTypeName = getMetaModel().getReturnTypeName(method);
String parList = getMetaModel().getParameterListAsString(method);
%>
/**
* Method <%=methodName%>
* <iqgen:foreach group="<%=getMetaModel().getParameterList(method)%>" item="parameter">
* @param <%=getMetaModel().getName(parameter)%> <%=getMetaModel().getDocumentation(parameter)%></iqgen:foreach>
<iqgen:if expr="<%=retType!=null%>">
* @return <%=retTypeName%>
</iqgen:if>
*/
public <%=retTypeName%> <%=methodName%>(<%=parList%>) <%=getMetaModel().getExceptionListAsString(method)%>;
</iqgen:foreach>
} Basically we just have to iterate over all the declared methods and print out their documentation and signature. In our example this is done using the built-in foreach tag. As attribute we define a group of elements to iterate over. This is done with the JSP expression <%=getMetaModel().getOperations(getElement())%>. Additionally we need to specify a variable in which the items of the group are to be placed during the iteration. In our case this is method. So the whole iteration looks like this:
<iqgen:foreach group="<%=getMetaModel().getOperations(getElement())%>" item="method"> [...] </iqgen:foreach>
The rest is pretty much straight forward. First we declare a number of variables like methodName and retTypeName for easier access to the method model element. Then we print the documentation, which includes another foreach iteration over the method's parameters. Finally we print the method's signature. That's it.
Of course generating interfaces is pretty simple, because usually you don't need to add custom code.
Generated code usually isn't perfect. Not all information is contained in model and templates, some needs to be added manually. With simple code generators the manual changes are lost during re-generation. iQgen solves this problem with usercode blocks.
During each generation the output directory is checked for files from earlier runs. If these files exist, the contents of protected sections of these files are inserted into the newly generated files. These special sections are marked as usercode blocks. Here is an example for adding custom imports to a Java file:
[...] <%@ taglib uri="iqgen" prefix="iqgen" %> <iqgen:usercode id="imports"> // your own imports </iqgen:usercode> <iqgen:import prefix="<%=getPrefix()%>" collectiontype="java.util.Collection"/> [...]
To use the usercode tag you have to register the iqgen taglib. Once this is done, you may mark a section of the template with the tag. Make sure that you specify a unique id attribute in the opening tag. This ensures that the right piece of code is merged into this section.
In the generated code the section will look like this:
[...] //==> Begin Protected Area imports // your own imports //==> End Protected Area imports [...]
Never modify the //==> [...] Protected Area [...] lines!
Alternatively to the id attribute you can also set a model element as attribute element:
[...] <%@ taglib uri="iqgen" prefix="iqgen" %> <iqgen:usercode element="<%=getElement()%>"> // your own code for the current modelelement </iqgen:usercode> [...]
id and element are mutually exclusive.
This chapter will show you how to use your own Tag Libraries (taglibs) with iQgen. We will use a Tag Library to format date and time data as an example. iQGen supports JSP 1.1 Tag Libraries. If you want to know how to program tag libraries, please consult the JSP 1.1 specification or any JSP tutorial.
Tag Libraries enable you to write simpler templates. Basically they allow you to move complicated logic from your templates into custom tags. Templates often are much easier to read, understand, and maintain, when Tag Libraries are used. They can be structured more clearly. As a consequence, you should use Tag Libraries whenever you feel that your templates are getting too complicated and unreadable.
Basically you can deploy every JSP 1.1 Tag Library into iQgen. The library has to meet certain criteria, though: First of all, the Tag Library has to be packed into a jar file and this jar file must contain a Tag Library Descriptor (TLD). The TLD is a file that describes the tags contained in the Tag Library. It is best - but not required - to be placed in the META-INF directory for compatibility with some IDEs e.g. IntelliJ IDEA™. The JSP engine uses this file to get all the necessary information to process the Tag Library.
Now the Tag Library can be deployed. You have to copy it into a subdirectory taglibs in the home directory of your iQgen installation (e.g. C:\Programme\iQgen). If the directory does not exist, you have to create it. Now this Tag Library can be used in all iQgen templates.
If the deployed Tag Library uses any libraries (jar files), they have to be put into a subdirectory of the taglibs directory called lib.
In case you want to use the Ant interface of iQgen a special issue arises. The jar file of the Tag Library then has to be placed in a taglibs directory in the lib directory of your Ant installation. The reason for this is that iQgen searches the jars of Tag Libraries relatively to the iQgen jar file. This jar file - in the Ant mode - resides in the lib directory of Ant.
If you have completed all the steps explained in the previous paragraph, you can use your Tag Libraries in your templates. Here is some example code which shows you how to access a Tag Library:
[...] <%@taglib uri="your_taglib" prefix="your_prefix" %> [...] <your_prefix:your_tag your_attr1="a" your_attr2="b"> In case of a body tag there can be something in here </your_prefix:your_tag> [...]The taglib directive ( <%@taglib ... %>) makes a Tag Library available within a template. To do this the URI of the Tag Library and the prefix must be specified as attributes of the directive. The URI of a Tag Library in the taglibs directory is the filename of the jar file of the Tag Library without .jar It is used to locate the Tag Library. Now you can use the Tag Library identifying it using the prefix, you have specified (i.e. <your_prefix:your_tag ... >).
The iQgen Sample Tag Library is included in the iQgen distribution, you can find it in the directory samples/getting_started/taglib_tutorial in your iQgen directory.
The Java class com.innoq.generator.samples.taglibs.SampleTag implements the date and time formating feature. The following TLD is used:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>iqgen-taglib-sample</shortname>
<info>Sample which shows you how to use the taglibs</info>
<tag>
<name>date</name>
<tagclass>com.innoq.generator.samples.taglibs.SampleTag</tagclass>
<info>Formats Dates</info>
<attribute>
<name>time</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>date</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>format</name>
<required>false</required>
</attribute>
</tag>
</taglib>The Tag Library contains only one tag, which
is called date. The attributes are
time, date and
format. The allowed values for the attribute
format are date,
time and datetime,
which is the default. If none of these values is given, the default
will be used.The tutorial includes an Ant build file ( build.xml), which can be used to compile, assemble and install the Tag Library. Just have to call the target install, respectively install-for-ant in order to make this Tag Library available for the GUI or the Ant interface of iQgen.
The important parts of the build file to illustrate what is done to deploy the Tag Library are:
[...]
<target name="dist" depends="compile">
<copy file="${basedir}/taglib.tld" todir="${classes.dir}/META-INF"/>
<jar jarfile="${jar.file}" basedir="${classes.dir}"/>
</target>
<target name="install" depends="dist">
<mkdir dir="${generator.dir}/taglibs"/>
<copy file="${jar.file}" todir="${generator.dir}/taglibs"/>
</target>
<target name="install-for-ant" depends="dist">
<mkdir dir="${ant.home}/lib/taglibs"/>
<copy file="${jar.file}" todir="${ant.home}/lib/taglibs"/>
</target>
[...]As you can see the taglib.tld is
copied into the META-INF directory of the jar file
in order to build the jar. This ensures the correct structure of the
jar file. The install and
install-for-ant targets then copy the jar
file into the correct directory.After having successfully installed the Tag Library there will be a taglibsample.jar in the taglibs directory of your iQgen installation. Now you can use the taglibsample Tag Library in your templates:
[...] <%@taglib uri="taglibsample" prefix="datelib" %> [...] <datelib:date format="date"/> <datelib:date time="<%=System.currentTimeMillis() + 3600000%>" format="datetime"/> [...]
This will result in the following output:
09.08.2002 09.08.2002 11:06:43
Transformation Properties represent a set of properties which can be accessed from within your templates. This enables you to add some flexibility to your templates, as you can change the result of the generation without changing the templates themselves.
This text refers to a sample which is included in the iQgen installation. The templates are in the directory samples/getting_started/properties_sample/templates. It will generate a HTML report on any model. You can use for instance the model of Tutorial 1.
To use Transformation Properties from the GUI just create a properties file and place it into the project directory of the transformation you want to use. When the transformation is opened this file will appear in the Transformation Properties combo box in the GUI. Just select it and the properties are available in the templates.
In order to use Transformation Properties on the command line set the -transformationProperties option.
Example:
iqgen.bat "-transform=tutorial_1 -nobackup -transformationProperties=transformation.properties"
In Ant use the transformationProperties attribute of the Generate Task.
If Transformation Properties are set they will be loaded when generation has started. They can be accessed in the templates via methods of the iQgen JSP base class, i.e. any iQgen JSP.
Table 2.3. Methods for accessing Transformation Properties
| Method | Description |
|---|---|
| public final String getProperty(String pKey) | Returns a property with the given key pKey |
| public final String getProperty(String pKey, String pDefault) | Returns a property with the given key pKey if defined, default pDefault otherwise |
| public final Properties getProperties() | Returns the whole set of Transformation Properties |
It is also possible to add new properties to the Transformation Properties or to change the value of an existing property. The following methods can be used:
Table 2.4. Methods for manipulating Transformation Properties
| Method | Description |
|---|---|
| public final void setProperty(String pKey, String pValue) | Sets a property with given key and value |
| public final void setProperties(Properties pProps) | Replaces Transformation Properties with pProps |
| public final void addProperties(Properties pProps) | Adds the given properties to the Transformation Properties |
The following example is a set of templates which generate an HTML report for a model. A Transformation Property (sort) is used to decide whether the lists of classes, attributes or methods will be sorted:
[...]
<TABLE cellpadding="3" cellspacing="3" border="1">
<TR bgcolor="#98AEB7" align="center">
<TD>Class Name</TD>
</TR>
<% List list = new ArrayList(getAttributeList("CLASS_KEY")); %>
<iqgen:if expr="<%=\"true\".equals(getProperty(\"sort\"))%>">
<% Collections.sort(list, myComparatorInstance); %>
</iqgen:if>
<iqgen:foreach group="<%=list%>" item="item" type="ru.novosoft.uml.MBase">
<TR bgcolor="#FFFFFF" align="right">
<TD>
<a href="<%=getMetaModel().getPath(item)%>/<%=getMetaModel().getName(item)%>.html">
<%=getMetaModel().getName(item)%>
</a>
</TD>
</TR>
</iqgen:foreach>
</TABLE>
[...] To sort the lists all you need is the following
property file: sort=true
The following example demonstrates how to validate a model exported by your CASE tool. You can find the templates and the model for this example at: ../samples/getting_started/validation. The templates use the Model Validation feature and will generate an HTML report for the underlying UML model.
Here is a complete list of files of this example:
Table 2.5. Files for the Model Validation example
| Directory | File | Comment |
|---|---|---|
| ./ | validation.iqp | Project file for this example |
| ./ | build.xml | Ant Script for generation |
| model | valid_model.xmi | Valid model XMI file |
| model | invalid_model.xmi | Invalid model XMI file |
| model | model.zargo | ArgoUML model file |
| templates | main.jsp | Model element to template mapping, Validation |
| templates | report.jsp | Creates the HTML output |
The UML profile in this case is very simple. What we want to show is how to use model validation. Model validation answers the question: Does the UML model satisfy the UML profile?
The UML profile looks like this:
only Entity, Process and Enum are allowed stereotypes
every navigable association must be named with a rolename
a usage dependency of processes to classes shows implicitly a get method of the used class
First let us start with the invalid model. It looks as follows:
You can find the invalid model as XMI file in the folder validation/model. Please open the transformation samples/getting_started/validation/validation.iqp. When you start generation and change to the validation page you should see that the model has three validation errors:
| Unknown stereotype: | Class: User |
| Association [Document -> Version] is navigable but missing rolename. | Association: |
| Association [Version -> Label] is navigable but missing rolename. | Association: |
The Unknown stereotype error is a warning, the missing rolename exceptions are errors (different images in table!). If we used a fatal error the execution would have stopped. In our example the validation violation status are arbitrarily.
The next step is that we fix the model, remove the validation violations and re-generate. The correct model looks as follows:
You can load the model from the XMI file valid_model.xmi. Now re-generating will not produce errors anymore!
You can find both templates main.jsp and report.jsp in the templates directory of this example. Most of the used methods are explained in further examples so we can concentrate on the validation method (see main.jsp):
[...]
private static final List STEREOTYPES = Arrays.asList(
new String[] {"Entity", "Process", "Enum"}
);
[...]
public boolean canBeGenerated(MBase pElement) {
return super.canBeGenerated(pElement)
|| getMetaModel().isAssociation(pElement);
}
public ValidationMessage isValid(MBase pElement) {
String s = getMetaModel().getStereotype(pElement);
// valid stereotypes
if (getMetaModel().isClass(pElement) && !STEREOTYPES.contains(s)) {
return new ValidationMessage(ValidationMessage.WARN, "Unknown stereotype: " + s);
}
// navigable associations do have a rolename?
if (getMetaModel().isAssociation(pElement)) {
for (Iterator it = ((MAssociation)pElement).getConnections().iterator(); it.hasNext(); ) {
MAssociationEnd lAssocEnd = (MAssociationEnd)getMetaModel().getOppositeEnd((MBase)it.next());
if (getMetaModel().isNavigable(lAssocEnd)
&& getMetaModel().getName(lAssocEnd).length() == 0) {
StringBuffer sb = new StringBuffer();
sb.append("Association [");
sb.append(getMetaModel().getTypeName(lAssocEnd.getOppositeEnd()));
sb.append(" -> ");
sb.append(getMetaModel().getTypeName(lAssocEnd));
sb.append("] is navigable but lacks a rolename.");
return new ValidationMessage(ValidationMessage.ERROR, sb.toString());
}
}
}
return new ValidationMessage(ValidationMessage.OK, "No error found!");
}
[...] The model validation happens programmatically. For validation purpose you can use the hook method isValid. This method is called for every model element that is to be processed during generation. You can control which model element leads to the generation of an artifact by overwriting the method canBeGenerated. By default only classes and interfaces are generated. In our example we have added associations, because the UML profile demands a validation of associations, too. Our intention is to check navigable associations and their rolenames.
In our custom isValid method we check whether all classes have a valid stereotype - if not we return a ValidationMessage of type ValidationMessage.WARN. Then we check whether all navigable associations have rolenames.
To do this we check, if the element is an association, then we take a look at the association's ends. Every association consists of two association ends which you can get by calling the method getConnections. Finally we check the UML profile constraint ("Association is navigable and has a rolename?!?"). If this constraint is violated we return a ValidationMessage of type ValidationMessage.ERROR.
If the element is no association in the first place, there is nothing to test form, so we simply return a ValidationMessage of type ValidationMessage.OK.
In a real world application the model validation would be more complex. Therefore we recommend to handle it in a separate class. Our experience is that it is also an incremental process to make your model validation more and more detailed. In a way, this is comparable with unit testing your model.
Dynamic classloading allows you to change certain classes while the iQgen GUI is running. Maybe you like Java helper classes do some work for your generation progress. Typically these classes are not bug free, so you have to fix them and test again. Dynamic classloading relieves you from having to restart iQgen every time you make a tiny change to a class. The only thing you have to do is to recompile your helper classes and start generation again.
Of course iQgen has to know where to find these classes. The properties enables you to define a directory from which iQgen will reload the classes for every generation process! (see Properties/Dirs)
The example itself generates one IDL file for the model.
Here is a complete list of files of this example:
| Directory | File | Comment |
|---|---|---|
| ./ | classloading.iqp | Project file for this example |
| ./ | build.xml | Ant Script for Generation |
| model | model.xmi | Model XMI file |
| model | model.zargo | ArgoUML model file |
| templates | main.jsp | Model element to template mapping |
| templates | idl.jsp | Creates the IDL output |
| classes/com/innoq/iqgen/classloadingtemplates | AttributeList.java | Container for attributes and associations |
| classes/com/innoq/iqgen/classloadingtemplates | Attribute.java | Attribute Wrapper |
| classes/com/innoq/iqgen/classloadingtemplates | Sequence.java | Association Wrapper |
The UML profile looks like this:
only Struct and Interface are allowed as stereotypes
the stereotype Struct maps to IDL struct
the stereotype Interface maps to IDL interface
every navigable association must be named with a rolename
The model describes a simple message board. The interface to the message board is the board itself. You are able to login, logout, add a message (addMessage) and add a reply to a message (addReply). Entities are User and Message. Every Message can have multiple replies which are also messages. In addition it is possible to add an Attachment to every Message.
This example does not produce a complete runnable application it only generates the compilable IDL for the model.
First of all: If you try to verify the generated IDL file you have to download an IDL compiler. The JDK IDL compiler idlj.exe does not support forward declarations, which are required for this example.
In structs we have to list all attributes and navigable associations. For this purpose we write a helper class AttributeList. Its init method iterates over all attributes and associations. For an attribute and an association with multiplicity one an Attribute will be created and for an association with multiplicity many a Sequence will be created. In order to take advantage of the dynamic reloading feature for the helper class, we place it in the classes directory.
Finally we are able to iterate over the resulting collection in idl.jsp:
[...]
struct <%=getMetaModel().getName(_struct)%> {
<iqgen:foreach group="<%=new AttributeList(getMetaModel(),_struct).getElements()%>" item="_attribute"
type="com.innoq.iqgen.classloading.Attribute">
<%=getProperty(_attribute.getTypeName(),_attribute.getTypeName())%> <%=_attribute.getName()%>;
</iqgen:foreach>
}; // <%=getMetaModel().getName(_struct)%>
[...] Open the project file /samples/getting_started/classloading/classloading.iqp and load the model. Set the Properties/Dirs/User Classes to C:\iqgen\samples\getting_started\classloading\classes (or where else your sample is located!). Press the button.
A single file should have been generated. Try to make an IDL compilation of this file (maybe use JacORB ). It will lead to the following exception:
$ ./idl.bat Classloading.idl Error in Classloading.idl, line:42(13): Declarator attachment already defined in scope. Attachment Can't recover from previous error(s), giving up. : parse error: null
The problem is that the type Attachment is equal to the attribute name attachment!
How do we solve this problem?
We can change the getName method in com.innoq.iqgen.classloading.Attribute to:
public class Attribute {
[...]
public String getName() {
//old : return metamodel.getName(clazz);
return "m" + StringHelper.fu(metamodel.getName(clazz));
}
[...]
} Just recompile the Attribute class and regenerate the model - now the IDL compilation should work just fine!
In this example we will show how to use activity diagrams to connect some HTML pages and simulate a simple screenflow. The content of the HTML pages is added as HTML to the modelelement documentation which we use to generate some visual content.
Here is a complete list of files of this example:
| Directory | File | Comment |
|---|---|---|
| ./ | activity.iqp | Project file for this example |
| ./ | build.xml | Ant Script for Generation |
| model | activity.xmi | Model XMI file |
| model | activity.zargo | ArgoUML model file |
| templates | main.jsp | Model element to template mapping |
| templates | form.jsp | Creates a HTML form |
| templates | index.jsp | Creates a HTML index site |
Table of Contents
As with any tool, code generation and MDA is not a silver bullet. The key to successfully applying it to your project is to decide when this makes sense, and when it doesn't.
The following list includes the main indicators that your project might benefit from using a generative approach:
You have few business model elements, such as entities and processes, but a complicated infrastructure
You are using a technology that requires you to specify information in multiple places, yet maintain consistency (such as J2EE)
There is a need to isolate technical changes from changes in business requirements
There are also some indicators that a generative approach might not be the best tool for the job:
The project's focus is largely on algorithms, not largely static structure
You are building a low-level component, such as an I/O library
Your project is trivial and small
As with any recommendation, these guidelines are not intended to be applied without careful consideration. In general, most developers start building a prototype, and while doing so, recognize repetitive elements. This is generally the best way to find out whether you should use a generative approach in your project.
Once you have decided to use a generative approach in your development effort, it is a good idea to apply some architectural guidelines as to how to use it:
In general, you should try to meet the goal that all of the generated code must be at least as good as if it had been written manually. While not always possible, the idea of this goal is to avoid using code generation to circumvent problems with the underlying architecture and frameworks.
While code generation can sometimes improve performance, you need to be careful to avoid the dreaded “code bloat” symptom. Since generating code is so easy, you might find yourself with a million lines of code, where a lot of them are basically just identical, with only minor changes. Your underlying platform will often allow you to solve these problems by building libraries or frameworks. Use this approach, and augment it with code generation where your platform does not provide the needed means.
A well-known, and in our opinion, false assertion about code generation is, that it is a sign of a bad design to need something like this at all. There are, of course, cases where this is true. Most of the time, though, you need to be concerned about the division of your solutions into “generic” and “generative”, and there is most definitely no single best strategy here.
Consider, for example, mapping objects, their relations, and their associations, to code. One way to address this is to statically type your classes according to your model - have a get and set method for your attributes, a Java class for each model class, use e.g. java.util.Vector to contain associated objects. If you want to do this, and have a model that exceeds trivial complexity, a generative approach - i.e., using iQgen - is a perfect match.
On the other hand, you could also define a class called ApplicationObject with a java.util.HashMap to hold the attributes, keyed by their name. You could then change your business model (to a certain degree) without touching your code, too.
Which of these solutions is better? Clearly, there is no simple answer to this question, since it depends very much on your specific requirements. Quite often, a generative approach will improve performance and make code easier to read, since it is a lot more explicit than the generic solution. Generic solutions work at compile time, though, so sometimes they might be too inflexible for a given problem. Generating code can also significantly enhance your code base, which might hurt both performance at run time and turn-around cycles at development time. Quite often, a thin veneer that is generated at compile time and wraps the generic object structure is a possible solution.
In summary, there can be no clear, universal preference to either solution. Each project requires careful consideration of the requirements at hand, and to find the right balance requires a skilled software architect.
Designing a UML profile is a technically simple task, but should be done with great care nonetheless. Essentially, the UML profile for your project is just a set of possible stereotypes and tagged values that model elements can be annotated with. Their role, though, is very important, since they define the language you can work with as you model your domain.
You should strive to enable the creation of models that are simple enough to be understood, yet formal enough to enable code generation. In your iQgen templates, you can use this information to map model constructs to system artifacts. Because of this, having a large set of stereotypes and tagged values to finely control what kind of output to generate makes building templates easy, but burdens you (or whoever creates the model) with having to decide which element to chose for a given purpose.
From applying an MDA approach in a significant number of projects, our experience is that it's best to err on the side of too few stereotypes and tagged values and accept having to write more complicated templates. While this will increase the effort in setting up the infrastructure, templates can almost always be changed easier than a complex model.
It's also a good idea not to clutter your UML profile with low-level, technical details. This cannot be avoided completely. Still, it makes sense to e.g. not introduce a stereotype such as “EntityBean”, but rather opt for “Entity” - although you might consider a J2EE Entity Bean to be the best match in a given scenario, it should be possible to change this to some other mechanism (such as a non-J2EE persistence framework) without having to modify the model. Of course the name does not have any inherent meaning for iQgen, so it would be possible to generate, say, a C# class from a model element stereotyped with “MessageDrivenBean”, but this clearly does not make things any clearer.
iQgen follows a strict forward engineering approach, as opposed to other well known strategies such as reverse engineering or round-trip engineering. What this means for you is that you need to be careful to make any changes in the appropriate place - either in the model or inside the protected areas in your generated artifacts. A failure to do so will result in your code being overwritten unintentionally, resulting in code loss. To address this, your development process should be adjusted to match the generative approach to software development.
It's tempting to view this as a disadvantage, and require that every artifact in the system should be modifiable with whatever tool is best suited to the purpose. But the generation of multiple artifacts from a simpler, central source element raises productivity so much that you will soon get used to it and appreciate the benefits. An obvious analogy to the classical compile step can be made, and after all, you would not expect to be able to modify the machine (or VM) code emitted by a language compiler.
The first step to take when introducing a generative approach is to embed the code generation process into your processing chain. In general, this means that you should generate code from within your build scripts. The iQgen Ant integration allows you to call iQgen from within your Ant scripts. If you prefer make or some other build management tool, you can use the command line tools.
As with other software artifacts, you should take care to put your source model under configuration management control. Depending on your CASE tool of choice, you can either version the model file itself or only the XMI export. While the first choice is preferable, some tools don't offer this possibility - most notably those that are based on some centralized repository. They do, however, usually offer some built-in versioning mechanism instead.
As a result, your build cycle will roughly resemble the followi