The RealTime Modeling Platform (RMP) Metamodel Integration (MMI)
framework enables a given domain model to graphically understand the
domain concepts in terms of another domain notation.
This tutorial explains how to create an Eclipse PDE Modeler. This MMI-based domain specific
modeler will visualize elements from the Eclipse PDE domain on UML diagrams. Among the many
benefits of representing domain elements as UML is the fact that the UML notation is an open
standard and is well known to the Software Development Community.
The complete code for this tutorial can be installed by running the wizard accessible from File > New > Example > RMP (RealTime Modeling Platform) > Domain Modeling Layer Plug-ins > Plug-in UML Visualization Example.
The MMI framework provides the ability to map domain elements to
target domains such as UML, but unlike the traditional round-trip engineering based mapping,
it enjoys the following characteristics:
The MMI framework realizes the mapping framework by allowing
MMI-based domain specific modelers to create and associate target domain proxies for
their domain elements. These proxies are synchronized on-demand, and
can be referenced without being persisted.
All class diagrams shown in this tutorials are created using the MMI-based Java Modeling
functionality, which is part of some Model RealTime modeling solutions. This tutorial
will present how to build the functionality enabling Eclipse Plugin Development Environment (PDE)
modeling. For the purpose of this tutorial, the following elements in the PDE model are considered;
IPluginBase: Interface representing a Plug-in or Fragment.
IPluginImport: Interface representing an import of a Plug-in.
The PDE Modeler will represent Plug-in as a UML Artifact, and
will represent the imports of Plug-in as client dependencies to the
corresponding artifact. At the end of this tutorial, the Eclipse
runtime will be able to support following features:
Using Eclipse new Plugin Wizard, create a new Plugin
com.ibm.xtools.umlviz.ui.examples.pde
. Don't choose any default
templates in the Wizard.
Switch to the Java Perspective.
In com.ibm.xtools.umlviz.ui.examples.pde/META-INF/MANIFEST.MF
, create the following dependencies:
org.eclipse.pde org.eclipse.pde.core org.eclipse.pde.runtime org.eclipse.pde.ui org.eclipse.uml2 org.eclipse.jface com.ibm.xtools.mmi.core com.ibm.xtools.uml.core
Create following packages in the com.ibm.xtools.umlviz.ui.examples.pde
plugin.
com.ibm.xtools.umlviz.ui.examples.pde.internal.providers com.ibm.xtools.umlviz.ui.examples.pde.internal.handlers
Not all domain models come with serializable and de-serializable referencing framework, so StructuredReference was introduced to uniformly reference all domain concepts. An MMI-based domain specific modeler must define StructuredReference for all reference-able UML proxies for their domain element. A StructuredReference representation of a domain element should have enough information to de-reference the domain element.
For more information on StructuredReference, Please refer to FAQ.
The StructuredReferences for PDE elements of interest are represented with this key information and provider ID.
Domain Element | Key Properties | StructuredReference Provider Id |
---|---|---|
IPluginBase | Plugin ID, Plugin Version | pde.IPluginBase |
IPluginImport | Client ID, Client Version, Supplier ID, Supplier Version, Supplier Match Rule | pde.IPluginImport |
To serve the structured reference for IPluginBase and IPluginImport,
com.ibm.xtools.umlviz.ui.examples.pde.internal.handlers.PdeStructuredReferenceHandler
extending AbstractCachingStructuredReferenceProvider
.com.ibm.xtools.umlviz.ui.examples.pde.internal.handlers.PdeStructuredReferenceHandler
.
<extension id="pdeumlstructuredreferencehandler" name="StructuredReferenceHandler for PDE constructs" point="com.ibm.xtools.mmi.core.StructuredReferenceProviders"> <StructuredReferenceProvider class="com.ibm.xtools.umlviz.ui.examples.pde.internal.handlers.PdeStructuredReferenceHandler"> <StructuredReferenceProviderId id="pde.IPluginBase"/> <DomainElementType class="org.eclipse.pde.core.plugin.IPluginBase"/> <StructuredReferenceProviderId id="pde.IPluginImport"/> <DomainElementType class="org.eclipse.pde.core.plugin.IPluginImport"/> </StructuredReferenceProvider> </extension>
public StructuredReference createStructuredReference(Object referencedContext, Object domainElement)
public Object resolveToDomainElement(Object referencingContext, StructuredReference sRef)
public Object getInfo(Object referencedContext, StructuredReference sRef, String infoName)
The key to represent domain concepts on UML diagrams is to map them
properly to UML. For PDE Modeler example, the mapping of domain
elements of interest to their UML counterparts is as follows:
Domain Element | UML Counterpart |
---|---|
IPluginBase | Artifact |
IPluginImport | Usage |
IPluginBase.pluginImports | Artifact.clientDependencies |
To serve the UML proxies for the domain elements,
com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVisualizationProvider
extending AbstractModelMappingProvider
.com.ibm.xtools.umlviz.ui.examples.pde/plugin.xml
,
and create extension to com.ibm.xtools.mmi.core.ModelMappingProviders
. com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVisualizationProvider
<extension id="pdeumlmodelmappingprovider" name="UML Model Mapping Provider for PDE constructs" point="com.ibm.xtools.mmi.core.ModelMappingProviders"> <ModelMappingProvider class="com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVisualizationProvider"> <Priority name="Medium"/> <AdaptRequest DomainElementType="org.eclipse.pde.core.plugin.IPluginBase" TargetKind="uml.Artifact"/> <AdaptRequest DomainElementType="org.eclipse.pde.core.plugin.IPluginImport" TargetKind="uml.Usage"/> <ResolveRequest TargetKind="uml.Artifact" StructuredReferenceProviderId="pde.IPluginBase"/> <ResolveRequest TargetKind="uml.Usage" StructuredReferenceProviderId="pde.IPluginImport"/> </ModelMappingProvider> </extension>
public EObject adapt(TransactionalEditingDomain domain, Object source, EClass targetKind)
public EObject resolve(TransactionalEditingDomain domain, StructuredReference sRef, EClass eClass)
<pde.IPluginBase, uml2.Artifact>
to UML Artifact and
<pde.IPluginImport, uml2.Usage>
to UML Usage. The guidelines for
implementing resolve are the same as adapt.public boolean canAdapt(TransactionalEditingDomain domain, Object source, EClass targetKind)
public boolean canResolve(TransactionalEditingDomain domain, StructuredReference sRef, EClass eClass)
public boolean provides(IOperation operation)
The MMI framework strength lies in its ability to handle
synchronization of proxies on-demand. This means that the UML proxies
aren't synchronized unless client requests for that property.
The UML Proxies created by PdeUmlVisualizationProvider, are mere stubs
representing the domain element. The creation of these proxies involves
establishing a link between the proxy and the domain element. Also,
these proxies have to be initialized with an adapter that can populate
the properties of this UML Proxy. All this is achieved by invoking
ITarget.activate(ITargetSynchronizer, StructuredReference)
on the UML
Proxy implementing ITarget. Every feature of a UML proxy can be in two
different states, Synchronized and UnSynchronized.
ITargetSynchronizer.synchronizeFeature
is invoked. If
synchronizeFeature returns true the feature changes its state to
Synchronized. ITargetSynchronizer.synchronizeFeature
is invoked which synchronizes
the feature of the UML Proxy with the domain Element properties. ITargetSynchronizer.verifyFeatureContents
is invoked. ITargetSynchronizer
for every domain element. Use the singleton instance of this target
synchronizer to activate the UML proxy of the domain element.
public boolean synchronizeFeature(EObject eObj, EStructuralFeature sf, Object hint)
public void verifyFeatureContents(EObject eObj, EStructuralFeature sf, Object hint)
The MMI framework provides the ability to synchronize domain
elements in response to change to UML proxies representing domain
element. The backbone of this infrastructure is the
SourceSynchronizationService. The SourceSynchronizationService
listens to changes in UML elements representing domain elements, and
invokes appropriate providers to make changes to these domain elements.
Modifications to UML Proxies aren't supported if no source synchronization provider is
found that can handle that change.
com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVizCodeProvider
implementing ISourceSynchronizationProvider
. com.ibm.xtools.umlviz.ui.examples.pde/plugin.xml
, and create extension to om.ibm.xtools.mmi.core.CodeProviders
. com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVizCodeProvider
<extension id="pdeumlsourcesynchronizationprovider" name="Source Synchronization Provider for UML Viz Artifacts" point="com.ibm.xtools.mmi.core.SourceSynchronizationProviders"> <SourceSynchronizationProvider class="com.ibm.xtools.umlviz.ui.examples.pde.internal.providers.PdeUmlVizCodeProvider"> <Priority name="Medium"/> <StructuredReferenceProviderId id="pde.IPluginBase"/> <StructuredReferenceProviderId id="pde.IPluginImport"/> </SourceSynchronizationProvider> </extension>
public ICommand emit(ModelChangeDelta delta)
public boolean provides(IOperation operation)
The previous 5 sections have explained in detail, how to create a fully
functional infrastructure to visualize any given domain concepts as
UML. Also what has been explained so far is the ability to perform
two-way synchronization driven by Domain changes or UML changes.
At this time, it is recommended that some unit testing be done. Using JUnit API, the following scenarios could be tested:
How good is an MMI-base modeler if the user can't visualize anything!
The following user interface features are integral parts of every MMI-based domain
specific modeler:
The rest of the document will guide you in creating user interfaces for MMI-based domain specific modeler.
Though not mandatory, it is a good programming practice to separate UI
from core. In addition to core dependencies, UI plugin needs to depend
on the following plugins:
com.ibm.xtools.umlviz.ui org.eclipse.ui.ide org.eclipse.gef org.eclipse.gmf.runtime.common.ui org.eclipse.gmf.runtime.diagram.ui org.eclipse.gmf.runtime.diagram.ui.providers org.eclipse.gmf.runtime.common.ui.services.dnd
Other must do items:
plugin.properties
for storing L10n strings in plugin.xml. message.properties
for storing L10n strings in source code. The MMI framework provides implementation for most commonly used
MMI-based domain specific modeler use-cases. This is made possible by creating yet another
service to manage interaction with such modelers. The
service is IMMIUIService and the providers for this service are
registered as extensions to com.ibm.xtools.mmi.ui.MMIUIProviders
extension point. The providers registered with IMMIUIService
must implement IMMIUIProvider interface.
IMMIUIProvider provides the following handlers for multiple UI components:
For our example,
com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers
.com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers.PdeUmlVizUIProvider
implementing IMMIUIProvider
and extending AbstractProvider
. com.ibm.xtools.umlviz.ui.examples.pde/plugin.xml
, and create extension to com.ibm.xtools.mmi.ui.MMIUIProviders
. com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers.PdeUmlVizUIProvider
<extension id="pdeumlmmiuiprovider" name="MMI UI Provider for PDE" point="com.ibm.xtools.mmi.ui.MMIUIProviders"> <MMIUIProvider class="com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers.PdeUmlVizUIProvider"> <Priority name="Medium"/> <MMIUIHandler name="PdeVizUIHandler" uiObjectClass="org.eclipse.core.resources.IFile"> <enablement> <or> <test property="com.ibm.xtools.mmi.ui.DiagramTypePropertyTester" value="Freeform"/> <test property="com.ibm.xtools.mmi.ui.DiagramTypePropertyTester" value="Class"/> <test property="com.ibm.xtools.mmi.ui.DiagramTypePropertyTester" value="Deployment"/> </or> </enablement> </MMIUIHandler> <OpenStructuredReferenceHandler name="PdeVizOpenHandler"> <StructuredReferenceProviderId id="pde.IPluginBase"/> </OpenStructuredReferenceHandler> </MMIUIProvider> </extension>
public IMMIUIHandler getUIHandler(Object uiObject, IUIContext uiContext)
public IStructuredReferenceOpenHandler getStructuredReferenceOpenHandler(String providerId)
public boolean provides(IOperation operation)
GetUIHandlerOperation
, GetStructuredReferenceOpenHandlerOperation
. In
the PDE Modeler example, the provides method implementation need to
check the file name of the object in GetUIHandlerOperation
. The allowed
filenames are plugin.xml and fragment.xml. For all other operations,
the provider returns true as the information specified in extension is
sufficient to validate provider activation condition.The implementation of this interface requires implementation of following methods:
public IPath getDefaultDiagramPath(Object uiObject, IUIContext uiContext)
public List getSourceElements(Object referencedContext, Object uiObject, IUIContext uiContext)
public EClass getTargetEClass(Object referencedContext, Object source, IUIContext uiContext)
The implementation of this interface requires implementation of following methods:
public boolean canOpenStructuredReference(Object referencedContext, StructuredReference sRef)
public void openStructuredReference(Object referencedContext, StructuredReference sRef, IProgressMonitor monitor)
Every domain modeler provides some functionality to drag and drop
domain elements onto the diagram surface. The MMI framework provides a
Drop Target Listener to register with Drag and Drop Service. This Drop
Target Listener provides ability to drag from the custom viewer onto the
diagram surface and visualize the domain element as suggested in Domain
MMIUIProvider. Please refer to Technical_Note_DnD_Infra.
In PDE Modeler example, the ability to drag and drop from the Package Explorer onto diagram is defined as follows:
<extension id="pdeumldragdropProvider" name="Drag and drop Provider for PDE Visualization" point="org.eclipse.gmf.runtime.common.ui.services.dnd.dragDropListenerProviders"> <DragDropListenerProvider class="com.ibm.xtools.mmi.ui.dnd.MMIDragDropTargetListener" id="com.ibm.xtools.umlviz.ui.examples.pde.pdedndlistenerprovider"> <Priority name="Low"/> <!-- supporting drop on MMI-based domain specific modeler editor --> <ViewId id="UMLVisualizerEditor"> <ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart"> <OperationType operation="drop"> <TransferId transferId="JDTLocalSelectionTransfer"/> </OperationType> </ElementType> </ViewId> <!-- supporting drop on modeling editor --> <ViewId id="ModelerDiagramEditor"> <ElementType class="org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart"> <OperationType operation="drop"> <TransferId transferId="JDTLocalSelectionTransfer"/> </OperationType> </ElementType> </ViewId> </DragDropListenerProvider> </extension>
The most used actions for domain modelers is Add To New Class
Diagram and Add to Current Diagram. The MMI framework provides
implementation for these actions in two classes
com.ibm.xtools.umlviz.ui.examples.pde.internal.actions.AddToNewClassDiagramAction
and
com.ibm.xtools.mmi.ui.actions.AddToCurrentDiagramAction
.
Domain modelers can use these implementations to create pop up
menus. In PDE Modeler example, three menus are provided on
plugin.xml and fragment.xml:
<extension id="PDEPopupMenus" name="PDE Popup Menus" point="org.eclipse.ui.popupMenus"> <!-- Add to Current/Create new --> <objectContribution objectClass="org.eclipse.core.resources.IFile" nameFilter="plugin.xml" id="pluginVisualizationPopup"> <!-- Add to New Deployment diagram action --> <action label="%AddToNewDiagramFile.deployment.actionLabel" class="com.ibm.xtools.umlviz.ui.examples.pde.internal.actions.AddToNewDeploymentDiagramAction" menubarPath="com.ibm.xtools.umlviz.ui.VizMenu/addToNewDiagramFileMenu/diagramsGroup" id="addToNewDeploymentDiagramAction"> </action> <!-- Add to New Class diagram action --> <action label="%AddToNewDiagramFile.class.actionLabel" class="com.ibm.xtools.umlviz.ui.examples.pde.internal.actions.AddToNewClassDiagramAction" menubarPath="com.ibm.xtools.umlviz.ui.VizMenu/addToNewDiagramFileMenu/diagramsGroup" id="addToNewClassDiagramAction"> </action> <!-- Add to current diagram action --> <action label="%addToCurrentDiagramAction" class="com.ibm.xtools.mmi.ui.actions.AddToCurrentDiagramAction" menubarPath="com.ibm.xtools.umlviz.ui.VizMenu/addToGroup" id="addToCurrentDiagramAction"> </action> </objectContribution> </extension>
Domain modelers need palette tools to create domain
elements. Creation of these palette tools is out of this document's
scope. For detailed reference on how to Create Palette tools, please
refer to the GMF documentation. High level steps are as follows:
com.ibm.xtools.diagram.ui.paletteProviders
.
Use the org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider
as the class of the Palette Provider. com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers.PdeUmlVizPaletteFactory
.<extension id="PdeUmlVizPaletteProvider" name="Palette Provider for Pde Uml Visualization" point="org.eclipse.gmf.runtime.diagram.ui.paletteProviders"> <paletteProvider class="org.eclipse.gmf.runtime.diagram.ui.providers.DefaultPaletteProvider"> <Priority name="Highest"> </Priority> <content> <method name="hasNature(org.eclipse.pde.PluginNature)" value="true"> </method> </content> <contribution factoryClass="com.ibm.xtools.umlviz.ui.examples.pde.internal.ui.providers.PdeUmlVizPaletteFactory"> <!-- Root drawer for PDE Modeler --> <entry label="%PdeVizDrawer.Label" kind="drawer" description="%PdeVizDrawer.Description" path="/" id="PdeViz"> </entry> <!-- Palette item to create usage --> <entry label="%PdeUsageTool.Label" kind="tool" description="%PdeUsageTool.Description" path="/PdeViz/" large_icon="icons/pde_usage_24x24.gif" small_icon="icons/pde_usage.gif" id="PdeUsageTool"> </entry> </contribution> </paletteProvider> </extension>
public Tool createTool(String toolId)
Domain modelers need action bars to create domain elements. Action bars are contributed by Modeling Assistant Providers. For reference on how to create and use Modeling Assistant Providers, please refer to the GMF documentation.
At times UML proxies can not represent the entire information about the
domain element. So UML Profiles can be used to represent that extra
information. UML Profiles allow for extensibility of UML. Domain
modelers can create UML Profiles for their domains, and apply
stereotypes on UML proxies. For detailed reference on how to create and
use profiles, please refer to Tutorial on UML Profiles.