10 steps to write a cartridge

This article shows you how to write an AndroMDA cartridge in 10 distinct steps, using a sample cartridge which generates an Ant-like build script from a UML deployment model. This is why the tutorial cartridge is called "andromda-deployment".

Writing templates

OK, until now you know the following:

  1. a model is parsed into an AST
  2. AST is made of metaobjects (instances of metaclasses)
  3. metaobjects are wrapped with metafacades
  4. metafacades return PSM metaobjects which are ready to fill a template
  5. you'll now learn how to write templates that transform PSM objects to text

We'll have a look at the sample template which transforms the contents of a Project object into an XML file for Ant. The template is written in the Velocity template language and looks like this:


#set ($project = $node.transformToAntProject())
<project name="$project.name"
         default="$project.defaultTargetName">#foreach ($target in $project.targets)#if ($target.dependencyList)
    <target name="$target.name" depends="$target.dependencyList">#else
    <target name="$target.name">#end#foreach ($task in $target.taskcalls)#if ($task.taskName == "javac")
        <javac package="$task.packageToBeCompiled"/>#elseif($task.taskName == "jar")
        <jar name="$task.jarName">#foreach ($package in $task.packagesToBeJarred)<package

You see that a template basically consists of:

  1. the text you want to see in your output file
  2. placeholders where concrete names and values will be filled in
  3. metalevel statements like #set, #if and #for to allow navigation along the structure of the PSM metaobjects

The template language is documented in the docs of the Apache Velocity project or the Freemarker project, depending on which template engine you use.

This is the second template which is contained in the sample deployment cartridge. It generates a simple deployment report about all nodes, components and artifacts.


<deployment-report generation-date="$date">
    #foreach ($node in $nodes)
    <node name="$node.name">
        #foreach ($component in $node.deployedComponents)
        <component name="$component.name">
            #foreach ($artifact in $component.manifestingArtifacts)
            <artifact name="$artifact.name">
                #foreach ($package in $artifact.wrappedPackages)<package

I think you now get the basic idea about how templates work.