HOME
UNTERNEHMEN
LEISTUNGEN
PRODUKTE
PROJEKTE
IQGEN
NEWS
KONTAKT
iQgen News
About iQgen
Whitepaper
Prerequisites
Download
Pricing & Licence
Services
Performance
User's Guide
Getting Started
FAQ
Resources

Getting Started

[Previous] [Overview] [Next]

JSP in Templates Part I

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 modelelement 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 decalaration 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 similiar 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 packagename and the generated file is written in 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, right here.

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, repetetive, 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 assiciations 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"/>

We now have the skeleton for our generated interface class. What's still missing are methods. We'll take a look at them in the next section.

Copyright © 2001-2003 innoQ. Alle Rechte vorbehalten. Rechtliche Hinweise