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".
If there is no PIM metaclass that matches your needs, you should also model a new <<metaclass>> (see Node, Component and Artifact in the sample below).
AndroMDA's meta cartridge will transform all those metafacade attributes, associations and operations into Java methods which you will have to implement. The algorithms inside those methods come from the transformation rules you have recorded in your transformation table.
For our sample deployment cartridge, the metafacade model looks like this:
I have used the following inheritance relationships:
This only works because in the UML metamodel, Node, Component and Artifact all specialize Classifier. That way, I can reuse all the operations in ClassifierFacade which is included in the AndroMDA distribution.
Make sure your cartridge POM (see pom.xml) contains a dependency to the andromda-meta cartridge. Then:
As an example, look at the code which is contained in our deployment cartridge metafacades:
NodeFacadeLogicImpl.java:
protected Project handleTransformToAntProject() { ArrayList compilationTasks = new ArrayList(); ArrayList deploymentTasks = new ArrayList(); for (Iterator iter = getDeployedComponents().iterator(); iter.hasNext();) { ComponentFacade element = (ComponentFacade) iter.next(); compilationTasks.addAll(element.getTasksForCompilationPhase()); deploymentTasks.addAll(element.getTasksForDeploymentPhase()); } Target compilationTarget = new Target("compile", null, compilationTasks); Target deploymentTarget = new Target("deploy", "compile", deploymentTasks); ArrayList allTargets = new ArrayList(2); allTargets.add(compilationTarget); allTargets.add(deploymentTarget); Project p = new Project(getFullyQualifiedName(), "deploy", allTargets); return p; }
ComponentFacadeLogicImpl.java:
protected java.util.Collection handleGetManifestingArtifacts() { ArrayList result = new ArrayList(); Collection dependencies = getTargetDependencies(); for (Iterator iter = dependencies.iterator(); iter.hasNext();) { DependencyFacade element = (DependencyFacade) iter.next(); if (element.hasStereotype(DeploymentProfile.STEREOTYPE_MANIFEST)) { result.add(element.getSourceElement()); } } return result; } protected Collection handleGetTasksForDeploymentPhase() { ArrayList result = new ArrayList(); Collection manifestingArtifacts = getManifestingArtifacts(); for (Iterator iter = manifestingArtifacts.iterator(); iter.hasNext();) { ArtifactFacade element = (ArtifactFacade) iter.next(); result.addAll(element.getTasksForDeploymentPhase()); } return result; } protected Collection handleGetTasksForCompilationPhase() { ArrayList result = new ArrayList(); Collection manifestingArtifacts = getManifestingArtifacts(); for (Iterator iter = manifestingArtifacts.iterator(); iter.hasNext();) { ArtifactFacade element = (ArtifactFacade) iter.next(); result.addAll(element.getTasksForCompilationPhase()); } return result; }
ArtifactFacadeLogicImpl.java:
protected java.util.Collection handleGetWrappedPackages() { ArrayList result = new ArrayList(); Collection dependencies = getSourceDependencies(); for (Iterator iter = dependencies.iterator(); iter.hasNext();) { DependencyFacade element = (DependencyFacade) iter.next(); if (element.hasStereotype(DeploymentProfile.STEREOTYPE_WRAPS)) { result.add(element.getTargetElement()); } } return result; } protected Collection handleGetTasksForCompilationPhase() { ArrayList result = new ArrayList(); Collection wrappedPackages = getWrappedPackages(); for (Iterator iter = wrappedPackages.iterator(); iter.hasNext();) { DeployedPackageFacade element = (DeployedPackageFacade) iter.next(); result.addAll(element.getTasksForCompilationPhase()); } return result; } protected Collection handleGetTasksForDeploymentPhase() { ArrayList packages = new ArrayList(); // find all packages which deploy in this artifact Collection wrappedPackages = getWrappedPackages(); for (Iterator iter = wrappedPackages.iterator(); iter.hasNext();) { DeployedPackageFacade element = (DeployedPackageFacade) iter.next(); packages.add(element.getFullyQualifiedName()); } // jar all packages into one jar JarTaskCall taskCall = new JarTaskCall(packages, getName(), "jar"); ArrayList result = new ArrayList(1); result.add(taskCall); return result; }
Now you have seen that the transformation rules which you identified earlier have been coded into metafacade classes. Each transformation rule translates one or more PIM objects into one or more PSM objects. These PSM metaobjects are now ready to be processed by templates. So, it's just the right time to show you how to write templates.