This example will demonstrate how to create custom views for stereotyped elements.

Extend the 
org.eclipse.gmf.runtime.diagram.core.viewProviders extension-point and 
set the viewProvider class to be a class which extends 
org.eclipse.gmf.runtime.diagram.core.providers.AbstractViewProvider.
The custom view needs to be provided for two types of actions:
To satisfy the first scenario, create an object context for class 
com.ibm.xtools.uml.type.IStereotypedElementType. For this context object, 
getStereotypeName() should return the fully qualified name of the expected stereotype, 
in this example the expected qualified name is MyProfile::MyStereotype.
To satisfy the second scenario, create another object context for class 
org.eclipse.gmf.runtime.emf.core.util.IProxyEObject. 
IProxyEObject is used because it provides a method to obtain the class ID without resolving 
the EObject if it happens to be a proxy. For this context object, 
getProxyClassID() should return the UML element ID for which the stereotype may be 
applied. A further check for the expected applied stereotype can either be 
implemented inside the view provider or by using a static method reference 
in the xml. This example implements this additional check in the view provider code.
   <extension
         point="org.eclipse.gmf.runtime.diagram.core.viewProviders">
      <viewProvider class="com.ibm.xtools.examples.atm.profiles.providers.MyViewProvider">
         <Priority name="Medium"/>
         <object class="com.ibm.xtools.uml.type.IStereotypedElementType(com.ibm.xtools.uml.type)" id="MyNode1">
            <method
	           name="getStereotypeName()"
	           value="MyProfile::MyStereotype">
            </method>
         </object>
         <!-- check for the applied stereotype in the provider code -->
         <object class="org.eclipse.gmf.runtime.emf.core.util.IProxyEObject(org.eclipse.gmf.runtime.emf.core)" id="MyNode2">
            <method
                  name="getProxyClassID()"
                  value="uml.Class">
            </method>
         </object>
         
         <context
              elements="MyNode1, MyNode2"
              viewClass="org.eclipse.gmf.runtime.notation.Node"/>
      </viewProvider>
   </extension>
The MyViewProvider implementation should 
provide a view factory class for each of the above scenarios.
To satisfy the first scenario, attempt to get an adapter for 
IStereotypedElementType.class. 
If the adapted 
IStereotypedElementType is the MyStereotype element type, then return the 
corresponding view factory class.
To satisfy the second scenario, get the semantic element and check if the expected applied stereotype can be found, and if so return the corresponding view factory class.
public class MyViewProvider
    extends AbstractViewProvider {
    IElementType MY_STEREOTYPE_TYPE = ElementTypeRegistry.getInstance()
            .getType("com.ibm.examples.type.myStereotype");
    
    protected Class getNodeViewClass(IAdaptable semanticAdapter, View containerView, String semanticHint) {
        Class clazz = null;
        
        if (semanticHint != null && semanticHint.length() == 0) {
            Object elementType = semanticAdapter.getAdapter(IStereotypedElementType.class);
            if (elementType == MY_STEREOTYPE_TYPE) {
                clazz = MyViewFactory.class;
            } else {
                // search for applied stereotype
                EObject eObject = getSemanticElement(semanticAdapter);
                if (eObject instanceof Element) {
                    Element element = (Element)eObject;
                    List stereotypes = element.getAppliedStereotypes();
                    for (Iterator i = stereotypes.iterator(); i.hasNext(); ) {
                        Stereotype stereotype = (Stereotype)i.next();
                        String name = stereotype.getQualifiedName();
                        if ("MyProfile::MyStereotype".equals(name)) {
                            clazz = MyViewFactory.class;
                            break;
                        }
                    }
                }
            }
        }
        
        return clazz;
    }
}
The MyViewFactory extends 
org.eclipse.gmf.runtime.diagram.ui.view.factories.AbstractShapeViewFactory. 
Override the decorateView method to set the type for the view and to append 
view children. In this example the MyStereotype view will make use of the UML Name 
text compartment by appending a child to the stereotype view using the 
CommonParserHint#NAME semantic hint.
public class MyViewFactory
	extends AbstractShapeViewFactory {
    protected void decorateView(View containerView, View view, IAdaptable element, String semanticHint, int index, boolean persisted) {
        // call super.decorateView to initialize view from preferences
        super.decorateView(containerView, view, element, semanticHint, index, persisted);
        
        // set view type
        view.setType("MyProfile::MyStereotype");
        // append the UML name text compartment
        getViewService().createNode(element, view, CommonParserHint.NAME, ViewUtil.APPEND, persisted, getPreferencesHint());
    }
}
In order to create a visual representations of the notation view provided by the view provider, 
extend the 
org.eclipse.gmf.runtime.diagram.ui.editpartProviders extension-point and set the editpartProvider class 
to be a class which extends 
org.eclipse.gmf.runtime.diagram.ui.services.editpart.AbstractEditPartProvider.
Set the enablement critiera to be a org.eclipse.gmf.runtime.notation.Node class whose 
type is the expected MyProfile::MyStereotype type.
   <extension
         point="org.eclipse.gmf.runtime.diagram.ui.editpartProviders">
      <editpartProvider class="com.ibm.examples.providers.MyEditPartProvider">
         <Priority name="Medium"/>
         <object
               class="org.eclipse.gmf.runtime.notation.Node(org.eclipse.gmf.runtime.notation)"
               id="MyNode">
            <method name="getType()" value="MyProfile::MyStereotype"/>
         </object>
         <context views="MyNode"/>
      </editpartProvider>
   </extension>
Type MyEditPartProvider returns the 
MyEditPart class if the view type is the expected MyStereotype type.
public class MyEditPartProvider extends AbstractEditPartProvider {
    private Map nodeMap = new HashMap();
    {
        nodeMap.put("MyProfile::MyStereotype", MyEditPart.class);
    }
    
    protected Class getNodeEditPartClass(View view) {
        return (Class) nodeMap.get(view.getType());
    }
}
The MyEditPart class should extend 
org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart 
to inherit the basic functions of a shape node.
Override createNodeFigure() to return a NodeFigure. 
Since the MyStereotype view has a text compartment child, override getPrimaryChildEditPart() 
to return the corresponding text compartment edit part. This will force the text 
compartment into direct edit mode when the edit part is created on the diagram.
public class MyEditPart extends ShapeNodeEditPart {
    public MyEditPart(View view) {
        super(view);
    }
    protected NodeFigure createNodeFigure() {
        return new CustomFigure();
    }
    public EditPart getPrimaryChildEditPart() {
        return getChildBySemanticHint(CommonParserHint.NAME);
    }
}

The CustomFigure class, for the MyEditPart above, extends 
org.eclipse.gmf.runtime.gef.ui.figures.NodeFigure. 
The figure is responsible for drawing the visual aspect of the edit part via the 
NodeFigure.paintFigure(Graphics graphics) method. In this 
example, paintFigure creates a rectangle with a triangular roof to represent the MyStereotype shape. 
Using a non-rectangular shape for the figure surfaces a couple complications.
The first complication is that the the text compartment will show up on the roof, therefore a margin border with sufficient padding is added to push the text compartment down into the main area of the figure.
The second complication is that in order to allow connections to anchor to the slanted roof, 
the class must implement org.eclipse.gmf.runtime.draw2d.ui.figures.IPolygonAchorableFigure 
and specify a list of points representing the outline of the figure otherwise it is assumed that the figure is 
a rectangular shape. This would result in connection ends appearing to be unattached.
Finally, the figure needs a layout manager to handle the layout of child figures.
public class CustomFigure
    extends NodeFigure
    implements IPolygonAnchorableFigure {
    
    private static int DPtoLP_1 = MapModeUtil.getMapMode().DPtoLP(1);
    private static int DPtoLP_3 = MapModeUtil.getMapMode().DPtoLP(3);
    private static int DPtoLP_10 = MapModeUtil.getMapMode().DPtoLP(10);
    private static int DPtoLP_12 = MapModeUtil.getMapMode().DPtoLP(12);
    private static final int MARGIN_TOP_BOTTOM = DPtoLP_3;
    
    private static final int MARGIN_LEFT_RIGHT = DPtoLP_10;
    
    private static final int ROOF_HEIGHT = DPtoLP_12;
    public CustomFigure() {
        setOpaque(true);
        setLayoutManager(new ConstrainedToolbarLayout());
        setBorder(new MarginBorder(ROOF_HEIGHT,
            MARGIN_LEFT_RIGHT, MARGIN_TOP_BOTTOM, MARGIN_LEFT_RIGHT));
    }
    protected void paintFigure(Graphics g) {
        Rectangle r = getHandleBounds().getCopy().expand(DPtoLP_1,DPtoLP_1);
        RGB newForeRGB = ColorUtil.blend(g.getForegroundColor()
            .getRGB(), g.getBackgroundColor().getRGB());
        
        g.setBackgroundColor( DiagramColorRegistry.getInstance()
            .getColor(newForeRGB));
        
        // draw the roof
        Point p1 = r.getTopLeft().getTranslated(0, ROOF_HEIGHT);
        Point p2 = r.getTopLeft().getTranslated((int)(r.width * 0.5), 0);
        Point p3 = r.getTopRight().getTranslated(0, ROOF_HEIGHT);
        
        PointList pList = new PointList();
        pList.addPoint(p1);
        pList.addPoint(p2);
        pList.addPoint(p3);
        g.fillPolygon(pList);
        g.drawPolygon(pList);
        
        // draw the outline
        Rectangle outline = new Rectangle();
        outline.setLocation(r.getLocation().translate(DPtoLP_1, ROOF_HEIGHT));
        // width and height - DPtoLP_1 due to line width of 1
        outline.setSize(r.width - DPtoLP_1*2, r.height - ROOF_HEIGHT - DPtoLP_1);
        g.drawRectangle(outline);
    }
    public PointList getPolygonPoints() {
        PointList ptList = new PointList();     
        Rectangle rect = getHandleBounds().getCopy().expand(DPtoLP_1,DPtoLP_1);
        Point p1 = rect.getBottomRight();
        Point p2 = rect.getBottomLeft();
        Point p3 = rect.getTopLeft().getTranslated(0, ROOF_HEIGHT);
        Point p4 = rect.getTopLeft().getTranslated((int)(rect.width*0.5), 0);
        Point p5 = rect.getTopRight().getTranslated(0, ROOF_HEIGHT);
        ptList.addPoint(p1);
        ptList.addPoint(p2);
        ptList.addPoint(p3);
        ptList.addPoint(p4);
        ptList.addPoint(p5);
        ptList.addPoint(p1);
    
        return ptList;
    }
}
Adding compartments is done in the same way as adding any other view child. The compartments require a view and corresponding edit part. Compartments can be made to either contain other shapes or list items:

To add compartments as children to a view, override the decorateView method 
of the compartments parent view factory and append the compartment views as children.
public class MyParentViewFactory extends AbstractShapeViewFactory {
    protected void decorateView(View containerView, View view, IAdaptable element, String semanticHint, int index, boolean persisted) {
        super.decorateView(containerView, view, element, semanticHint, index, persisted);
        getViewService().createNode(element, view, "myListCompartment", ViewUtil.APPEND, persisted, getPreferencesHint());
        getViewService().createNode(element, view, "myShapeCompartment", ViewUtil.APPEND, persisted, getPreferencesHint());
    }
}
There needs to be a view provider which will provide a view for each of the compartments. 
Extend the 
org.eclipse.gmf.runtime.diagram.core.viewProviders extension-point and 
set the viewProvider class to be a class which extends 
org.eclipse.gmf.runtime.diagram.core.providers.AbstractViewProvider.
Add a context to the view provider extension for the myShapeCompartment and 
myListCompartment semanticHints.
   <extension
         point="org.eclipse.gmf.runtime.diagram.core.viewProviders">
      <viewProvider class="com.ibm.examples.providers.MyCompartmentsViewProvider">
         <Priority name="Medium"/>
         <context
              semanticHints="myShapeCompartment, myListCompartment"
              viewClass="org.eclipse.gmf.runtime.notation.Node"/>
      </viewProvider>
   </extension>
The MyCompartmentsViewProvider class should 
return a view factory class for the myShapeCompartment and 
myListCompartment semantic hints.
org.eclipse.gmf.runtime.diagram.ui.view.factories.ResizableCompartmentViewFactory class, or instance of, 
	for the myShapeCompartment.org.eclipse.gmf.runtime.diagram.ui.view.factories.ListCompartmentViewFactory class, or instance of, 
	for the myListCompartment.public class MyCompartmentsViewProvider extends AbstractViewProvider {
    private Map nodeMap = new HashMap();
    {
        nodeMap.put("myShapeCompartment", ResizableCompartmentViewFactory.class);
        nodeMap.put("myListCompartment", ListCompartmentViewFactory.class);
    }
    
    protected Class getNodeViewClass(IAdaptable semanticAdapter, View containerView, String semanticHint) {
        return (Class)nodeMap.get(semanticHint);
    }
}
In order to create a visual representations of the notation view provided by the view provider, 
extend the 
org.eclipse.gmf.runtime.diagram.ui.editpartProviders extension-point and set the editpartProvider class 
to be a class which extends 
org.eclipse.gmf.runtime.diagram.ui.services.editpart.AbstractEditPartProvider.
Set the enablement critiera to be a org.eclipse.gmf.runtime.notation.Node class whose 
type is the expected myShapeCompartment or myListCompartment type.
   <extension
         point="org.eclipse.gmf.runtime.diagram.ui.editpartProviders">
      <editpartProvider class="com.ibm.examples.providers.MyCompartmentsEditPartProvider">
         <Priority name="Medium"/>
         <object
               class="org.eclipse.gmf.runtime.notation.Node(org.eclipse.gmf.runtime.notation)"
               id="myCompartments">
            <method name="getType()" value="myShapeCompartment, myListCompartment"/>
         </object>
         <context views="myCompartments"/>
      </editpartProvider>
   </extension>
The MyCompartmentEditPartProvider class should 
return an edit part class for the myShapeCompartment and 
myListCompartment view types.
org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart for the 
	myShapeCompartment view type.org.eclipse.gmf.runtime.diagram.ui.editparts.ListCompartmentEditPart for the 
	myListCompartment view type.public class MyCompartmentEditPartProvider extends AbstractEditPartProvider {
    private Map nodeMap = new HashMap();
    {
        nodeMap.put("myShapeCompartment", MyShapeCompartmentEditPart.class);
        nodeMap.put("myListCompartment", MyListCompartmentEditPart.class);
    }
    
    protected Class getNodeEditPartClass(View view) {
        return (Class) nodeMap.get(view.getType());
    }
}
The MyShapeCompartmentEditPart class can 
be as simple as extending 
ShapeCompartmentEditPart and implementing a constructor. 
ShapeCompartmentEditPart is a generic (sub) shape container that holds instances of
ShapeNodeEditParts and manages the display of
ConnectionNodeEditParts anchored to these shape edit part instances.
public class MyShapeCompartmentEditPart extends ShapeCompartmentEditPart {
    public MyShapeCompartmentEditPart(View view) {
        super(view);
    }
}
List compartments are generally created to be canonical. In order to add canonical behavior 
to the MyListCompartmentEditPart class 
install a canonical edit policy for the 
EditPolicyRoles#CANONICAL_ROLE. Override the 
hasModelChildrenChanged(Notification evt) method to 
determine if a given event affects the semantic model children.
public class MyListCompartmentEditPart extends ListCompartmentEditPart {
    public MyListCompartmentEditPart(EObject model) {
        super(model);
    }
    protected void createDefaultEditPolicies() {
        super.createDefaultEditPolicies();
        installEditPolicy(EditPolicyRoles.CANONICAL_ROLE, new MyCanonicalEditPolicy());
    }
    
    protected boolean hasModelChildrenChanged(Notification evt) {
        Object feature = evt.getFeature();
        return feature == UMLPackage.eINSTANCE.getClass_OwnedOperation();
    }
}
The MyCanonicalEditPolicy class should extend 
org.eclipse.gmf.runtime.diagram.ui.editpolicies.CanonicalEditPolicy and implement 
the 
CanonicalEditPolicy#getSemanticChildrenList() method. 
CanonicalEditPolicy#getSemanticChildrenList() should return a list of 
semantic elements to be displayed in the list compartment.
public class MyCanonicalEditPolicy extends CanonicalEditPolicy {
    protected List getSemanticChildrenList() {
        return ((Class) resolveSemanticElement()).getOwnedOperations();
    }
    protected String getDefaultFactoryHint() {
        return CommonParserHint.NAME;
    }
}
Note: An edit part needs to be provided for each semantic child. The edit part for list 
items generally extends the 
org.eclipse.gmf.runtime.diagram.ui.editparts.TextCompartmentEditPart class.
Canonical: Canonical is the terminology used to describe a container that keeps its view of semantic data synchronized with the semantic children. This means that the child views of canonical containers are created on demand whenever the semantic children change. When the diagram is saved, canonical views are not persisted in the diagram model.
Start by creating a class which extends 
org.eclipse.gmf.runtime.diagram.ui.editpolicies.DragDropEditPolicy. Override 
DragDropEditPolicy.getDropElementCommand(EObject element, DropObjectsRequest request) to return the drop command. 
In this example, a command which adds a dropped UML Package to the container UML Package is returned.
public class MyDragDropEditPolicy extends DragDropEditPolicy {
    protected Command getDropElementCommand(EObject element, DropObjectsRequest request) {
        if (element instanceof Package) {
            final Package item = (Package)element;
            return new ICommandProxy(
                new AbstractTransactionalCommand(getEditingDomain(), "Add Item", null) {
            
                protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) {
                    Package container = (Package)ViewUtil.resolveSemanticElement((View)getHost().getModel())
                    container.getNestedPackages().add(item);
                    return CommandResult.newOKCommandResult();
                }
                
            });
        }
        return null;
    }
}
This edit policy needs to be installed on an edit part. In the edit part class, install the 
MyDragDropEditPolicy edit policy for the 
EditPolicyRoles.DRAG_DROP_ROLE role.
public class MyShapeNodeEditPart extends ShapeNodeEditPart {
    
    ...
    
    protected void createDefaultEditPolicies() {
        super.createDefaultEditPolicies();
    
        installEditPolicy(EditPolicyRoles.DRAG_DROP_ROLE, new MyDragDropEditPolicy());
    }
    ...
    
}
To install this, or any other, edit policy onto an existing edit part, see the Installing Edit Policies on Existing Edit Parts section for more info
Adding double-clicking behaviour to edit parts is generally useful to open another editor using model element of the edit part as the context. However it can be used to perform any sort of command. This example will demonstrate how to add double-click behaviour to an edit part to be executed which will open a message dialog.
Start by creating a class which extends 
org.eclipse.gmf.runtime.diagram.ui.editpolicies.OpenEditPolicy. Override 
OpenEditPolicy.getOpenCommand(Request request) to return the open command. In this example, a command which opens a 
message dialog is returned.
public class MyOpenEditPolicy extends OpenEditPolicy {
    protected Command getOpenCommand(Request request) {
        return new Command("Test double-click") {
            public void execute() {
                Shell shell = new Shell();
                MessageDialog.openInformation(
                    shell,
                    "My Title",
                    "Double-click command executed.");
            }
        };
    }
}
This edit policy needs to be installed on an edit part. In the edit part class, install the 
MyOpenEditPolicy edit policy for the 
EditPolicyRoles.OPEN_ROLE role.
public class MyShapeNodeEditPart extends ShapeNodeEditPart {
    
    ...
    
    protected void createDefaultEditPolicies() {
        super.createDefaultEditPolicies();
    
        installEditPolicy(EditPolicyRoles.OPEN_ROLE, new MyOpenEditPolicy());
    }
    ...
    
}
To install this, or any other, edit policy onto an existing edit part, see the Installing Edit Policies on Existing Edit Parts section for more info
In the above examples for Adding Drag and Drop Behaviour and 
Adding Double-Click Behaviour, it is possible to install these 
edit policies onto existing edit parts in the RMP UML Modeler. This is done by extending the 
org.eclipse.gmf.runtime.diagram.ui.editpolicyProviders extension-point. Defining the extension is similar to that for view and edit part providers.
editpolicyprovider and set the class to be a class which implements 
	org.eclipse.gmf.runtime.diagram.ui.services.editpolicy.IEditPolicyProvider.IGraphicalEditPart and additionally 
	check the semantic element of the edit part. In this example, edit policies will be provided 
	for any edit part whose semantic element is a UML Interface.   <extension
         point="org.eclipse.gmf.runtime.diagram.ui.editpolicyProviders">
      <editpolicyProvider class="com.ibm.examples.providers.MyEditPolicyProvider">
         <Priority name="Medium"/>
         <object
               class="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart(org.eclipse.gmf.runtime.diagram.ui)"
               id="InterfaceEP">
            <method
                  name="resolveSemanticElement().eClass().getName()"
                  value="Interface"/>
         </object>
         <context editparts="InterfaceEP"/>
      </editpolicyProvider>
   </extension>
The MyEditPolicyProvider should include 
the same, or stricter, provides criteria defined in the xml extension. It should also implement 
createEditPolicies(EditPart ep) to create and install the edit policy on the 
given edit part. In this example, the MyOpenEditPolicy is 
installed on all edit parts with semantic element of type UML Interface.
public class MyEditPolicyProvider extends AbstractProvider implements IEditPolicyProvider {
    public void createEditPolicies(EditPart ep) {
        if (ep instanceof IGraphicalEditPart) {
            EObject element = ((IGraphicalEditPart)ep).resolveSemanticElement();
            if (element instanceof Interface) {
                ep.installEditPolicy(EditPolicyRoles.OPEN_ROLE, new MyOpenEditPolicy());
            }
        }
    }
    public boolean provides(IOperation operation) {
        if (operation instanceof CreateEditPoliciesOperation) {
            EditPart ep = ((CreateEditPoliciesOperation) operation).getEditPart();
            if (ep instanceof IGraphicalEditPart && ep instanceof IPrimaryEditPart) {
                EObject element = ((IGraphicalEditPart)ep).resolveSemanticElement();
                return element instanceof Interface;
            }
        }
        return false;
    }
}
The Decoration Service gives clients the ability to decorate diagram elements with an image or figure. A provider of the decoration service will be able to add an adornment to any diagram element. The decoration is typically an image, but can be any sort of graphics object or figure. A provider of the decoration service is not restricted to any specific graphic type.

To add decorations extend the 
org.eclipse.gmf.runtime.diagram.ui.decoratorProviders extension-point.
decoratorProvider.decoratorProvider class to be a class which extends 	
	org.eclipse.gmf.runtime.common.core.service.AbstractProvider 
	and implements 
	org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorProvider.decoratorTargets for which the decorator provider provides for. In this example
	the decorator provider will provide only for an 	
	IPrimaryEditPart whose semantic element is of type UML Class. 
	The IPrimaryEditPart interface is a common interface implemented by 
	ConnectionEditPart and ShapeEditPart.   <extension point="org.eclipse.gmf.runtime.diagram.ui.decoratorProviders">
      <decoratorProvider class="com.ibm.examples.providers.MyDecoratorProvider">
         <Priority name="Lowest"/>
         <object
               class="org.eclipse.gmf.runtime.diagram.ui.editparts.IPrimaryEditPart(org.eclipse.gmf.runtime.diagram.ui)"
               id="class">
            <method
                  name="resolveSemanticElement().eClass().getName()"
                  value="Class"/>
         </object>
         <context decoratorTargets="class"/>
      </decoratorProvider>
   </extension>
The MyDecoratorProvider should provide for the same, or stricter, 
criteria which was used in the xml extension.
In the MyDecoratorProvider#createDecorators(IDecoratorTarget decoratorTarget) 
method, install the decorator on the decoratorTarget using a unique key.
If another decorator is installed on the same target with the same key then it will override the previous one installed. 
GMF defines a few standard decorator keys in the 
IDecoratorKeys interface: 
BOOKMARK, CROSS_MODEL_REFERENCE, and UNRESOLVED_VIEW. Since this example decorator will not replace any of 
the decorators for the pre-defined keys, an arbitrary unique key is used.
public class MyDecoratorProvider
        extends AbstractProvider implements IDecoratorProvider {
    public void createDecorators(IDecoratorTarget decoratorTarget) {
        IGraphicalEditPart editPart = (IGraphicalEditPart)decoratorTarget.getAdapter(IGraphicalEditPart.class);
        if (editPart instanceof IPrimaryEditPart) {
            EObject eObject = editPart.resolveSemanticElement();
            if (eObject instanceof Class) {
                decoratorTarget.installDecorator("myDecoratorKey", new MyDecorator(decoratorTarget));
            }
        }
    }
    public boolean provides(IOperation operation) {
        if (!(operation instanceof CreateDecoratorsOperation)) {
            return false;
        }
        IDecoratorTarget decoratorTarget = ((CreateDecoratorsOperation) operation).getDecoratorTarget();
        IGraphicalEditPart editPart = (IGraphicalEditPart)decoratorTarget.getAdapter(IGraphicalEditPart.class);
        if (editPart instanceof IPrimaryEditPart) {
            EObject eObject = editPart.resolveSemanticElement();
            return  eObject instanceof Class;
        }
        return false;
    }
}
The installed decorator should extend 
org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator. 
The IDecorator#refresh() method is responsible for setting / removing the decoration from the target.
In this example, a NotificationListener is added to the DiagramEventBroker for the element of interest in the 
MyDecorator#activate() method. 
The DiagramEventBroker is a model server listener that broadcasts EObject events to all registered listeners. 
This will allow the listener in the decorator to refresh the decoration whenever the model changes. 
The listener is removed from the element in the MyDecorator#deactivate() 
deactivate method.
The DiagramEventBroker is a model server listener that broadcasts EObject events to all registered listeners.
The MyDecorator#refresh() method has the responsibility 
of setting / removing the decoration from the target. In this example, shape decorations are added using the 
IDecoratorTarget.addShapeDecoration(..) method. Adding shape decorations requires passing a direction for the location of the decoration. 
The available directions are found in the 
IDecoratorTarget.Direction enumeration. The possible directions are: 
CENTER, EAST, NORTH, NORTH_EAST, NORTH_WEST, SOUTH, SOUTH_EAST, SOUTH_WEST, and WEST.
If the decoration target is a connection, use the 
IDecoratorTarget.addConnectionDecoration(..) method to add decorations along any point of the connection.
public class MyDecorator extends AbstractDecorator {
    private final Image ABSTRACT_IMG = 
        ImageDescriptor.createFromURL("file://abstract.gif").createImage();
    private ChangeListener changeListener;
    
    protected EObject notifier;
    
    private class ChangeListener
        implements NotificationListener {
        IDecorator decorator;
        public ChangeListener(IDecorator decorator) {
            this.decorator = decorator;
        }
        public void notifyChanged(Notification evt) {
            if (evt.getFeature() == UMLPackage.eINSTANCE.getClassifier_IsAbstract()) {
                decorator.refresh();
            }
        }
    }
    
    public MyDecorator(IDecoratorTarget decoratorTarget) {
        super(decoratorTarget);
        changeListener = new ChangeListener(this);
    }
    
    public void activate() {
        IGraphicalEditPart editPart = (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
        EObject element = editPart.resolveSemanticElement();
        if (element instanceof Class) {
            notifier = element;
            DiagramEventBroker.getInstance(UMLModeler.getEditingDomain()).
                addNotificationListener(notifier, changeListener);
        }
    }
    
    public void deactivate() {
        if (notifier != null) {
            DiagramEventBroker.getInstance(UMLModeler.getEditingDomain()).
                removeNotificationListener(notifier, changeListener);
            notifier = null;
        }
        super.deactivate();
    }
    
    public void refresh() {
        IGraphicalEditPart editPart = (IGraphicalEditPart) getDecoratorTarget().getAdapter(IGraphicalEditPart.class);
        EObject element = editPart.resolveSemanticElement();
        if (element instanceof Class) {
            Class clazz = (Class)element;
            removeDecoration();
            if (clazz.isAbstract()) {
                setDecoration(getDecoratorTarget().addShapeDecoration(ABSTRACT_IMG, IDecoratorTarget.Direction.NORTH_EAST, 0, false));
            }
        }
    }
}