org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionEditPart.java

Source

/******************************************************************************
 * Copyright (c) 2002, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IBM Corporation - initial API and implementation 
 ****************************************************************************/

package org.eclipse.gmf.runtime.diagram.ui.editparts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineDecoration;
import org.eclipse.draw2d.RelativeBendpoint;
import org.eclipse.draw2d.RotatableDecoration;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.transaction.RunnableWithResult;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gef.AccessibleEditPart;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import org.eclipse.gef.editpolicies.SnapFeedbackPolicy;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.gef.requests.GroupRequest;
import org.eclipse.gef.requests.ReconnectRequest;
import org.eclipse.gef.requests.TargetRequest;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.common.ui.services.action.filter.ActionFilterService;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ConnectionBendpointEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.ConnectionLabelsEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.DecorationEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.EditPolicyRoles;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.PropertyHandlerEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.SemanticEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
import org.eclipse.gmf.runtime.diagram.ui.internal.commands.ToggleCanonicalModeCommand;
import org.eclipse.gmf.runtime.diagram.ui.internal.editparts.IContainedEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.editpolicies.ConnectionEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.editpolicies.ConnectionLineSegEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.editpolicies.TreeConnectionBendpointEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.internal.properties.Properties;
import org.eclipse.gmf.runtime.diagram.ui.internal.ruler.SnapToHelperUtil;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.editpolicy.EditPolicyService;
import org.eclipse.gmf.runtime.diagram.ui.internal.type.NotationTypeUtil;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramColorRegistry;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.preferences.IPreferenceConstants;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateConnectionViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper;
import org.eclipse.gmf.runtime.diagram.ui.services.editpart.EditPartService;
import org.eclipse.gmf.runtime.diagram.ui.util.EditPartUtil;
import org.eclipse.gmf.runtime.draw2d.ui.figures.FigureUtilities;
import org.eclipse.gmf.runtime.draw2d.ui.figures.PolylineConnectionEx;
import org.eclipse.gmf.runtime.draw2d.ui.internal.figures.ConnectionLayerEx;
import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.ForestRouter;
import org.eclipse.gmf.runtime.draw2d.ui.internal.routers.OrthogonalRouter;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
import org.eclipse.gmf.runtime.gef.ui.internal.editpolicies.GraphicalEditPolicyEx;
import org.eclipse.gmf.runtime.gef.ui.internal.l10n.Cursors;
import org.eclipse.gmf.runtime.gef.ui.internal.tools.SelectConnectionEditPartTracker;
import org.eclipse.gmf.runtime.notation.ArrowStyle;
import org.eclipse.gmf.runtime.notation.ArrowType;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.FontStyle;
import org.eclipse.gmf.runtime.notation.JumpLinkStatus;
import org.eclipse.gmf.runtime.notation.JumpLinkType;
import org.eclipse.gmf.runtime.notation.LineStyle;
import org.eclipse.gmf.runtime.notation.LineType;
import org.eclipse.gmf.runtime.notation.LineTypeStyle;
import org.eclipse.gmf.runtime.notation.NotationPackage;
import org.eclipse.gmf.runtime.notation.RelativeBendpoints;
import org.eclipse.gmf.runtime.notation.Routing;
import org.eclipse.gmf.runtime.notation.RoutingStyle;
import org.eclipse.gmf.runtime.notation.Smoothness;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.DeviceResourceException;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.ui.IActionFilter;

/**
 * the base edit part that controls <code>Edge</code> views, it is the basic
 * controller for the connection's view
 * 
 * @author mmostafa
 */
abstract public class ConnectionEditPart extends AbstractConnectionEditPart implements IGraphicalEditPart,
        PropertyChangeListener, IContainedEditPart, IPrimaryEditPart, NotificationListener {

    /** A map of listener filters ids to filter data */
    private Map listenerFilters;

    /** Used for registering and unregistering the edit part */
    private String elementGuid;

    /**
     * Flag to indicate if the edit part is in edit mode
     */
    private boolean isEditable = true;

    /** Used for accessibility. */
    protected AccessibleEditPart accessibleEP;

    /**
     * Cache the editing domain after it is retrieved.
     */
    private TransactionalEditingDomain editingDomain;

    /**
     * Cache the font data when a font is created so that it can be
     * disposed later.
     */
    private FontData cachedFontData;

    /**
    * Cache the answer to whether or not this is a semantic connection after it
    * is retrieved.
    */
    private Boolean semanticConnection;

    /** counter that tracs the recursive depth of the getCommand() method. */
    private static volatile int GETCOMMAND_RECURSIVE_COUNT = 0;

    /** A list of editparts who's canonical editpolicies are to be temporarily disabled. */
    private static Set _disableCanonicalEditPolicyList = new HashSet();

    /**
     * gets a property change command for the passed property, using both of the
     * old and new values
     * 
     * @param property
     *            the property associated with the command
     * @param oldValue
     *            the old value associated with the command
     * @param newValue
     *            the new value associated with the command
     * @return a command
     */
    protected Command getPropertyChangeCommand(Object property, Object oldValue, Object newValue) {
        // by default return null, which means there is no special command to
        // change the property
        return null;
    }

    protected void addChild(EditPart child, int index) {
        super.addChild(child, index);
        if (child instanceof GraphicalEditPart) {
            GraphicalEditPart gEP = (GraphicalEditPart) child;
            boolean editMode = isEditModeEnabled();
            if (editMode != gEP.isEditModeEnabled()) {
                if (editMode)
                    gEP.enableEditMode();
                else
                    gEP.disableEditMode();
            }
        }
    }

    /**
     * Register the adapters for the standard properties.
     */
    static {
        registerAdapters();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.EditPart#activate()
     */
    public void activate() {

        if (isActive()) {
            return;
        }

        addNotationalListeners();

        EObject semanticProxy = ((View) getModel()).getElement();
        EObject semanticElement = EMFCoreUtil.resolve(getEditingDomain(), semanticProxy);

        if (semanticElement != null)
            addSemanticListeners();
        else if (semanticProxy != null) {
            addListenerFilter("SemanticProxy", this, semanticProxy); //$NON-NLS-1$
        }
        super.activate();
    }

    /**
     * Adds a listener filter by adding the given listener to a passed notifier
     * 
     * @param filterId
     *            A unique filter id (within the same editpart instance)
     * @param listener
     *            A listener instance
     * @param notifier
     *            An element notifer to add the listener to
     */
    protected void addListenerFilter(String filterId, NotificationListener listener, EObject element) {

        if (element == null)
            return;

        assert filterId != null;
        assert listener != null;

        if (listenerFilters == null)
            listenerFilters = new HashMap();

        getDiagramEventBroker().addNotificationListener(element, listener);
        listenerFilters.put(filterId, new Object[] { element, listener });
    }

    /**
     * Adds a listener filter by adding the given listener to a passed notifier
     * 
     * @param filterId
     *            A unique filter id (within the same editpart instance)
     * @param listener
     *            A listener instance
     * @param notifier
     *            An element notifer to add the listener to
     */
    protected void addListenerFilter(String filterId, NotificationListener listener, EObject element,
            EStructuralFeature feature) {

        if (element == null)
            return;

        assert filterId != null;
        assert listener != null;

        if (listenerFilters == null)
            listenerFilters = new HashMap();

        getDiagramEventBroker().addNotificationListener(element, feature, listener);
        listenerFilters.put(filterId, new Object[] { element, feature, listener });
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.editparts.AbstractEditPart#createChild(java.lang.Object)
     */
    final protected EditPart createChild(Object model) {
        return EditPartService.getInstance().createGraphicEditPart((View) model);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createConnection(java.lang.Object)
     */
    final protected org.eclipse.gef.ConnectionEditPart createConnection(Object connectionView) {
        return (org.eclipse.gef.ConnectionEditPart) createChild(connectionView);
    }

    /**
     * Overridden to support editpolicies installed programmatically and via the
     * <code>EditPolicyService</code>. Subclasses should override
     * <code>createDefaultEditPolicies()</code>.
     * 
     * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
     */
    final protected void createEditPolicies() {
        createDefaultEditPolicies();
        EditPolicyService.getInstance().createEditPolicies(this);
    }

    /**
     * Should be overridden to install editpolicies programmatically.
     * 
     * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
     */
    protected void createDefaultEditPolicies() {
        installEditPolicy(EditPolicyRoles.SEMANTIC_ROLE, new SemanticEditPolicy());
        installEditPolicy(EditPolicyRoles.PROPERTY_HANDLER_ROLE, new PropertyHandlerEditPolicy());
        installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE,
                new org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy());
        installEditPolicy(EditPolicy.CONNECTION_ROLE, new ConnectionEditPolicy());
        installBendpointEditPolicy();
        installEditPolicy(EditPolicyRoles.DECORATION_ROLE, new DecorationEditPolicy());
        installEditPolicy(EditPolicyRoles.CONNECTION_LABELS_ROLE, new ConnectionLabelsEditPolicy());

        installEditPolicy(EditPolicyRoles.SNAP_FEEDBACK_ROLE, new SnapFeedbackPolicy());
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.EditPart#deactivate()
     */
    public void deactivate() {

        if (!isActive()) {
            return;
        }

        boolean wasActive = isActive();
        super.deactivate();
        if (listenerFilters != null && wasActive != isActive()) {
            for (Iterator i = listenerFilters.keySet().iterator(); i.hasNext();) {
                Object[] obj = (Object[]) listenerFilters.get(i.next());
                if (obj.length > 2) {
                    getDiagramEventBroker().removeNotificationListener((EObject) obj[0],
                            (EStructuralFeature) obj[1], (NotificationListener) obj[2]);
                } else {
                    getDiagramEventBroker().removeNotificationListener((EObject) obj[0],
                            (NotificationListener) obj[1]);
                }
            }
        }
        getConnectionFigure().getConnectionRouter().remove(getConnectionFigure());
    }

    public void removeNotify() {
        super.removeNotify();

        if (cachedFontData != null) {
            getResourceManager().destroyFont(FontDescriptor.createFrom(cachedFontData));
            cachedFontData = null;
        }
    }

    /**
     * executes the passed command
     * 
     * @param command
     *            the command to execute
     */
    protected void executeCommand(Command command) {
        getEditDomain().getCommandStack().execute(command);
    }

    /**
     * a function that registers this provider with the Eclipse AdapterManager
     * as an IView and an IActionFilter adapter factory for the
     * IGraphicalEditPart nodes
     * 
     */
    static private void registerAdapters() {
        Platform.getAdapterManager().registerAdapters(new IAdapterFactory() {

            /**
             * @see org.eclipse.core.runtime.IAdapterFactory
             */
            public Object getAdapter(Object adaptableObject, Class adapterType) {

                IGraphicalEditPart gep = (IGraphicalEditPart) adaptableObject;

                if (adapterType == IActionFilter.class) {
                    return ActionFilterService.getInstance();
                } else if (adapterType == View.class) {
                    return gep.getModel();
                }
                return null;
            }

            /**
             * @see org.eclipse.core.runtime.IAdapterFactory
             */
            public Class[] getAdapterList() {
                return new Class[] { IActionFilter.class, View.class };
            }

        }, IGraphicalEditPart.class);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.editparts.AbstractEditPart#getAccessibleEditPart()
     */
    protected AccessibleEditPart getAccessibleEditPart() {
        if (accessibleEP == null) {
            accessibleEP = new AccessibleGraphicalEditPart() {

                private String getSemanticName() {
                    EObject semanticElement = resolveSemanticElement();

                    if (semanticElement != null) {
                        String name = semanticElement.getClass().getName();
                        int startIndex = name.lastIndexOf('.') + 1;
                        int endIndex = name.lastIndexOf("Impl"); //$NON-NLS-1$
                        return name.substring(startIndex, endIndex);
                    }

                    return DiagramUIMessages.Accessible_Connection_Label;
                }

                public void getName(AccessibleEvent e) {

                    EditPart sourceEP = getSource();
                    EditPart targetEP = getTarget();

                    // Get the Connection Name
                    String connectionName = getSemanticName();

                    // Get the Source Name
                    String sourceName = null;
                    if (sourceEP != null) {
                        AccessibleEditPart aEP = (AccessibleEditPart) sourceEP.getAdapter(AccessibleEditPart.class);
                        AccessibleEvent event = new AccessibleEvent(this);
                        aEP.getName(event);
                        sourceName = event.result;
                    }

                    // Get the Target Name
                    String targetName = null;
                    if (targetEP != null) {
                        AccessibleEditPart aEP = (AccessibleEditPart) targetEP.getAdapter(AccessibleEditPart.class);
                        AccessibleEvent event = new AccessibleEvent(this);
                        aEP.getName(event);
                        targetName = event.result;
                    }

                    if (sourceName != null && targetName != null) {
                        e.result = NLS.bind(DiagramUIMessages.Accessible_Connection_From_Source_To_Target,
                                new Object[] { connectionName, sourceName, targetName });
                    } else if (sourceName != null) {
                        e.result = NLS.bind(DiagramUIMessages.Accessible_Connection_From_Source,
                                new Object[] { connectionName, sourceName });
                    } else if (targetName != null) {
                        e.result = NLS.bind(DiagramUIMessages.Accessible_Connection_To_Target,
                                new Object[] { connectionName, targetName });
                    } else {
                        e.result = connectionName;
                    }
                }
            };
        }
        return accessibleEP;
    }

    /**
     * Adds the ability to adapt to this editpart's view class.
     */
    public Object getAdapter(Class key) {
        Object adapter = Platform.getAdapterManager().getAdapter(this, key);
        if (adapter != null) {
            return adapter;
        }

        if (key == SnapToHelper.class) {
            return SnapToHelperUtil.getSnapHelper((org.eclipse.gef.GraphicalEditPart) this.getSource());
        }

        Object model = getModel();

        if (View.class.isAssignableFrom(key) && key.isInstance(model)) {
            return model;
        }

        if (model != null && model instanceof View) {
            // Adapt to semantic element
            EObject semanticObject = ViewUtil.resolveSemanticElement((View) model);
            if (key.isInstance(semanticObject)) {
                return semanticObject;
            } else if (key.isInstance(model)) {
                return model;
            }
        }
        return super.getAdapter(key);
    }

    /**
     * Method getChildBySemanticHint.
     * 
     * @param semanticHint
     * @return IGraphicalEditPart
     */
    public IGraphicalEditPart getChildBySemanticHint(String semanticHint) {
        if (getModel() != null) {
            View view = ViewUtil.getChildBySemanticHint((View) getModel(), semanticHint);
            if (view != null)
                return (IGraphicalEditPart) getViewer().getEditPartRegistry().get(view);
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.EditPart#getCommand(org.eclipse.gef.Request)
     */
    public Command getCommand(Request _request) {
        if (!isEditModeEnabled()) {
            return UnexecutableCommand.INSTANCE;
        }

        Command cmd = null;
        try {
            GETCOMMAND_RECURSIVE_COUNT++;
            final Request request = _request;
            try {
                cmd = (Command) getEditingDomain().runExclusive(new RunnableWithResult.Impl() {

                    public void run() {
                        setResult(ConnectionEditPart.super.getCommand(request));
                    }
                });
            } catch (InterruptedException e) {
                Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                        "getCommand", e); //$NON-NLS-1$
                Log.error(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
                        "getCommand", e); //$NON-NLS-1$
            }

            if (cmd != null) {
                _disableCanonicalEditPolicyList.addAll(disableCanonicalFor(_request));
            }

            GETCOMMAND_RECURSIVE_COUNT--;

            if (GETCOMMAND_RECURSIVE_COUNT == 0) {
                if (cmd != null && !_disableCanonicalEditPolicyList.isEmpty()) {
                    CompoundCommand cc = new CompoundCommand();
                    cc.setLabel(cmd.getLabel());
                    ToggleCanonicalModeCommand tcmd = ToggleCanonicalModeCommand
                            .getToggleCanonicalModeCommand(_disableCanonicalEditPolicyList, false);
                    cc.add(tcmd);
                    cc.add(cmd);
                    ToggleCanonicalModeCommand tcmd2 = ToggleCanonicalModeCommand
                            .getToggleCanonicalModeCommand(tcmd, true);
                    if (tcmd2 != null) {
                        tcmd2.setDomain(getEditingDomain());
                    }
                    cc.add(tcmd2);
                    _disableCanonicalEditPolicyList.clear();
                    return cc.unwrap();
                }
            }
        } catch (RuntimeException t) {
            GETCOMMAND_RECURSIVE_COUNT = 0;
            throw t;
        }
        return cmd;
    }

    /**
     * Return a list of editparts who's canonical editpolicies should be disabled
     * prior to executing the commands associated to the supplied request.
     * This implementation will return the editpart honoring a <code>SemanticWrapperRequest</code>
     * and a <code>CreateConnectionViewRequest</code>'s source and target editparts.
     *
     * @param request a request that has returned a command.
     * @return list of editparts.
     */
    protected Collection disableCanonicalFor(final Request request) {
        //
        // not the most generic of solution; however, it will have to do for now...
        //
        // Alternate solutions
        // 1. common request interface on all the requests
        //  IRequest#getAffectedEditParts
        //
        // 2. Traverse down the command and collect of the ICommand#getAffectedObjects()
        //  -- this requires that all our commands properly set this value.

        Set hosts = new HashSet();
        if ((request instanceof EditCommandRequestWrapper) || request instanceof TargetRequest
                || request instanceof DropRequest) {
            hosts.add(this);
            hosts.add(getParent());
        }
        if ((request instanceof ReconnectRequest)) {
            ReconnectRequest reconnect = (ReconnectRequest) request;
            hosts.add(this);
            hosts.add(getParent());
            if (reconnect.getTarget() != null) {
                EditPart target = reconnect.getTarget();
                addEditPartAndParent(hosts, target);
            }
            if (reconnect.getConnectionEditPart() != null) {
                org.eclipse.gef.ConnectionEditPart connectionEditPart = reconnect.getConnectionEditPart();
                if (connectionEditPart.getSource() != null) {
                    EditPart srcEP = connectionEditPart.getSource();
                    addEditPartAndParent(hosts, srcEP);
                }
                if (connectionEditPart.getTarget() != null) {
                    EditPart trgEP = connectionEditPart.getTarget();
                    addEditPartAndParent(hosts, trgEP);
                }
            }
        }
        if ((request instanceof CreateConnectionRequest)) {
            CreateConnectionRequest ccvr = (CreateConnectionRequest) request;
            hosts.add(this);
            hosts.add(getParent());
            if (ccvr.getSourceEditPart() != null) {
                hosts.add(ccvr.getSourceEditPart());
                hosts.add(ccvr.getSourceEditPart().getParent());
            }
            if (ccvr.getTargetEditPart() != null) {
                hosts.add(ccvr.getTargetEditPart());
                hosts.add(ccvr.getTargetEditPart().getParent());
            }
        }
        if ((request instanceof GroupRequest)) {
            List parts = ((GroupRequest) request).getEditParts();
            hosts.add(this);
            hosts.add(getParent());

            Iterator editparts = parts == null ? Collections.EMPTY_LIST.iterator() : parts.iterator();
            while (editparts.hasNext()) {
                EditPart ep = (EditPart) editparts.next();
                addEditPartAndParent(hosts, ep);
            }
        }

        /////////////////////////////////////////////////////////////
        // This following behavior is specific to BorderItemEditPart and
        // AbstractBorderItemEditPart, but we do not want to allow clients to
        // override this method so we do not want to make it protected.

        if (this instanceof IBorderItemEditPart) {
            if ((request instanceof CreateConnectionViewRequest)) {
                CreateConnectionViewRequest ccvr = (CreateConnectionViewRequest) request;
                if (ccvr.getSourceEditPart() instanceof IBorderItemEditPart) {
                    hosts.add(ccvr.getSourceEditPart().getParent().getParent());
                }
                if (ccvr.getTargetEditPart() instanceof IBorderItemEditPart) {
                    hosts.add(ccvr.getTargetEditPart().getParent().getParent());
                }
            }
        }
        /////////////////////////////////////////////////////////////

        return hosts;
    }

    private void addEditPartAndParent(Set hosts, EditPart editPart) {
        hosts.add(editPart);
        hosts.add(editPart.getParent());
    }

    /**
     * Convenience method returning the editpart's Diagram, the Diagam that owns
     * the edit part
     * 
     * @return the diagram
     */
    protected Diagram getDiagramView() {
        return ((View) getRoot().getContents().getModel()).getDiagram();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#getPrimaryView()
     */
    public View getPrimaryView() {
        if (this instanceof IPrimaryEditPart && getModel() instanceof View) {
            return (View) getModel();
        } else {
            for (EditPart ep = getParent(); ep != null; ep = ep.getParent()) {
                if (ep instanceof IGraphicalEditPart && ep.getModel() instanceof View) {
                    return ((IGraphicalEditPart) ep).getPrimaryView();
                }
            }
        }
        return null;
    }

    /**
     * Convenience method returning the editpart's edit domain. Same as calling
     * <code>getRoot().getViewer().getEditDomain()</code>
     * 
     * @return the edit domain
     */
    protected EditDomain getEditDomain() {
        return getRoot().getViewer().getEditDomain();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#getDiagramEditDomain()
     */
    public IDiagramEditDomain getDiagramEditDomain() {
        return (IDiagramEditDomain) getEditDomain();
    }

    /**
     * Return this editpart's view (model) children.
     * 
     * @return list of views.
     */
    protected List getModelChildren() {
        return new ArrayList(((View) getModel()).getChildren());
    }

    /**
     * Convenience method to retreive the value for the supplied value from the
     * editpart's associated view element. Same as calling
     * <code> ViewUtil.getStructuralFeatureValue(getNotationView(),feature)</code>.
     */
    public Object getStructuralFeatureValue(EStructuralFeature feature) {
        return ViewUtil.getStructuralFeatureValue((View) getModel(), feature);
    }

    /**
     * try to resolve the semantic element and Return the resolven element; if
     * the element is unresolvable or null it will return null
     * 
     * @return non proxy EObject or NULL
     */
    public EObject resolveSemanticElement() {
        EObject eObj = ((View) getModel()).getElement();
        if (eObj == null) {
            return null;
        }

        if (!eObj.eIsProxy()) {
            return eObj;
        }

        try {
            return (EObject) getEditingDomain().runExclusive(new RunnableWithResult.Impl() {

                public void run() {
                    setResult(ViewUtil.resolveSemanticElement((View) getModel()));
                }
            });
        } catch (InterruptedException e) {
            Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                    "resolveSemanticElement", e); //$NON-NLS-1$
            Log.error(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
                    "resolveSemanticElement", e); //$NON-NLS-1$
            return null;
        }
    }

    /**
     * Walks up the editpart hierarchy to find and return the
     * <code>TopGraphicEditPart</code> instance.
     */
    public TopGraphicEditPart getTopGraphicEditPart() {
        EditPart editPart = this;
        while (editPart instanceof IGraphicalEditPart) {
            if (editPart instanceof TopGraphicEditPart)
                return (TopGraphicEditPart) editPart;
            editPart = editPart.getParent();
        }
        return null;
    }

    /**
     * Return the editpart's associated Notation View.
     * 
     * @return <code>View</code>, the associated view or null if there is no
     *         associated Notation View
     */
    public View getNotationView() {
        Object model = getModel();
        if (model instanceof View)
            return (View) model;
        return null;
    }

    /**
     * Handles the passed property changed event only if the editpart's view is
     * not deleted
     */
    public final void propertyChange(PropertyChangeEvent event) {
        if (isActive())
            handlePropertyChangeEvent(event);
    }

    /**
     * Handles the property changed event. Clients should override to respond to
     * the specific notification events they are interested.
     * 
     * Note: This method may get called on a non-UI thread. Clients should
     * either ensure that their code is thread safe and/or doesn't make
     * unsupported calls (i.e. Display.getCurrent() ) assuming they are on the
     * main thread. Alternatively if this is not possible, then the client can
     * wrap their handler within the Display.synchExec runnable to ensure
     * synchronization and subsequent execution on the main thread.
     * 
     * @param event
     *            the <code>Notification</code> object that is the property
     *            changed event
     */
    protected void handlePropertyChangeEvent(PropertyChangeEvent event) {
        if (event.getPropertyName().equals(Connection.PROPERTY_CONNECTION_ROUTER)) {
            installRouter();
        }
    }

    /**
     * Method reactivateSemanticModel. This method reactivates the edit part's
     * emantic model by: 1- removing semantic listeners 2- adding semantic
     * listeners if the semantic reference is resolvable 3- Refreshing it
     * 
     * This method is called in response to IView's Properties.ID_SEMANTICREF
     * property change event However, it will only work under the following
     * assumptions: 1- The old and new semantic models are compatible in their
     * kind 2- The deltas between old and new semantic models do not affect
     * notation 3- Connections are not refereshed since they are maintained by
     * the diagram
     */
    public void reactivateSemanticModel() {
        removeSemanticListeners();
        if (resolveSemanticElement() != null)
            addSemanticListeners();
        refresh();
    }

    /** Finds an editpart given a starting editpart and an EObject */
    public EditPart findEditPart(EditPart epBegin, EObject theElement) {
        if (theElement == null) {
            return null;
        }
        EditPart epStart = null;
        if (epBegin == null) {
            epStart = this;
        } else {
            epStart = epBegin;
        }

        final View view = (View) ((IAdaptable) epStart).getAdapter(View.class);

        if (view != null) {
            EObject el = ViewUtil.resolveSemanticElement(view);

            if ((el != null) && el.equals(theElement)) {
                return epStart;
            }
        }

        ListIterator childLI = epStart.getChildren().listIterator();
        while (childLI.hasNext()) {
            EditPart epChild = (EditPart) childLI.next();

            EditPart elementEP = findEditPart(epChild, theElement);
            if (elementEP != null) {
                return elementEP;
            }
        }
        return null;
    }

    /**
     * Refresh the editpart's figure foreground colour.
     */
    protected void refreshForegroundColor() {
        LineStyle style = (LineStyle) getPrimaryView().getStyle(NotationPackage.Literals.LINE_STYLE);
        if (style != null)
            setForegroundColor(DiagramColorRegistry.getInstance().getColor(Integer.valueOf(style.getLineColor())));
    }

    /**
     * Refresh the editpart's figure visibility.
     */
    protected void refreshVisibility() {
        setVisibility(((View) getModel()).isVisible());
    }

    /**
     * Removes a listener previously added with the given id
     * 
     * @param filterId
     *            the filiter ID
     */
    protected void removeListenerFilter(String filterId) {
        if (listenerFilters == null)
            return;

        Object[] objects = (Object[]) listenerFilters.get(filterId);
        if (objects == null) {
            return;
        }

        if (objects.length > 2) {
            getDiagramEventBroker().removeNotificationListener((EObject) objects[0],
                    (EStructuralFeature) objects[1], (NotificationListener) objects[2]);
        } else {
            getDiagramEventBroker().removeNotificationListener((EObject) objects[0],
                    (NotificationListener) objects[1]);
        }
        listenerFilters.remove(filterId);
    }

    /**
     * sets the forefround color of the editpart's figure
     * 
     * @param color
     *            the color
     */
    protected void setForegroundColor(Color color) {
        getFigure().setForegroundColor(color);
    }

    /**
     * Sets the passed feature if possible on this editpart's view to the passed
     * value.
     * 
     * @param feature
     *            the feature to use
     * @param value
     *            the value of the property being set
     */
    public void setStructuralFeatureValue(EStructuralFeature feature, Object value) {
        ViewUtil.setStructuralFeatureValue((View) getModel(), feature, value);
    }

    /**
     * sets the edit part's visibility
     * 
     * @param vis
     *            the new visibilty value
     */
    protected void setVisibility(boolean vis) {
        if (!vis && getSelected() != SELECTED_NONE)
            getViewer().deselect(this);
        getFigure().setVisible(vis);
        getFigure().revalidate();
    }

    /**
     * This method adds all listeners to the notational world (views, figures,
     * editpart...etc) Override this method to add more notational listeners
     * down the hierarchy
     */
    protected void addNotationalListeners() {
        addListenerFilter("View", this, (View) getModel());//$NON-NLS-1$
        getFigure().addPropertyChangeListener(Connection.PROPERTY_CONNECTION_ROUTER, this);
    }

    /**
     * This method adds all listeners to the semantic element behind this
     * EditPart Override this method to add more semantic listeners down the
     * hierarchy This method is called only if the semantic element is
     * resolvable
     */
    protected void addSemanticListeners() {
        addListenerFilter("SemanticModel", //$NON-NLS-1$
                this, resolveSemanticElement());
    }

    /**
     * This method removes all listeners to the notational world (views,
     * figures, editpart...etc) Override this method to remove notational
     * listeners down the hierarchy
     */
    protected void removeNotationalListeners() {
        getFigure().removePropertyChangeListener(Connection.PROPERTY_CONNECTION_ROUTER, this);
        removeListenerFilter("View");//$NON-NLS-1$
    }

    /**
     * This method removes all listeners to the semantic element behind this
     * EditPart Override this method to remove semantic listeners down the
     * hierarchy
     */
    protected void removeSemanticListeners() {
        removeListenerFilter("SemanticModel");//$NON-NLS-1$
    }

    /**
     * @see org.eclipse.gef.EditPart#addNotify()
     */
    public void addNotify() {
        super.addNotify();
        installRouter();
    }

    /**
     * a static array of appearance property ids applicable to the connections
     */
    protected static final String[] appearanceProperties = new String[] { Properties.ID_FONTNAME,
            Properties.ID_FONTSIZE, Properties.ID_FONTBOLD, Properties.ID_FONTITALIC, Properties.ID_FONTCOLOR,
            Properties.ID_LINECOLOR };

    /**
     * construcotr
     * 
     * @param view ,
     *            the view the edit part will own
     */
    public ConnectionEditPart(View view) {
        setModel(view);
    }

    /**
     * Method createConnectionFigure.
     * 
     * @return a <code>Connection</code> figure
     */
    abstract protected Connection createConnectionFigure();

    final protected IFigure createFigure() {
        return createConnectionFigure();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.EditPart#refresh()
     */
    public void refresh() {
        if (getSource() != null && getTarget() != null) {
            try {
                getEditingDomain().runExclusive(new Runnable() {

                    public void run() {
                        ConnectionEditPart.super.refresh();
                        EditPolicyIterator i = getEditPolicyIterator();
                        while (i.hasNext()) {
                            EditPolicy policy = i.next();
                            if (policy instanceof GraphicalEditPolicyEx) {
                                ((GraphicalEditPolicyEx) policy).refresh();
                            }
                        }
                    }
                });
            } catch (InterruptedException e) {
                Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                        "refresh", e); //$NON-NLS-1$
                Log.error(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING, "refresh", //$NON-NLS-1$
                        e);
            }
        }
    }

    /**
     * utility method to get the <code>Edge</code> view
     * 
     * @return the <code>Edge</code>
     */
    protected Edge getEdge() {
        return (Edge) getModel();
    }

    /*
     * @see AbstractEditPart#getDragTracker(Request)
     */
    public DragTracker getDragTracker(Request req) {
        return new SelectConnectionEditPartTracker(this);
    }

    /**
     * give access to the source of the edit part's Edge
     * 
     * @return the source
     */
    protected Object getModelSource() {
        return getEdge().getSource();
    }

    /**
     * give access to the target of the edit part's Edge
     * 
     * @return the target
     */
    protected Object getModelTarget() {
        return getEdge().getTarget();
    }

    /**
     * installes a router on the edit part, depending on the
     * <code>RoutingStyle</code>
     */
    protected void installRouter() {
        ConnectionLayer cLayer = (ConnectionLayer) getLayer(LayerConstants.CONNECTION_LAYER);
        RoutingStyle style = (RoutingStyle) ((View) getModel()).getStyle(NotationPackage.Literals.ROUTING_STYLE);

        if (style != null && cLayer instanceof ConnectionLayerEx) {

            ConnectionLayerEx cLayerEx = (ConnectionLayerEx) cLayer;
            Routing routing = style.getRouting();
            if (Routing.MANUAL_LITERAL == routing) {
                getConnectionFigure().setConnectionRouter(cLayerEx.getObliqueRouter());
            } else if (Routing.RECTILINEAR_LITERAL == routing) {
                getConnectionFigure().setConnectionRouter(cLayerEx.getRectilinearRouter());
            } else if (Routing.TREE_LITERAL == routing) {
                getConnectionFigure().setConnectionRouter(cLayerEx.getTreeRouter());
            }

        }

        refreshRouterChange();
    }

    /**
     * refresh the pendpoints owned by the EditPart's <code>Edge</code>
     */
    protected void refreshBendpoints() {
        RelativeBendpoints bendpoints = (RelativeBendpoints) getEdge().getBendpoints();
        List modelConstraint = bendpoints.getPoints();
        List figureConstraint = new ArrayList();
        for (int i = 0; i < modelConstraint.size(); i++) {
            org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint wbp = (org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint) modelConstraint
                    .get(i);
            RelativeBendpoint rbp = new RelativeBendpoint(getConnectionFigure());
            rbp.setRelativeDimensions(new Dimension(wbp.getSourceX(), wbp.getSourceY()),
                    new Dimension(wbp.getTargetX(), wbp.getTargetY()));
            if (modelConstraint.size() == 1) {
                rbp.setWeight(0.5f);
            } else {
                rbp.setWeight(i / ((float) modelConstraint.size() - 1));
            }
            figureConstraint.add(rbp);
        }
        getConnectionFigure().setRoutingConstraint(figureConstraint);
    }

    private void installBendpointEditPolicy() {
        if (getConnectionFigure().getConnectionRouter() instanceof ForestRouter) {
            installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new TreeConnectionBendpointEditPolicy());
        } else if (getConnectionFigure().getConnectionRouter() instanceof OrthogonalRouter) {
            installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new ConnectionLineSegEditPolicy());
        } else {
            installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new ConnectionBendpointEditPolicy());
        }

        EditPartUtil.synchronizeRunnableToMainThread(this, new Runnable() {

            public void run() {
                if (getConnectionFigure().getConnectionRouter() instanceof ForestRouter) {
                    getConnectionFigure().setCursor(Cursors.CURSOR_SEG_MOVE);
                } else if (getConnectionFigure().getConnectionRouter() instanceof OrthogonalRouter) {
                    getConnectionFigure().setCursor(Cursors.CURSOR_SEG_MOVE);
                } else {
                    getConnectionFigure().setCursor(Cursors.CURSOR_SEG_ADD);
                }
            };
        });
    }

    /**
     * Method refreshRouterChange.
     */
    protected void refreshRouterChange() {
        refreshBendpoints();
        installBendpointEditPolicy();
    }

    /**
     * Method refreshSmoothness.
     */
    protected void refreshSmoothness() {
        Connection connection = getConnectionFigure();
        if (!(connection instanceof PolylineConnectionEx))
            return;

        PolylineConnectionEx poly = (PolylineConnectionEx) connection;
        RoutingStyle style = (RoutingStyle) ((View) getModel()).getStyle(NotationPackage.Literals.ROUTING_STYLE);
        if (style != null) {
            Smoothness smoothness = style.getSmoothness();

            if (Smoothness.LESS_LITERAL == smoothness) {
                poly.setSmoothness(PolylineConnectionEx.SMOOTH_LESS);
            } else if (Smoothness.NORMAL_LITERAL == smoothness) {
                poly.setSmoothness(PolylineConnectionEx.SMOOTH_NORMAL);
            } else if (Smoothness.MORE_LITERAL == smoothness) {
                poly.setSmoothness(PolylineConnectionEx.SMOOTH_MORE);
            } else if (Smoothness.NONE_LITERAL == smoothness) {
                poly.setSmoothness(PolylineConnectionEx.SMOOTH_NONE);
            }
        }
    }

    /**
     * Refreshes raduis for rounding bendpoints in rectilinear routing (radius
     * smaller than 1 indicates that bendpoints should not be rounded).
     * 
     * @since 1.2
     */
    protected void refreshRoundedBendpoints() {
        Connection connection = getConnectionFigure();
        if (!(connection instanceof PolylineConnectionEx))
            return;

        RoutingStyle style = (RoutingStyle) ((View) getModel()).getStyle(NotationPackage.Literals.ROUTING_STYLE);
        if (style != null) {
            PolylineConnectionEx poly = (PolylineConnectionEx) connection;
            poly.setRoundedBendpointsRadius(style.getRoundedBendpointsRadius());
        }
    }

    /**
     * Method refreshJumplinks.
     */
    protected void refreshJumplinks() {
        Connection connection = getConnectionFigure();
        if (!(connection instanceof PolylineConnectionEx))
            return;

        PolylineConnectionEx poly = (PolylineConnectionEx) connection;
        RoutingStyle style = (RoutingStyle) ((View) getModel()).getStyle(NotationPackage.Literals.ROUTING_STYLE);

        JumpLinkStatus status = JumpLinkStatus.NONE_LITERAL;
        JumpLinkType type = JumpLinkType.SEMICIRCLE_LITERAL;
        boolean reverse = false;
        if (style != null) {
            status = style.getJumpLinkStatus();
            type = style.getJumpLinkType();
            reverse = style.isJumpLinksReverse();
        }

        int jumpType = 0;
        if (JumpLinkStatus.BELOW_LITERAL == status) {
            jumpType = PolylineConnectionEx.JUMPLINK_FLAG_BELOW;
        } else if (JumpLinkStatus.ABOVE_LITERAL == status) {
            jumpType = PolylineConnectionEx.JUMPLINK_FLAG_ABOVE;
        } else if (JumpLinkStatus.ALL_LITERAL == status) {
            jumpType = PolylineConnectionEx.JUMPLINK_FLAG_ALL;
        }

        boolean bCurved = type.equals(JumpLinkType.SEMICIRCLE_LITERAL);
        boolean bAngleIn = !type.equals(JumpLinkType.SQUARE_LITERAL);
        boolean bOnBottom = reverse;

        poly.setJumpLinks(jumpType != 0);
        poly.setJumpLinksStyles(jumpType, bCurved, bAngleIn, bOnBottom);
    }

    /**
     * Method refreshRoutingStyles.
     */
    protected void refreshRoutingStyles() {
        Connection connection = getConnectionFigure();
        if (!(connection instanceof PolylineConnectionEx))
            return;

        PolylineConnectionEx poly = (PolylineConnectionEx) connection;

        RoutingStyle style = (RoutingStyle) ((View) getModel()).getStyle(NotationPackage.Literals.ROUTING_STYLE);
        if (style != null) {

            boolean closestDistance = style.isClosestDistance();
            boolean avoidObstruction = style.isAvoidObstructions();

            poly.setRoutingStyles(closestDistance, avoidObstruction);

            if (avoidObstruction)
                installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, null);
            else
                installBendpointEditPolicy();

        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
     */
    protected void refreshVisuals() {
        super.refreshVisuals();
        refreshVisibility();
        refreshForegroundColor();
        refreshRoutingStyles();
        refreshSmoothness();
        refreshRoundedBendpoints();
        refreshJumplinks();
        refreshBendpoints();
        refreshFont();
    }

    /**
     * Refresh the editpart's figure font.
     */
    protected void refreshFont() {
        FontStyle style = (FontStyle) getPrimaryView().getStyle(NotationPackage.Literals.FONT_STYLE);
        if (style != null) {
            setFont(new FontData(style.getFontName(), style.getFontHeight(),
                    (style.isBold() ? SWT.BOLD : SWT.NORMAL) | (style.isItalic() ? SWT.ITALIC : SWT.NORMAL)));
        }
    }

    /**
     * Sets the font to the label. This method could be overriden to change the
     * font data of the font overrides typically look like this: super.setFont(
     * new FontData( fontData.getName(), fontData.getHeight(),
     * fontData.getStyle() <| &> SWT.????));
     * 
     * @param fontData
     *            the font data
     */
    protected void setFont(FontData fontData) {
        if (cachedFontData != null && cachedFontData.equals(fontData)) {
            // the font was previously set and has not changed; do nothing.
            return;
        }

        try {
            Font newFont = getResourceManager().createFont(FontDescriptor.createFrom(fontData));
            getFigure().setFont(newFont);
            getFigure().repaint();

            if (cachedFontData != null) {
                getResourceManager().destroyFont(FontDescriptor.createFrom(cachedFontData));
            }
            cachedFontData = fontData;
        } catch (DeviceResourceException e) {
            Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                    "setFont", e); //$NON-NLS-1$
            Log.error(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING, "setFont", e); //$NON-NLS-1$
        }
    }

    /**
     * Returns an array of the appearance property ids applicable to the
     * receiver. Fro this type it is Properties.ID_FONT,
     * Properties.ID_FONTCOLOR, Properties.ID_LINECOLOR
     * 
     * @return - an array of the appearane property ids applicable to the
     *         receiver
     */
    protected String[] getAppearancePropertyIDs() {
        return appearanceProperties;
    }

    /**
     * Perform a request by executing a command from the target editpart of the
     * request For the Direct_Edit request, we need to show up an editor first
     * 
     * @see org.eclipse.gef.EditPart#performRequest(org.eclipse.gef.Request)
     */
    public void performRequest(Request request) {
        if (!isEditModeEnabled()) {
            return;
        }

        if (RequestConstants.REQ_DIRECT_EDIT == request.getType()) {
            performDirectEditRequest(request);
        } else {
            EditPart targetEditPart = getTargetEditPart(request);
            if (targetEditPart != null) {
                Command command = targetEditPart.getCommand(request);
                if (command != null) {
                    getDiagramEditDomain().getDiagramCommandStack().execute(command);
                    return;
                }
            }
        }
    }

    /**
     * Performs a direct edit request (usually by showing some type of editor)
     * 
     * @param request
     *            the direct edit request
     */
    protected void performDirectEditRequest(Request request) {
        try {
            EditPart primaryChildEditPart = (EditPart) getEditingDomain()
                    .runExclusive(new RunnableWithResult.Impl() {

                        public void run() {
                            setResult(getPrimaryChildEditPart());
                        }
                    });
            if (primaryChildEditPart != null) {
                primaryChildEditPart.performRequest(request);
            }

        } catch (InterruptedException e) {
            Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
                    "performDirectEditRequest", e); //$NON-NLS-1$
            Log.error(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING,
                    "performDirectEditRequest", e); //$NON-NLS-1$
        }

    }

    /**
     * @see org.eclipse.gef.EditPart#understandsRequest(org.eclipse.gef.Request)
     */
    public boolean understandsRequest(Request req) {
        return RequestConstants.REQ_DIRECT_EDIT == req.getType() || super.understandsRequest(req);
    }

    /** Adds a [ref, editpart] mapping to the EditPartForElement map. */
    protected void registerModel() {
        super.registerModel();

        // Save the elements Guid to use during unregister
        EObject ref = ((View) getModel()).getElement();
        if (ref == null) {
            return;
        }

        elementGuid = EMFCoreUtil.getProxyID(ref);

        ((IDiagramGraphicalViewer) getViewer()).registerEditPartForElement(elementGuid, this);
    }

    /** Remove this editpart from the EditPartForElement map. */
    protected void unregisterModel() {
        super.unregisterModel();

        ((IDiagramGraphicalViewer) getViewer()).unregisterEditPartForElement(elementGuid, this);
    }

    /**
     * Handles the case where the semantic reference has changed.
     */
    protected final void handleMajorSemanticChange() {
        if (getSource() instanceof GraphicalEditPart && getTarget() instanceof GraphicalEditPart) {
            ((GraphicalEditPart) getSource()).refreshSourceConnection(this);
            ((GraphicalEditPart) getTarget()).refreshTargetConnection(this);
        }
    }

    /**
     * Refreshes a child editpart by removing it and refreshing children
     * 
     * @param child
     */
    final void refreshChild(GraphicalEditPart child) {
        removeChild(child);
        refreshChildren();
    }

    /**
     * check if there is a canonical edit policy installed on the edit part or
     * not
     * 
     * @return <tt>true</tt> if a canonical editpolicy has been installed on
     *         this editpart; otherwise <tt>false</tt>
     */
    public final boolean isCanonical() {
        return getEditPolicy(EditPolicyRoles.CANONICAL_ROLE) != null;
    }

    /**
     * checks if the edit part's figure is visible or not
     * 
     * @return <tt>true</tt> if the editpart's figure is visible;
     *         <tt>false</tt> otherwise.
     */
    public boolean isSelectable() {
        return getFigure().isVisible();
    }

    /*
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#disableEditMode()
     */
    public void disableEditMode() {
        if (isEditable == false) {
            return;
        }

        List l = getSourceConnections();
        int size = l.size();
        for (int i = 0; i < size; i++) {
            Object obj = l.get(i);
            if (obj instanceof IEditableEditPart) {
                ((IEditableEditPart) obj).disableEditMode();
            }
        }

        List c = getChildren();
        size = c.size();
        for (int i = 0; i < size; i++) {
            Object obj = c.get(i);
            if (obj instanceof IEditableEditPart) {
                ((IEditableEditPart) obj).disableEditMode();
            }
        }

        isEditable = false;
    }

    /*
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#enableEditMode()
     */
    public void enableEditMode() {
        if (isEditable) {
            return;
        }
        isEditable = true;
        List c = getChildren();
        int size = c.size();
        for (int i = 0; i < size; i++) {
            Object obj = c.get(i);
            if (obj instanceof IEditableEditPart) {
                ((IEditableEditPart) obj).enableEditMode();
            }
        }

        List l = getSourceConnections();
        size = l.size();
        for (int i = 0; i < size; i++) {
            Object obj = l.get(i);
            if (obj instanceof IEditableEditPart) {
                ((IEditableEditPart) obj).enableEditMode();
            }
        }
    }

    /*
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#isEditModeEnabled()
     */
    public boolean isEditModeEnabled() {
        // protect against deadlock - don't allow any action while write
        // transaction
        // is active on another thread
        if (EditPartUtil.isWriteTransactionInProgress(this, true, true))
            return false;
        return isEditable;
    }

    /*
     * @see org.eclipse.gef.EditPart#showSourceFeedback(org.eclipse.gef.Request)
     */
    public void showSourceFeedback(Request request) {
        if (!isEditModeEnabled()) {
            return;
        }

        super.showSourceFeedback(request);
    }

    /*
     * @see org.eclipse.gef.EditPart#showTargetFeedback(org.eclipse.gef.Request)
     */
    public void showTargetFeedback(Request request) {
        if (!isEditModeEnabled()) {
            return;
        }

        super.showTargetFeedback(request);
    }

    /*
     * @see org.eclipse.gef.EditPart#eraseSourceFeedback(org.eclipse.gef.Request)
     */
    public void eraseSourceFeedback(Request request) {
        if (!isEditModeEnabled()) {
            return;
        }

        super.eraseSourceFeedback(request);
    }

    /*
     * @see org.eclipse.gef.EditPart#eraseTargetFeedback(org.eclipse.gef.Request)
     */
    public void eraseTargetFeedback(Request request) {
        if (!isEditModeEnabled()) {
            return;
        }

        super.eraseTargetFeedback(request);
    }

    /**
     * this method will return the primary child EditPart inside this edit part
     * 
     * @return the primary child view inside this edit part
     */
    public EditPart getPrimaryChildEditPart() {
        if (getChildren().size() > 0)
            return (EditPart) getChildren().get(0);
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart#getDiagramPreferencesHint()
     */
    public PreferencesHint getDiagramPreferencesHint() {
        RootEditPart root = getRoot();
        if (root instanceof IDiagramPreferenceSupport) {
            return ((IDiagramPreferenceSupport) root).getPreferencesHint();
        }
        return PreferencesHint.USE_DEFAULTS;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener#notifyChanged(org.eclipse.emf.common.notify.Notification)
     */
    public void notifyChanged(Notification notification) {
        if (isActive()) {
            handleNotificationEvent(notification);
        }
    }

    /**
     * Handles the property changed event
     * 
     * @param event
     *            the property changed event
     */
    protected void handleNotificationEvent(Notification event) {
        Object feature = event.getFeature();
        if (NotationPackage.Literals.VIEW__PERSISTED_CHILDREN.equals(feature)
                || NotationPackage.Literals.VIEW__TRANSIENT_CHILDREN.equals(feature)) {
            refreshChildren();
        } else if (NotationPackage.Literals.VIEW__VISIBLE.equals(feature)) {
            Object notifier = event.getNotifier();
            if (notifier == getModel())
                setVisibility(((Boolean) event.getNewValue()).booleanValue());
            // Reactivating in response to semantic model reference change
            // However, we need to verify that the event belongs to this
            // editpart's view
        } else if (NotationPackage.Literals.ROUTING_STYLE__ROUTING.equals(feature)) {
            installRouter();
        } else if (NotationPackage.Literals.ROUTING_STYLE__SMOOTHNESS.equals(feature)
                || NotationPackage.Literals.ROUTING_STYLE__AVOID_OBSTRUCTIONS.equals(feature)
                || NotationPackage.Literals.ROUTING_STYLE__CLOSEST_DISTANCE.equals(feature)
                || NotationPackage.Literals.ROUTING_STYLE__JUMP_LINK_STATUS.equals(feature)
                || NotationPackage.Literals.ROUTING_STYLE__JUMP_LINK_TYPE.equals(feature)
                || NotationPackage.Literals.ROUTING_STYLE__JUMP_LINKS_REVERSE.equals(feature)
                || NotationPackage.Literals.ROUNDED_CORNERS_STYLE__ROUNDED_BENDPOINTS_RADIUS.equals(feature)) {
            refreshVisuals();
        } else if (NotationPackage.Literals.LINE_STYLE__LINE_COLOR.equals(feature)) {
            Integer c = (Integer) event.getNewValue();
            setForegroundColor(DiagramColorRegistry.getInstance().getColor(c));
        } else if (NotationPackage.Literals.RELATIVE_BENDPOINTS__POINTS.equals(feature)) {
            refreshBendpoints();
        } else if (event.getFeature() == NotationPackage.Literals.VIEW__ELEMENT
                && ((EObject) event.getNotifier()) == getNotationView()) {
            handleMajorSemanticChange();
        } else if (event.getEventType() == EventType.UNRESOLVE
                && event.getNotifier() == ((View) getModel()).getElement())
            handleMajorSemanticChange();
    }

    /**
     * @return <code>IMapMode</code> that allows for the coordinate mapping
     *         from device to logical units.
     */
    protected IMapMode getMapMode() {
        RootEditPart root = getRoot();
        if (root instanceof DiagramRootEditPart) {
            DiagramRootEditPart dgrmRoot = (DiagramRootEditPart) root;
            return dgrmRoot.getMapMode();
        }

        return MapModeUtil.getMapMode();
    }

    /**
     * Derives my editing domain from my diagram element. Subclasses may
     * override.
     */
    public TransactionalEditingDomain getEditingDomain() {
        if (editingDomain == null) {
            // try to get the editing domain for the model
            editingDomain = TransactionUtil.getEditingDomain(getModel());

            if (editingDomain == null) {
                // try to get the editing domain from the diagram view
                editingDomain = TransactionUtil.getEditingDomain(getDiagramView());
            }
        }
        return editingDomain;
    }

    /**
     * Gets the diagram event broker from the editing domain.
     * 
     * @return the diagram event broker
     */
    private DiagramEventBroker getDiagramEventBroker() {
        TransactionalEditingDomain theEditingDomain = getEditingDomain();
        if (theEditingDomain != null) {
            return DiagramEventBroker.getInstance(theEditingDomain);
        }
        return null;
    }

    public Object getPreferredValue(EStructuralFeature feature) {
        Object preferenceStore = getDiagramPreferencesHint().getPreferenceStore();
        if (preferenceStore instanceof IPreferenceStore) {
            if (feature == NotationPackage.eINSTANCE.getLineStyle_LineColor()) {

                return FigureUtilities.RGBToInteger(PreferenceConverter.getColor((IPreferenceStore) preferenceStore,
                        IPreferenceConstants.PREF_LINE_COLOR));

            } else if (feature == NotationPackage.eINSTANCE.getFontStyle_FontColor()) {

                return FigureUtilities.RGBToInteger(PreferenceConverter.getColor((IPreferenceStore) preferenceStore,
                        IPreferenceConstants.PREF_FONT_COLOR));

            }
        }
        return getStructuralFeatureValue(feature);
    }

    /**
     * Gets the resource manager to remember the resources allocated for this
     * graphical viewer. All resources will be disposed when the graphical
     * viewer is closed if they have not already been disposed.
     * 
     * @return the resource manager
     */
    protected ResourceManager getResourceManager() {
        EditPartViewer viewer = getViewer();
        if (viewer instanceof DiagramGraphicalViewer) {
            return ((DiagramGraphicalViewer) viewer).getResourceManager();
        }
        return JFaceResources.getResources();
    }

    /**
    * Answers whether or not this connection represents a part of the semantic
    * model.
    * 
    * @return <code>true</code> if this connection has semantic meaning,
    *         <code>false</code> otherwise.
    */
    public boolean isSemanticConnection() {

        if (semanticConnection == null) {
            if (getEdge() != null
                    && (getEdge().getElement() != null || !NotationTypeUtil.hasNotationType(getEdge()))) {
                semanticConnection = Boolean.TRUE;
            } else {
                semanticConnection = Boolean.FALSE;
            }
        }
        return semanticConnection.booleanValue();
    }

    /**
     * Clear the semantic connection value when the model changes.
     */
    public void setModel(Object model) {
        super.setModel(model);
        semanticConnection = null;
    }

    /**
     * Set the line width of the connection. Clients need to override if they
     * support line width.
     * 
     * @param width
     *            the line width.
     */
    protected void setLineWidth(int width) {
        /* not implemented */
    }

    /**
     * Get the line width of the connection.
     * 
     * @return width
     *            the line width.
     */
    protected int getLineWidth() {
        /* a default of -1 means the diagram does not implement line width */
        int lineWidth = -1;

        LineStyle style = (LineStyle) getPrimaryView().getStyle(NotationPackage.eINSTANCE.getLineStyle());
        if (style != null) {
            lineWidth = style.getLineWidth();
        }

        return lineWidth;
    }

    /**
     * Set the line type of the connection. Clients need to override if they
     * support line type.
     * 
     * @param lineType
     *            the line type.
     */
    protected void setLineType(int lineType) {
        /* not implemented */
    }

    /**
     * Get the line type of the connection.
     * 
     * @return the line type.
     */
    protected int getLineType() {
        // default to Graphics.LINE_SOLID.
        int lineType = Graphics.LINE_SOLID;

        LineTypeStyle style = (LineTypeStyle) getPrimaryView()
                .getStyle(NotationPackage.eINSTANCE.getLineTypeStyle());
        if (style != null) {
            if (style.getLineType() == LineType.SOLID_LITERAL) {
                lineType = Graphics.LINE_SOLID;
            } else if (style.getLineType() == LineType.DASH_LITERAL) {
                lineType = Graphics.LINE_DASH;
            } else if (style.getLineType() == LineType.DOT_LITERAL) {
                lineType = Graphics.LINE_DOT;
            } else if (style.getLineType() == LineType.DASH_DOT_LITERAL) {
                lineType = Graphics.LINE_DASHDOT;
            } else if (style.getLineType() == LineType.DASH_DOT_DOT_LITERAL) {
                lineType = Graphics.LINE_DASHDOTDOT;
            }
        }

        return lineType;
    }

    /**
     * Set the arrow decoration on the connection source end. Clients need to override if they
     * support arrow decorations.
     * 
     * @param arrowDecoration
     *            the arrow decoration.
     */
    protected void setArrowSource(RotatableDecoration arrowDecoration) {
        /* not implemented */
    }

    /**
     * Set the arrow decoration on the connection target end. Clients need to override if they
     * support arrow decorations.
     * 
     * @param arrowDecoration
     *            the arrow type.
     */
    protected void setArrowTarget(RotatableDecoration arrowDecoration) {
        /* not implemented */
    }

    /**
     * Get the arrow decoration for the arrow type.
     * 
     * @param arrowType
     *            the arrow type.
     */
    protected RotatableDecoration getArrowDecoration(int arrowType) {
        RotatableDecoration decoration = null;
        int width = getLineWidth();
        if (width < 0) {
            width = 1;
        }
        if (arrowType == ArrowType.OPEN_ARROW) {
            IMapMode mm = getMapMode();
            decoration = new PolylineDecoration();
            ((PolylineDecoration) decoration).setScale(mm.DPtoLP(11 + width), mm.DPtoLP(6 + width));
            ((PolylineDecoration) decoration).setTemplate(PolylineDecoration.TRIANGLE_TIP);
            ((PolylineDecoration) decoration).setLineWidth(mm.DPtoLP(width));
        } else if (arrowType == ArrowType.SOLID_ARROW) {
            IMapMode mm = getMapMode();
            decoration = new PolygonDecoration();
            ((PolygonDecoration) decoration).setScale(mm.DPtoLP(11 + width), mm.DPtoLP(6 + width));
            ((PolygonDecoration) decoration).setTemplate(PolygonDecoration.TRIANGLE_TIP);
            ((PolygonDecoration) decoration).setLineWidth(mm.DPtoLP(width));
            ((PolygonDecoration) decoration).setFill(true);
        }
        return decoration;
    }

    /**
     * Refreshes the line type property.
     */
    protected void refreshLineWidth() {
        setLineWidth(getLineWidth());
    }

    /**
     * Refreshes the line type property.
     */
    protected void refreshLineType() {
        setLineType(getLineType());
    }

    /**
     * Refreshes the arrow decoration on the source end property.
     */
    protected void refreshArrowSource() {
        // default to no decoration.
        int arrowType = ArrowType.NONE;

        ArrowStyle style = (ArrowStyle) getPrimaryView().getStyle(NotationPackage.eINSTANCE.getArrowStyle());
        if (style != null) {
            arrowType = style.getArrowSource().getValue();
        }

        setArrowSource(getArrowDecoration(arrowType));
    }

    /**
     * Refreshes the arrow decoration on the target end property.
     */
    protected void refreshArrowTarget() {
        // default to no decoration.
        int arrowType = ArrowType.NONE;

        ArrowStyle style = (ArrowStyle) getPrimaryView().getStyle(NotationPackage.eINSTANCE.getArrowStyle());
        if (style != null) {
            arrowType = style.getArrowTarget().getValue();
        }

        setArrowTarget(getArrowDecoration(arrowType));
    }
}