Writing your own metafacades is a non-trivial task, if you do it for the first time. You should close the door and get yourself at least two days in a quiet atmosphere, reducing the context switches in your mind to a minimum. Otherwise, it might be a pain! :-)
The next section assumes you have brewed a good cup of coffee (or tea or whatever) and have at least two hours of time. Take a deep breath and start to prepare your working environment.
First, make sure you have the correct directory structure on disk to keep all the artifacts you need to develop an AndroMDA cartridge. The easiest way to get such a correct directory structure is to copy an existing cartridge that already contains its own metafacades. A good example for this is the Hibernate cartridge.
After you copied the cartridge, you will see a directory structure like this:
src/java src/templates src/uml
Metafacades are generated from a UML model. Put this UML model in a file into the src/uml directory. Open MagicDraw and import the basic metafacades module which is shipped with AndroMDA. These basic metafacades for UML are in the model file andromda/xml.zips/UMLMetafacadeModel-*.xml.zip located in the AndroMDA binary distribution. You import them using the "File, Use Profile/Module..." menu in MagicDraw. After using the module, you should be able to see the basic facade classes (like ClassifierFacade, etc.) but MagicDraw should show them as read-only.
The next step is to model your own metafacades.
A few rules apply if you want to make AndroMDA generate the metafacades for you. You will see that they are easy to remember and that they make sense. After a short recap to clarify the terminology, the rules will be shown here.
Later, the user of your cartridge will load a model into AndroMDA and will try to run your cartridge. At that time, the metadata repository in AndroMDA will instantiate a metaobject for each element of the user's model. After this, AndroMDA optionally instantiates a metafacade object that shields the metaobject.
We choose the following terms when we speak about metafacades:
So, don't confuse a metafacade class with a metaclass!
There are rules that tell you how to shield a metaclass with a metafacade. Metafacades and metaclasses can relate to each other in the following ways:
There are two rules how to add stereotypes to the classes:
That's it. No more rules for modeling metafacades.
Here, you see a picture of some typical metafacades:
A metafacade can have attributes, operations and associations to other metafacade classes. It can also depend on a metaclass or specialize another metafacade class. Let's talk about what it means if you add various things to a metafacade class.
The code for the metafacades will be generated by the andromda-meta cartridge. (Cool: you use AndroMDA to develop a cartridge that extends AndroMDA!). Each model element that you add to a metafacade class will later be translated by andromda-meta into a bunch of Java elements. The following table shows you which model element will be translated to which Java element:
|Model element||Java element(s)|
|Metafacade class||Interface, plumbing and implementation classes|
|Dependency||Ignored except when the target of the dependency is a metaclass. In that case, a constructor with an argument of the metaclass type is generated.|
|Specialization||Same constructor as in the dependency case except that this constructor calls the "superfacade" constructor.|
A metaclass itself translates to three classes in Java:
//TODO: Add pictures of generated metafacades here...
//TODO: Describe what the responsibilities of the three classes are...
Basically, after having generated all those nice metafacade classes, you will want to implement their real functionality, right? To do that, start your favourite Java IDE (e.g. Eclipse).
Open a project that references all the source files, generated as well as hand-written. Make the IDE project reference the standard, basic metafacade project in the metafacades/uml directory. //TODO: Chad, where are those files in the binary distribution? Metafacade developers should possibly reference a jar file here instead of the source code tree, right?
Now, watch out for all those classes that end with "LogicImpl" in their names. These classes have been generated for you but will never be touched by the generator again. This is the place where you can implement your own logic.
Watch out for the "//TODO" tags in the files. You will notice that getters for attributes and associations are there to be filled by hand. This is the place where the facade does its work - you will want to refer to the contents of the metaobject that is shielded by this facade and translate it in some way so that you can return it from one of those getters. Operations in the metafacade model are translated to abstract Java methods - you will also want to implement these in the LogicImpl class.
//TODO: Describe how to create new metafacade objects and how the factory knows which one to instantiate, depending on stereotype and context.
//TODO: Insert reference to Configuring metafacades so that we explain everything only once.
//TODO: Describe how to shield a metaobject with a metafacade object.
After you have modeled, generated and implemented your metafacades, you can deploy them with your cartridge. To make this work, you need to configure an XML file. Read Configuring metafacades to see how to make AndroMDA use your metafacades at the right time.