Hints for Writing Plug-Ins
  • Still using Poseidon 1.x and you cannot/do not want to move to Poseidon 2.x? Get the keys for CodeGenDemo (Version 0.x) and API-Demo (Version 1.x) in Poseidon 1.x format.

  • The Java API to UML 1.4 is included in the lib folder of your Poseidon distribution as compiled Java classes. In the jar archive jumiuml14di.jar, you find Interfaces conforming to the UML 1.4 specification (plus the Diagram Interchange).

  • Some definitions related to metadata management: The UML 1.4 specification can be written down in XML using the XMI (XML Metadata Interchange) DTD. Poseidon writes XMI 1.2 and reads XMI 1.0, 1.1 and 1.2.

    UML 1.4 can be formally defined using MOF (Meta-Object Facility). This, in combination with JMI (Java Metadata Interface), defines the shape of the Java interfaces representing the UML metamodel. MDR (Metadata Repository) complies to the XMI, MOF, and JMI standards. MDR is the component that Poseidon uses for management of the UML data.

  • Poseidon itself and all plug-ins require a license key. The license key needs the name of the plug-in (the name that is displayed in the Plug-ins Panel) and the version number. This is a major version, ie., the number before the first dot. Programmatically, you give the name and version number in the super call in the constructor of your plug-in class, e.g., ApiDemoPlugin.

  • Getting notified of the user's selections: The current selection is called a Target in Poseidon. Learn more.

  • Localizing your plug-in: Learn how to use Poseidon's localization system.

  • Hiding tagged values in the 'Tagged Values' tab: PoseidonUMLConnector.addHiddenTagDefinition(String regex) and PoseidonUMLConnector.removeHiddenTagDefinition(String regex) can be used to hide your user-defined Tag Definition names. You can use regular expressions such as ".*johndoe.*" to hide all tags with the String "johndoe" in them. (Note that the . stands for any character, and .* stands for a sequence of zero or more characters; to explicitly refer to a . such as in "com.johndoe.myTaggedValue", write "com\.johndoe\.myTaggedValue".) More on regular expressions can be found in the documentation to java.util.regex.Pattern. We recommend that you use a naming scheme similar to package names, so that you can hide tagged values by simple wildcarding, e.g. com.example.value1, com.example.value2.

  • To store the settings of your plug-in, use Poseidon's configuration file in poseidon2//Poseidon.properties. You just need to store your values in a special map and read them. Persistence happens automatically.

    To address your value, you need a ConfigurationKey: Services.getInstance().getConfiguration.makeKey("com", example", poseidonplugin", "color") will create a key for you. The separate parameters are just there to define a separate namespace for your keys. It is quite useful, by the way, to make those keys static final constants somewhere.

    Then, call Services.getInstance().getConfiguration().putString(key, "white") to save the value. And call Services.getInstance().getConfiguration().getString(key) to retrieve the value of your key again. There are similar methods like getBoolean(ConfigurationKey key, boolean defaultValue) or putDouble(ConfigurationKey key, double newValue) for other data types.

  • To create a new tab in the details pane, we recommend that you inherit from org.argouml.ui.TabSpawnable. All project-related initializations should then happen in initProjectRelated(), all init routines independent of the current project can be done in the constructor. Also, the methods onProjectLoaded(), onProjectCreated(), onProjectClosed(), onProjectSaved() are provided to provide hooks for project change events.

  • To navigate and read the UML model of the current project, you should use the ModelElementAccessory with its many helpful methods. To get the current model, call PoseidonProjectConnector.getModel() and cast it to org.omg.uml.model_management.Model.

  • In Poseidon 2, we have introduced Undo/Redo. We use the GoF Command pattern to implement Undo/Redo, that means that every modification of the model must be a Command. Many Commands are available to perform different actions. They are provided by CommandFactories.

    Def.: Sm = semantic model, UML ; Di = Diagram interchange, diagram information ; DiSm = shorthand for both

    From the current project, call getCommandSmFactory(), getCommandDiSmFactory() or getCommandDiFactory() . In the CommandSmFactory, you will find all Uml-related commands like makeCommandSmCreateAttribute(SmId attributeSmId, Smid classifierSmId). You can then call execute() on the returned command, and that's it. All required updates are done implicitly, like repainting the class where the new attribute should be shown.

    Now, what is an SmId? An Id is a unique reference to an element, either existing, to be created, or already deleted. We need Ids to reference elements across commands and across all undo/redo stages. There are SmIds and DiIds, again distinguishing Sm and Id level. To get a new SmId for your new attribute, just call project.getNextSmId(). To get the SmId of the class where you want to insert the attribute, call project.getSmId(class) . To get the element from a SmId, call smid.getElement() .Call smid.hasElement() to find out if it already has an element, like after execution of the createAttribute command, or does not yet have one, like before the execute() call.

  • Composite commands: Let's say you want to create an attribute 'foo'. You can get the first command as described above, get the makeCommandSmSetModelElementName(attributeSmId, "foo") and execute them one after another. But that's not great, as now we find two commands on the undo stack. Better would be to turn back both commands at once. This can be done using a MacroCommand, inserting the two commands in the MacroCommand, and executing that one instead of the two commands separately. commandDiFactory().makeMacroCommand() gives you a MacroCommand. Call macro.addCommand(createAttributeCommand); macro.addCommand(setNameCommand); macro.execute() and you will see that the two commands were executed one after the other, but for the user it looks like just one.

  • Reacting to project changes: You can register as listener in order to receive an event when a project has been saved, opened from file, closed, or newly created. When you hit the 'New project' button, first a 'closed' event is fired, then a 'created' event. When you load a project, a 'closed' is followed by a 'loaded'. At startup, you will find either 'loaded' when the setting 'reload last project' was enabled or a project was given to Poseidon (via command line or double click in Windows on a .zuml file); or a 'created' event when Poseidon starts with a blank project. At shutdown, a 'closed' is fired.

    Register with PoseidonProject.addProjectListener(VetoableChangeListener l). Currently, in Poseidon up to 2.2, all Vetos are ignored. You will receive a PoseidonProject.PROPERTY_EVENT_[LOADED|CREATED|CLOSED|SAVED] with the newValue being the new project at 'loaded' or 'created' , the oldValue being the closed project at 'closed' or the saved project at 'saved'. All other values are null.

© 2000 - 2010 Gentleware AG
 support  documentation  documentation  getting started  hints