/*******************************************************************************
 * Copyright (c) 2000, 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.gef.editparts;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleControlEvent;

import org.eclipse.core.runtime.IAdaptable;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;

import org.eclipse.gef.AccessibleAnchorProvider;
import org.eclipse.gef.AccessibleEditPart;
import org.eclipse.gef.AccessibleHandleProvider;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeListener;
import org.eclipse.gef.Request;

/**
 * Default implementation for {@link org.eclipse.gef.GraphicalEditPart}.
 * <P>
 * This is an implementation class, and the documentation here is targeted at
 * subclassing this class. Callers of public API should refer to the interface's
 * documentation.
 */
public abstract class AbstractGraphicalEditPart extends AbstractEditPart
		implements GraphicalEditPart {

	/**
	 * The Figure
	 */
	protected IFigure figure;

	/**
	 * List of <i>source</i> ConnectionEditParts
	 */
	protected List sourceConnections;

	/**
	 * List of <i>source</i> ConnectionEditParts
	 */
	protected List targetConnections;

	/**
	 * A default implementation of {@link AccessibleEditPart}. Subclasses can
	 * extend this implementation to get base accessibility for free.
	 * 
	 * @since 2.0
	 */
	protected abstract class AccessibleGraphicalEditPart extends
			AccessibleEditPart {
		/**
		 * @see AccessibleEditPart#getChildCount(AccessibleControlEvent)
		 */
		public void getChildCount(AccessibleControlEvent e) {
			e.detail = AbstractGraphicalEditPart.this.getChildren().size();
		}

		/**
		 * @see AccessibleEditPart#getChildren(AccessibleControlEvent)
		 */
		public void getChildren(AccessibleControlEvent e) {
			List list = AbstractGraphicalEditPart.this.getChildren();
			Object children[] = new Object[list.size()];
			for (int i = 0; i < list.size(); i++) {
				EditPart part = (EditPart) list.get(i);
				AccessibleEditPart access = (AccessibleEditPart) part
						.getAdapter(AccessibleEditPart.class);
				if (access == null)
					return; // fail if any children aren't accessible.
				children[i] = new Integer(access.getAccessibleID());
			}
			e.children = children;
		}

		/**
		 * @see AccessibleEditPart#getLocation(AccessibleControlEvent)
		 */
		public void getLocation(AccessibleControlEvent e) {
			Rectangle bounds = getFigure().getBounds().getCopy();
			getFigure().translateToAbsolute(bounds);
			org.eclipse.swt.graphics.Point p = new org.eclipse.swt.graphics.Point(
					0, 0);
			p = getViewer().getControl().toDisplay(p);
			e.x = bounds.x + p.x;
			e.y = bounds.y + p.y;
			e.width = bounds.width;
			e.height = bounds.height;
		}

		/**
		 * @see AccessibleEditPart#getState(AccessibleControlEvent)
		 */
		public void getState(AccessibleControlEvent e) {
			e.detail = ACC.STATE_SELECTABLE | ACC.STATE_FOCUSABLE;
			if (getSelected() != EditPart.SELECTED_NONE)
				e.detail |= ACC.STATE_SELECTED;
			if (getViewer().getFocusEditPart() == AbstractGraphicalEditPart.this)
				e.detail |= ACC.STATE_FOCUSED;
		}

		/**
		 * @see AccessibleEditPart#getRole(AccessibleControlEvent)
		 */
		public void getRole(AccessibleControlEvent e) {
			e.detail = ACC.ROLE_LABEL;
		}
	}

	/**
	 * The default implementation of {@link AccessibleAnchorProvider} returned
	 * in {@link #getAdapter(Class)}. This implementation creates an accessible
	 * location located along the right edge of the EditPart's Figure.
	 * 
	 * @since 2.0
	 */
	protected class DefaultAccessibleAnchorProvider implements
			AccessibleAnchorProvider {
		private List getDefaultLocations() {
			List list = new ArrayList();
			Rectangle r = getFigure().getBounds();
			Point p = r.getTopRight().translate(-1, r.height / 3);
			getFigure().translateToAbsolute(p);
			list.add(p);
			return list;
		}

		/**
		 * @see AccessibleAnchorProvider#getSourceAnchorLocations()
		 */
		public List getSourceAnchorLocations() {
			return getDefaultLocations();
		}

		/**
		 * @see AccessibleAnchorProvider#getTargetAnchorLocations()
		 */
		public List getTargetAnchorLocations() {
			return getDefaultLocations();
		}
	}

	static class MergedAccessibleHandles implements AccessibleHandleProvider {
		List locations = new ArrayList();

		MergedAccessibleHandles(EditPolicyIterator iter) {
			while (iter.hasNext()) {
				EditPolicy policy = iter.next();
				if (!(policy instanceof IAdaptable))
					continue;
				IAdaptable adaptable = (IAdaptable) policy;
				AccessibleHandleProvider adapter = (AccessibleHandleProvider) adaptable
						.getAdapter(AccessibleHandleProvider.class);
				if (adapter != null)
					locations.addAll(adapter.getAccessibleHandleLocations());
			}
		}

		public List getAccessibleHandleLocations() {
			return locations;
		}
	}

	/**
	 * Extends {@link AbstractEditPart#activate()} to also activate all
	 * <i>source</i> ConnectionEditParts.
	 * 
	 * @see org.eclipse.gef.EditPart#activate()
	 */
	public void activate() {
		super.activate();
		List l = getSourceConnections();
		for (int i = 0; i < l.size(); i++)
			((EditPart) l.get(i)).activate();
	}

	/**
	 * Adds the child's Figure to the {@link #getContentPane() contentPane}.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#addChildVisual(EditPart,
	 *      int)
	 */
	protected void addChildVisual(EditPart childEditPart, int index) {
		IFigure child = ((GraphicalEditPart) childEditPart).getFigure();
		getContentPane().add(child, index);
	}

	/**
	 * @see org.eclipse.gef.GraphicalEditPart#addNodeListener(org.eclipse.gef.NodeListener)
	 */
	public void addNodeListener(NodeListener listener) {
		eventListeners.addListener(NodeListener.class, listener);
	}

	/**
	 * @see org.eclipse.gef.EditPart#addNotify()
	 */
	public void addNotify() {
		super.addNotify();
		List conns;
		conns = getSourceConnections();
		for (int i = 0; i < conns.size(); i++)
			((ConnectionEditPart) conns.get(i)).setSource(this);
		conns = getTargetConnections();
		for (int i = 0; i < conns.size(); i++)
			((ConnectionEditPart) conns.get(i)).setTarget(this);
	}

	/**
	 * Adds a <i>source</i> ConnectionEditPart at the specified index. This
	 * method is called from {@link #refreshSourceConnections()}. There should
	 * be no reason to call or override this method. Source connection are
	 * created as a result of overriding {@link #getModelSourceConnections()}.
	 * <P>
	 * {@link #primAddSourceConnection(ConnectionEditPart, int)} is called to
	 * perform the actual update of the {@link #sourceConnections}
	 * <code>List</code>. The connection will have its source set to
	 * <code>this</code>.
	 * <P>
	 * If active, this EditPart will activate the ConnectionEditPart.
	 * <P>
	 * Finally, all {@link NodeListener}s are notified of the new connection.
	 * 
	 * @param connection
	 *            Connection being added
	 * @param index
	 *            Index where it is being added
	 */
	protected void addSourceConnection(ConnectionEditPart connection, int index) {
		primAddSourceConnection(connection, index);

		GraphicalEditPart source = (GraphicalEditPart) connection.getSource();
		if (source != null)
			source.getSourceConnections().remove(connection);

		connection.setSource(this);
		if (isActive())
			connection.activate();
		fireSourceConnectionAdded(connection, index);
	}

	/**
	 * Adds a <i>target</i> ConnectionEditPart at the specified index. This
	 * method is called from {@link #refreshTargetConnections()}. There should
	 * be no reason to call or override this method. Target connection are
	 * created as a result of overriding {@link #getModelTargetConnections()}.
	 * <P>
	 * {@link #primAddTargetConnection(ConnectionEditPart, int)} is called to
	 * perform the actual update of the {@link #targetConnections}
	 * <code>List</code>. The connection will have its target set to
	 * <code>this</code>.
	 * <P>
	 * Finally, all {@link NodeListener}s are notified of the new connection.
	 * 
	 * @param connection
	 *            Connection being added
	 * @param index
	 *            Index where it is being added
	 */
	protected void addTargetConnection(ConnectionEditPart connection, int index) {
		primAddTargetConnection(connection, index);

		GraphicalEditPart target = (GraphicalEditPart) connection.getTarget();
		if (target != null)
			target.getTargetConnections().remove(connection);

		connection.setTarget(this);
		fireTargetConnectionAdded(connection, index);
	}

	/**
	 * Creates a {@link ConnectionEditPart} for the given model. Similar to
	 * {@link AbstractEditPart#createChild(Object)}. This method is called
	 * indirectly during {@link #refreshSourceConnections()}, and
	 * {@link #refreshTargetConnections()}.
	 * <P>
	 * The default implementation goes to the EditPartViewer's
	 * {@link EditPartFactory} to create the connection. This method should not
	 * be overridden unless factories are not being used.
	 * 
	 * @param model
	 *            the connection model object
	 * @return the new ConnectionEditPart
	 */
	protected ConnectionEditPart createConnection(Object model) {
		return (ConnectionEditPart) getViewer().getEditPartFactory()
				.createEditPart(this, model);
	}

	/**
	 * Creates the <code>Figure</code> to be used as this part's <i>visuals</i>.
	 * This is called from {@link #getFigure()} if the figure has not been
	 * created.
	 * 
	 * @return a Figure
	 */
	protected abstract IFigure createFigure();

	/**
	 * Searches for an existing <code>ConnectionEditPart</code> in the Viewer's
	 * {@link EditPartViewer#getEditPartRegistry() EditPart registry} and
	 * returns it if one is found. Otherwise, {@link #createConnection(Object)}
	 * is called to create a new ConnectionEditPart. Override this method only
	 * if you need to find an existing connection some other way.
	 * 
	 * @param model
	 *            the Connection's model
	 * @return the ConnectionEditPart
	 */
	protected ConnectionEditPart createOrFindConnection(Object model) {
		ConnectionEditPart conx = (ConnectionEditPart) getViewer()
				.getEditPartRegistry().get(model);
		if (conx != null)
			return conx;
		return createConnection(model);
	}

	/**
	 * Extends {@link AbstractEditPart#deactivate()} to also deactivate the
	 * source ConnectionEditParts. Subclasses should <em>extend</em> this method
	 * to remove any listeners added in {@link #activate}.
	 * 
	 * @see org.eclipse.gef.EditPart#deactivate()
	 */
	public void deactivate() {
		List l = getSourceConnections();
		for (int i = 0; i < l.size(); i++)
			((EditPart) l.get(i)).deactivate();

		super.deactivate();
	}

	/**
	 * Notifies listeners that a source connection has been removed. Called from
	 * {@link #removeSourceConnection(ConnectionEditPart)}. There is no reason
	 * for subclasses to call or override this method.
	 * 
	 * @param connection
	 *            <code>ConnectionEditPart</code> being added as child.
	 * @param index
	 *            Position child is being added into.
	 */
	protected void fireRemovingSourceConnection(ConnectionEditPart connection,
			int index) {
		if (eventListeners == null)
			return;
		Iterator listeners = eventListeners.getListeners(NodeListener.class);
		NodeListener listener = null;
		while (listeners.hasNext()) {
			listener = (NodeListener) listeners.next();
			listener.removingSourceConnection(connection, index);
		}
	}

	/**
	 * Notifies listeners that a target connection has been removed. Called from
	 * {@link #removeTargetConnection(ConnectionEditPart)}. There is no reason
	 * for subclasses to call or override this method.
	 * 
	 * @param connection
	 *            <code>ConnectionEditPart</code> being added as child.
	 * @param index
	 *            Position child is being added into.
	 */
	protected void fireRemovingTargetConnection(ConnectionEditPart connection,
			int index) {
		if (eventListeners == null)
			return;
		Iterator listeners = eventListeners.getListeners(NodeListener.class);
		NodeListener listener = null;
		while (listeners.hasNext()) {
			listener = (NodeListener) listeners.next();
			listener.removingTargetConnection(connection, index);
		}
	}

	/**
	 * Notifies listeners that a source connection has been added. Called from
	 * {@link #addSourceConnection(ConnectionEditPart, int)}. There is no reason
	 * for subclasses to call or override this method.
	 * 
	 * @param connection
	 *            <code>ConnectionEditPart</code> being added as child.
	 * @param index
	 *            Position child is being added into.
	 */
	protected void fireSourceConnectionAdded(ConnectionEditPart connection,
			int index) {
		if (eventListeners == null)
			return;
		Iterator listeners = eventListeners.getListeners(NodeListener.class);
		NodeListener listener = null;
		while (listeners.hasNext()) {
			listener = (NodeListener) listeners.next();
			listener.sourceConnectionAdded(connection, index);
		}
	}

	/**
	 * Notifies listeners that a target connection has been added. Called from
	 * {@link #addTargetConnection(ConnectionEditPart, int)}. There is no reason
	 * for subclasses to call or override this method.
	 * 
	 * @param connection
	 *            <code>ConnectionEditPart</code> being added as child.
	 * @param index
	 *            Position child is being added into.
	 */
	protected void fireTargetConnectionAdded(ConnectionEditPart connection,
			int index) {
		if (eventListeners == null)
			return;
		Iterator listeners = eventListeners.getListeners(NodeListener.class);
		NodeListener listener = null;
		while (listeners.hasNext()) {
			listener = (NodeListener) listeners.next();
			listener.targetConnectionAdded(connection, index);
		}
	}

	/**
	 * Extends {@link AbstractEditPart#getAdapter(Class)} to handle additional
	 * adapter types. Currently, these types include
	 * {@link AccessibleHandleProvider} and {@link AccessibleAnchorProvider}.
	 * Subclasses should <em>extend</em> this method to support additional
	 * adapter types, or to replace the default provided adapaters.
	 * 
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
	 */
	public Object getAdapter(Class key) {
		if (key == AccessibleHandleProvider.class)
			return new MergedAccessibleHandles(getEditPolicyIterator());

		if (key == AccessibleAnchorProvider.class)
			return new DefaultAccessibleAnchorProvider();

		return super.getAdapter(key);
	}

	/**
	 * Implemented to delegate to {@link #getFigure()} by default. Subclasses
	 * may overwrite in case the {@link IFigure} returned by
	 * {@link #getFigure()} is a composite figure and child figures should be
	 * added to one of its children instead of the figure itself.
	 * 
	 * @see GraphicalEditPart#getContentPane()
	 */
	public IFigure getContentPane() {
		return getFigure();
	}

	/**
	 * Overridden to return a default <code>DragTracker</code> for
	 * GraphicalEditParts.
	 * 
	 * @see org.eclipse.gef.EditPart#getDragTracker(Request)
	 */
	public DragTracker getDragTracker(Request request) {
		return new org.eclipse.gef.tools.DragEditPartsTracker(this);
	}

	/**
	 * The default implementation calls {@link #createFigure()} if the figure is
	 * currently <code>null</code>.
	 * 
	 * @see org.eclipse.gef.GraphicalEditPart#getFigure()
	 */
	public IFigure getFigure() {
		if (figure == null)
			setFigure(createFigure());
		return figure;
	}

	/**
	 * A convenience method for obtaining the specified layer from the
	 * <code>LayerManager</code>.
	 * 
	 * @param layer
	 *            ID of the Layer
	 * @return The requested layer or <code>null</code> if it doesn't exist
	 */
	protected IFigure getLayer(Object layer) {
		LayerManager manager = (LayerManager) getViewer().getEditPartRegistry()
				.get(LayerManager.ID);
		return manager.getLayer(layer);
	}

	/**
	 * Returns the <code>List</code> of the connection model objects for which
	 * this EditPart's model is the <b>source</b>.
	 * {@link #refreshSourceConnections()} calls this method. For each
	 * connection model object, {@link #createConnection(Object)} will be called
	 * automatically to obtain a corresponding {@link ConnectionEditPart}.
	 * <P>
	 * Callers must not modify the returned List.
	 * 
	 * @return the List of model source connections
	 */
	protected List getModelSourceConnections() {
		return Collections.EMPTY_LIST;
	}

	/**
	 * Returns the <code>List</code> of the connection model objects for which
	 * this EditPart's model is the <b>target</b>.
	 * {@link #refreshTargetConnections()} calls this method. For each
	 * connection model object, {@link #createConnection(Object)} will be called
	 * automatically to obtain a corresponding {@link ConnectionEditPart}.
	 * <P>
	 * Callers must not modify the returned List.
	 * 
	 * @return the List of model target connections
	 */
	protected List getModelTargetConnections() {
		return Collections.EMPTY_LIST;
	}

	/**
	 * @see org.eclipse.gef.GraphicalEditPart#getSourceConnections()
	 */
	public List getSourceConnections() {
		if (sourceConnections == null)
			return Collections.EMPTY_LIST;
		return sourceConnections;
	}

	/**
	 * @see org.eclipse.gef.GraphicalEditPart#getTargetConnections()
	 */
	public List getTargetConnections() {
		if (targetConnections == null)
			return Collections.EMPTY_LIST;
		return targetConnections;
	}

	/**
	 * A GraphicalEditPart is considered selectable, if it is active and its
	 * figure is showing.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#isSelectable()
	 */
	public boolean isSelectable() {
		return super.isSelectable() && getFigure() != null
				&& getFigure().isShowing();
	}

	/**
	 * Adds the specified source <code>ConnectionEditPart</code> at an index.
	 * This method is used to update the {@link #sourceConnections} List. This
	 * method is called from
	 * {@link #addSourceConnection(ConnectionEditPart, int)}. Subclasses should
	 * not call or override this method.
	 * 
	 * @param connection
	 *            the ConnectionEditPart
	 * @param index
	 *            the index of the add
	 */
	protected void primAddSourceConnection(ConnectionEditPart connection,
			int index) {
		if (sourceConnections == null)
			sourceConnections = new ArrayList();
		sourceConnections.add(index, connection);
	}

	/**
	 * Adds the specified target <code>ConnectionEditPart</code> at an index.
	 * This method is used to update the {@link #targetConnections} List. This
	 * method is called from
	 * {@link #addTargetConnection(ConnectionEditPart, int)}. Subclasses should
	 * not call or override this method.
	 * 
	 * @param connection
	 *            the ConnectionEditPart
	 * @param index
	 *            the index of the add
	 */
	protected void primAddTargetConnection(ConnectionEditPart connection,
			int index) {
		if (targetConnections == null)
			targetConnections = new ArrayList();
		targetConnections.add(index, connection);
	}

	/**
	 * Removes the specified source <code>ConnectionEditPart</code> from the
	 * {@link #sourceConnections} List. This method is called from
	 * {@link #removeSourceConnection(ConnectionEditPart)}. Subclasses should
	 * not call or override this method.
	 * 
	 * @param connection
	 *            Connection to remove.
	 */
	protected void primRemoveSourceConnection(ConnectionEditPart connection) {
		sourceConnections.remove(connection);
	}

	/**
	 * Removes the specified target <code>ConnectionEditPart</code> from the
	 * {@link #targetConnections} List. This method is called from
	 * {@link #removeTargetConnection(ConnectionEditPart)}. Subclasses should
	 * not call or override this method.
	 * 
	 * @param connection
	 *            Connection to remove.
	 */
	protected void primRemoveTargetConnection(ConnectionEditPart connection) {
		targetConnections.remove(connection);
	}

	/**
	 * Extends {@link AbstractEditPart#refresh()} to refresh two additional
	 * structural features: <i>source</i> and <i>target</i> connections.
	 * Subclasses should probably override
	 * {@link AbstractEditPart#refreshVisuals()} instead of this method.
	 * 
	 * @see org.eclipse.gef.EditPart#refresh()
	 */
	public void refresh() {
		super.refresh();
		refreshSourceConnections();
		refreshTargetConnections();
	}

	/**
	 * Updates the set of <i>source</i> ConnectionEditParts so that it is in
	 * sync with the model source connections. This method is called from
	 * {@link #refresh()}, and may also be called in response to notification
	 * from the model.
	 * <P>
	 * The update is performed by comparing the existing source
	 * ConnectionEditParts with the set of model source connections returned
	 * from {@link #getModelSourceConnections()}. EditParts whose model no
	 * longer exists are {@link #removeSourceConnection(ConnectionEditPart)
	 * removed}. New models have their ConnectionEditParts
	 * {@link #createConnection(Object) created}. Subclasses should override
	 * <code>getModelSourceChildren()</code>.
	 * <P>
	 * This method should <em>not</em> be overridden.
	 */
	protected void refreshSourceConnections() {
		int i;
		ConnectionEditPart editPart;
		Object model;

		List sourceConnections = getSourceConnections();
		int size = sourceConnections.size();
		Map modelToEditPart = Collections.EMPTY_MAP;
		if (size > 0) {
			modelToEditPart = new HashMap(size);
			for (i = 0; i < size; i++) {
				editPart = (ConnectionEditPart) sourceConnections.get(i);
				modelToEditPart.put(editPart.getModel(), editPart);
			}
		}

		List modelObjects = getModelSourceConnections();
		if (modelObjects == null) {
			modelObjects = Collections.EMPTY_LIST;
		}
		for (i = 0; i < modelObjects.size(); i++) {
			model = modelObjects.get(i);

			if (i < sourceConnections.size()
					&& ((EditPart) sourceConnections.get(i)).getModel() == model)
				continue;

			editPart = (ConnectionEditPart) modelToEditPart.get(model);
			if (editPart != null)
				reorderSourceConnection(editPart, i);
			else {
				editPart = createOrFindConnection(model);
				addSourceConnection(editPart, i);
			}
		}

		// Remove the remaining EditParts
		size = sourceConnections.size();
		if (i < size) {
			List trash = new ArrayList(size - i);
			for (; i < size; i++)
				trash.add(sourceConnections.get(i));
			for (i = 0; i < trash.size(); i++)
				removeSourceConnection((ConnectionEditPart) trash.get(i));
		}
	}

	/**
	 * Updates the set of <i>target</i> ConnectionEditParts so that it is in
	 * sync with the model target connections. This method is called from
	 * {@link #refresh()}, and may also be called in response to notification
	 * from the model.
	 * <P>
	 * The update is performed by comparing the existing source
	 * ConnectionEditParts with the set of model source connections returned
	 * from {@link #getModelTargetConnections()}. EditParts whose model no
	 * longer exists are {@link #removeTargetConnection(ConnectionEditPart)
	 * removed}. New models have their ConnectionEditParts
	 * {@link #createConnection(Object) created}. Subclasses should override
	 * <code>getModelTargetChildren()</code>.
	 * <P>
	 * This method should <em>not</em> be overridden.
	 */
	protected void refreshTargetConnections() {
		int i;
		ConnectionEditPart editPart;
		Object model;

		List targetConnections = getTargetConnections();
		int size = targetConnections.size();
		Map modelToEditPart = Collections.EMPTY_MAP;
		if (size > 0) {
			modelToEditPart = new HashMap(size);
			for (i = 0; i < size; i++) {
				editPart = (ConnectionEditPart) targetConnections.get(i);
				modelToEditPart.put(editPart.getModel(), editPart);
			}
		}

		List modelObjects = getModelTargetConnections();
		if (modelObjects == null) {
			modelObjects = Collections.EMPTY_LIST;
		}
		for (i = 0; i < modelObjects.size(); i++) {
			model = modelObjects.get(i);

			if (i < targetConnections.size()
					&& ((EditPart) targetConnections.get(i)).getModel() == model)
				continue;

			editPart = (ConnectionEditPart) modelToEditPart.get(model);
			if (editPart != null)
				reorderTargetConnection(editPart, i);
			else {
				editPart = createOrFindConnection(model);
				addTargetConnection(editPart, i);
			}
		}

		// Remove the remaining EditParts
		size = targetConnections.size();
		if (i < size) {
			List trash = new ArrayList(size - i);
			for (; i < size; i++)
				trash.add(targetConnections.get(i));
			for (i = 0; i < trash.size(); i++)
				removeTargetConnection((ConnectionEditPart) trash.get(i));
		}
	}

	/**
	 * Registers the EditPart's Figure in the Viewer. This is what makes it
	 * possible for the Viewer to map a mouse location to an EditPart.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#registerVisuals()
	 */
	protected void registerVisuals() {
		getViewer().getVisualPartMap().put(getFigure(), this);
	}

	/**
	 * Remove the child's Figure from the {@link #getContentPane() contentPane}.
	 * 
	 * @see AbstractEditPart#removeChildVisual(EditPart)
	 */
	protected void removeChildVisual(EditPart childEditPart) {
		IFigure child = ((GraphicalEditPart) childEditPart).getFigure();
		getContentPane().remove(child);
	}

	/**
	 * @see org.eclipse.gef.GraphicalEditPart#removeNodeListener(org.eclipse.gef.NodeListener)
	 */
	public void removeNodeListener(NodeListener listener) {
		eventListeners.removeListener(NodeListener.class, listener);
	}

	/**
	 * Extends {@link AbstractEditPart#removeNotify()} to cleanup
	 * <code>ConnectionEditParts</code>.
	 * 
	 * @see EditPart#removeNotify()
	 */
	public void removeNotify() {
		List conns;
		ConnectionEditPart cep;
		conns = getSourceConnections();
		for (int i = 0; i < conns.size(); i++) {
			cep = (ConnectionEditPart) conns.get(i);
			if (cep.getSource() == this)
				cep.setSource(null);
		}
		conns = getTargetConnections();
		for (int i = 0; i < conns.size(); i++) {
			cep = (ConnectionEditPart) conns.get(i);
			if (cep.getTarget() == this)
				cep.setTarget(null);
		}
		super.removeNotify();
	}

	/**
	 * Removes the given connection for which this EditPart is the
	 * <B>source</b>. <BR>
	 * Fires notification. <BR>
	 * Inverse of {@link #addSourceConnection(ConnectionEditPart, int)}
	 * 
	 * @param connection
	 *            Connection being removed
	 */
	protected void removeSourceConnection(ConnectionEditPart connection) {
		fireRemovingSourceConnection(connection, getSourceConnections()
				.indexOf(connection));
		if (connection.getSource() == this) {
			connection.deactivate();
			connection.setSource(null);
		}
		primRemoveSourceConnection(connection);
	}

	/**
	 * Removes the given connection for which this EditPart is the
	 * <B>target</b>. <BR>
	 * Fires notification. <BR>
	 * Inverse of {@link #addTargetConnection(ConnectionEditPart, int)}
	 * 
	 * @param connection
	 *            Connection being removed
	 */
	protected void removeTargetConnection(ConnectionEditPart connection) {
		fireRemovingTargetConnection(connection, getTargetConnections()
				.indexOf(connection));
		if (connection.getTarget() == this)
			connection.setTarget(null);
		primRemoveTargetConnection(connection);
	}

	/**
	 * This method is extended to preserve a LayoutManager constraint if one
	 * exists.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#reorderChild(EditPart,
	 *      int)
	 */
	protected void reorderChild(EditPart child, int index) {
		// Save the constraint of the child so that it does not
		// get lost during the remove and re-add.
		IFigure childFigure = ((GraphicalEditPart) child).getFigure();
		LayoutManager layout = getContentPane().getLayoutManager();
		Object constraint = null;
		if (layout != null)
			constraint = layout.getConstraint(childFigure);

		super.reorderChild(child, index);
		setLayoutConstraint(child, childFigure, constraint);
	}

	/**
	 * Moves a source <code>ConnectionEditPart</code> into a lower index than it
	 * currently occupies. This method is called from
	 * {@link #refreshSourceConnections()}.
	 * 
	 * @param connection
	 *            the ConnectionEditPart
	 * @param index
	 *            the new index
	 */
	protected void reorderSourceConnection(ConnectionEditPart connection,
			int index) {
		primRemoveSourceConnection(connection);
		primAddSourceConnection(connection, index);
	}

	/**
	 * Moves a target <code>ConnectionEditPart</code> into a lower index than it
	 * currently occupies. This method is called from
	 * {@link #refreshTargetConnections()}.
	 * 
	 * @param connection
	 *            the ConnectionEditPart
	 * @param index
	 *            the new index
	 */
	protected void reorderTargetConnection(ConnectionEditPart connection,
			int index) {
		primRemoveTargetConnection(connection);
		primAddTargetConnection(connection, index);
	}

	/**
	 * Sets the Figure
	 * 
	 * @param figure
	 *            the Figure
	 */
	protected void setFigure(IFigure figure) {
		this.figure = figure;
	}

	/**
	 * @see GraphicalEditPart#setLayoutConstraint(EditPart, IFigure, Object)
	 */
	public void setLayoutConstraint(EditPart child, IFigure childFigure,
			Object constraint) {
		childFigure.getParent().setConstraint(childFigure, constraint);
	}

	/**
	 * Implemented to remove the Figure from the Viewer's registry.
	 * 
	 * @see AbstractEditPart#unregisterVisuals()
	 */
	protected void unregisterVisuals() {
		getViewer().getVisualPartMap().remove(getFigure());
	}

}
