Generator Development Walkthrough

this is a developing generator development guide

Preparing your Development Environment

Get the JARs from P4

Add the JARs to your CLASSPATH

Programming a Generator

Generators have to be derived from the Generator class from package de.tuhh.sts.cocoma.compiler.generators and have to provide a public constructor taking one string-valued argument. Apart from that there is no general rule how to program a generator. Still, this page will point you to the basic setup of a generator.

package ... ;

...

public class SomeGenerator
    extends Generator
{

    ...

    /**
     * Constructor as required by the compiler framework.
     */
    public APIGenerator () {

    }// constructor

    ...

}// class SomeGenerator

The most important function of a generator is generate(). When this method is invoked, a generator performs its actual task. Basically, the generate() method of generators often looks like the following:

package ... ;

import de.tuhh.sts.cocoma.Symboltable ;
import de.tuhh.sts.cocoma.generators.Generator ;
import de.tuhh.sts.cocoma.im.AssetClass ;
import de.tuhh.sts.cocoma.im.Attribute ;
import de.tuhh.sts.cocoma.im.IntermediateModel ;
import de.tuhh.sts.codegen.java.JavaClass ;
import de.tuhh.sts.codegen.java.JavaField ;
import java.io.FileWriter ;

public class SomeGenerator
    extends Generator
{

    ...

    /**
     * Constructor as required by compiler.
     */
    public APIGenerator () {

    }// constructor

    ...

    public SymbolTable generate (IntermediateModel im, ...)
        throws GeneratorException
    {

        // create the symbol table to return as the result of a generator run
        // (let SomeSymbolTable be some concrete symbol table class)
        SomeSymbolTable symTab = new SomeSymbolTable () ;

        AssetClass [] classes = im.getClasses () ;
        for (int i = 0, l = classes.length ; i < l ; i++) {

            AssetClass cls = classes [i] ;

            // do something with "cls"
            // e.g., create a Java class (let "javaClassName" be a method defined in this class):
            JavaClass jcls = new JavaClass (..., javaClassName (cls.getName ()), ...) ;
            symTab.putClass (cls, jcls) ;

            // next, handle the attributes (or only one kind of attributes, or all members)
            Attribute [] attribs = cls.getAttributes () ;
            // Characteristic [] characteristics = cls.getCharacteristics () ;
            // Relationship [] relationships = cls.getRelationships () ;
            // Member [] members = cls.getMembers () ;
            // Constraint [] constraint = cls.getConstraints () ;
            for (int j = 0, k = attribs.length ; j < k ; j++) {

                Attribute attrib = attribs [j] ;

                // do something with "attrib"
                // e.g., add a field to "jcls" (let "javaAttributeName" be a method defined in this class):
                JavaField f = new JavaField (..., javaAttributeName (attrib.getName ()), ...) ;
                jcls.addField (f) ;
                symTab.putField (attrib, f) ;

            }// for j

            ...

            // write result file
            try {
                FileWriter fw = new FileWriter (jcls.getName () + ".java") ;
                fw.write (jcls.toString () ;
                fw.close () ;
            }
            catch (IOException exc) {
                throw new GeneratorException ("While writing Java source code file: ", exc) ;
            }

        }// for i

        ...

        // return symbol table
        return symTab ;

    }// generate

}// class SomeGenerator

The lines shown in red are just examples of what could be done while generation. Here, Java code is generated using the Java code generation toolkit.

Other methods that have to be implemented are:

By calling getRequestedParameters() and getRequestedSymbolTables()the compiler framwork finds out which actual parameters the generate() method of a generator expects.

For the compiler framework to be able to schedule the generators these have to provide information on the return value of the generate() method on invocations of getProducedSymbolTable().

In certain adaptations of the compiler framework the domain modeller is informed about the state of the compilation process. The necessary information is gathered from generators by registering an observer, an implementation of the interface ProgressListener. An observer registers itself with a generator by calling addProgressListener(). When making progress the generator shall inform observers by invoking their changedState() method.

Configure the Compiler Framework

add generator to compiler configuration "my-cat.xml"
<?xml version="1.0"?>
<cat xmlns:util="http://www.sts.tu-harburg.de/2004/java/util/xmlconfigfile">
    <scanner class="de.tuhh.sts.cocoma.compiler.ADLScanner"/>
    <parser class="de.tuhh.sts.cocoma.compiler.ADLParser"/>
    <dictionary class="de.tuhh.sts.cocoma.dictionary.FileDictionary">
        <param name="directory">U:\Projects\my-project\model</param>
    </dictionary>
    <configuration name="myconfig">
        <param name="outputDirBase">U:\Projects\my-project\src</param>
        <generator name="apigen" class="de.tuhh.sts.cocoma.compiler.generators.api.APIGenerator">
            <param name="outputDir"><util:xpath path="../../../param[@name='outputDirBase']/text()"/>\classes</param>
            <param name="targetPackage">de.tuhh.sts</param>
        </generator>
        <generator name="mygen" class="de.tuhh.sts.cocoma.compiler.generators.myomy.MyGenerator">
            <param name="output directory"><util:xpath path="../../../param[@name='outputDirBase']/text()"/>\classes</param>
            <param name="target package">de.tuhh.sts</param>
        </generator>
    </configuration>
</cat>

Running the Compiler

run the compiler using

java de.tuhh.sts.cocoma.compiler.CAT -configFile ...\etc\my-cat.xml -configuration myconfig .../model/my-model.ald
and check the results in U:\Projects\my-project\src\de\tuhh\sts\...

Configuring a Component

The following XML code shows a sample component configuration:

<?xml version="1.0"?>
<cc:component name="my-component" xmlns:cc="http://sts.tuhh.de/cocoma/component-config.xsd">
    <cc:transformation-module name="my-module" class="de.tuhh.sts.cocoma.mymod.MyModule">
        <cc:base-module ref="base"/>
    </cc:transformation-module>
    <cc:client-module name="base" class="de.tuhh.sts.gkns.jdbc.GKNSJDBCImplIModule">
        <cc:param name="number of connections" value="10"/>
        <cc:param name="JDBC driver" value="oracle.jdbc.driver.OracleDriver"/>
        <cc:param name="JDBC connection URL" value="jdbc:oracle:thin:@sun20.sts.tu-harburg.de:1521:DB01"/>
        <cc:param name="DB user" value="my-gkns"/>
        <cc:param name="DB password" value="*****"/>
    </cc:client-module>
</cc:component>

In this sample configuration file a component is configured to consist of a C-module ("base") and a ...

Running the Component

Java-Code um Komponente zu instantiieren:

// start component
Component comp = new Component ("file:///D:/Projekte/myproject/etc/gkns-cc.xml") ;
System.out.println ("component \"" + comp.getName ()+ "\" initialized") ;
comp.run () ;
System.out.println ("component running") ;

Dann Client-Code z.B.:

// get "Student" asset class
AssetClass studentClass = mod.getClass ("Student") ;

// find all students named "Peter"
StudentIterator sIter = (StudentIterator)mod.lookfor (
    studentClass,
    new Module.QueryConstraint [] {
        new Module.CharacteristicQueryConstraint () {
            public Object getConstrainingValue () {
                return "Peter" ;
            }
            public String getAttributeName () {
                return "name" ;
            }
            public ComparisonOperator getComparator () {
                return ConstraintDescription.EQUAL ;
            }
        }
    }) ;

// show all students found
while (sIter.hasNext ()) {
    Student s = sIter.nextStudent () ;
    LectureIterator lIter = s.getLecures () ;
    System.out.println ("Student " + s.getName () + " has " + lIter.getLength () + " lectures") ;
    while (lIter.hasNext ())
        System.out.println (" - lecture \"" + lIter.nextLecture ().getTitle () + "\"") ;
}// while

HWS