/*******************************************************************************
 * 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.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;

import org.eclipse.draw2d.EventListenerList;

import org.eclipse.gef.AccessibleEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartFactory;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.RootEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.SelectionEditPolicy;

/**
 * The baseline implementation for the {@link EditPart} interface.
 * <P>
 * Since this is the default implementation of an interface, this document deals
 * with proper sub-classing of this implementation. This class is not the API.
 * For documentation on proper usage of the public API, see the documentation
 * for the interface itself: {@link EditPart}.
 * <P>
 * This class assumes no visual representation. Subclasses
 * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart} add
 * support for {@link org.eclipse.draw2d.IFigure Figures} and
 * {@link org.eclipse.swt.widgets.TreeItem TreeItems} respectively.
 * <P>
 * AbstractEditPart provides support for children. All AbstractEditPart's can
 * potentially be containers for other EditParts.
 */
public abstract class AbstractEditPart implements EditPart, RequestConstants,
		IAdaptable {

	/**
	 * This flag is set during {@link #activate()}, and reset on
	 * {@link #deactivate()}
	 */
	protected static final int FLAG_ACTIVE = 1;
	/**
	 * This flag indicates that the EditPart has focus.
	 */
	protected static final int FLAG_FOCUS = 2;

	/**
	 * The left-most bit that is reserved by this class for setting flags.
	 * Subclasses may define additional flags starting at
	 * <code>(MAX_FLAG << 1)</code>.
	 */
	protected static final int MAX_FLAG = FLAG_FOCUS;

	private Object model;
	private int flags;
	private EditPart parent;
	private int selected;

	private Object policies[];

	/**
	 * The List of children EditParts
	 */
	protected List children;

	/**
	 * call getEventListeners(Class) instead.
	 */
	EventListenerList eventListeners = new EventListenerList();

	/**
	 * Iterates over a <code>List</code> of EditPolcies, skipping any
	 * <code>null</code> values encountered.
	 */
	protected static class EditPolicyIterator {
		private Object list[];
		private int offset = 0;
		private final int length;

		EditPolicyIterator(Object list[]) {
			this.list = list;
			length = (list == null) ? 0 : list.length;
		}

		/**
		 * Constructs an Iterator for the given <code>List</code>.
		 * 
		 * @deprecated this constructor should not be used
		 * @param list
		 *            the list of policies.
		 */
		public EditPolicyIterator(List list) {
			this(list.toArray());
		}

		/**
		 * Returns the next non-<code>null</code> EditPolicy.
		 * 
		 * @return the next non-<code>null</code> EditPolicy.
		 */
		public EditPolicy next() {
			if (offset < length)
				return (EditPolicy) list[offset++];
			return null;
		}

		/**
		 * Returns <code>true</code> if there is a next edit policy.
		 * 
		 * @return <code>true</code> if there is a next policy
		 */
		public boolean hasNext() {
			if (list == null)
				return false;

			while (offset < list.length
					&& !(list[offset] instanceof EditPolicy))
				offset++;
			return offset < list.length;
		}
	}

	/**
	 * Activates this EditPart, which in turn activates its children and
	 * EditPolicies. Subclasses should <em>extend</em> this method to add
	 * listeners to the model. Activation indicates that the EditPart is
	 * realized in an EditPartViewer. <code>deactivate()</code> is the inverse,
	 * and is eventually called on all EditParts.
	 * 
	 * @see EditPart#activate()
	 * @see #deactivate()
	 */
	public void activate() {
		setFlag(FLAG_ACTIVE, true);

		activateEditPolicies();

		List c = getChildren();
		for (int i = 0; i < c.size(); i++)
			((EditPart) c.get(i)).activate();

		fireActivated();
	}

	/**
	 * Activates all EditPolicies installed on this part. There is no reason to
	 * override this method.
	 * 
	 * @see #activate()
	 */
	protected void activateEditPolicies() {
		EditPolicyIterator i = getEditPolicyIterator();
		while (i.hasNext())
			i.next().activate();
	}

	/**
	 * Adds a child <code>EditPart</code> to this EditPart. This method is
	 * called from {@link #refreshChildren()}. The following events occur in the
	 * order listed:
	 * <OL>
	 * <LI>The child is added to the {@link #children} List, and its parent is
	 * set to <code>this</code>
	 * <LI>{@link #addChildVisual(EditPart, int)} is called to add the child's
	 * visual
	 * <LI>{@link EditPart#addNotify()} is called on the child.
	 * <LI><code>activate()</code> is called if this part is active
	 * <LI><code>EditPartListeners</code> are notified that the child has been
	 * added.
	 * </OL>
	 * <P>
	 * Subclasses should implement {@link #addChildVisual(EditPart, int)}.
	 * 
	 * @param child
	 *            The <code>EditPart</code> to add
	 * @param index
	 *            The index
	 * @see #addChildVisual(EditPart, int)
	 * @see #removeChild(EditPart)
	 * @see #reorderChild(EditPart,int)
	 */
	protected void addChild(EditPart child, int index) {
		Assert.isNotNull(child);
		if (index == -1)
			index = getChildren().size();
		if (children == null)
			children = new ArrayList(2);

		children.add(index, child);
		child.setParent(this);
		addChildVisual(child, index);
		child.addNotify();

		if (isActive())
			child.activate();
		fireChildAdded(child, index);
	}

	/**
	 * Performs the addition of the child's <i>visual</i> to this EditPart's
	 * Visual. The provided subclasses {@link AbstractGraphicalEditPart} and
	 * {@link AbstractTreeEditPart} already implement this method correctly, so
	 * it is unlikely that this method should be overridden.
	 * 
	 * @param child
	 *            The EditPart being added
	 * @param index
	 *            The child's position
	 * @see #addChild(EditPart, int)
	 * @see AbstractGraphicalEditPart#removeChildVisual(EditPart)
	 */
	protected abstract void addChildVisual(EditPart child, int index);

	/**
	 * Adds an EditPartListener.
	 * 
	 * @param listener
	 *            the listener
	 */
	public void addEditPartListener(EditPartListener listener) {
		eventListeners.addListener(EditPartListener.class, listener);
	}

	/**
	 * @see EditPart#addNotify()
	 */
	public void addNotify() {
		register();
		createEditPolicies();
		List children = getChildren();
		for (int i = 0; i < children.size(); i++)
			((EditPart) children.get(i)).addNotify();
		refresh();
	}

	/**
	 * Create the child <code>EditPart</code> for the given model object. This
	 * method is called from {@link #refreshChildren()}.
	 * <P>
	 * By default, the implementation will delegate to the
	 * <code>EditPartViewer</code>'s {@link EditPartFactory}. Subclasses may
	 * override this method instead of using a Factory.
	 * 
	 * @param model
	 *            the Child model object
	 * @return The child EditPart
	 */
	protected EditPart createChild(Object model) {
		return getViewer().getEditPartFactory().createEditPart(this, model);
	}

	/**
	 * Creates the initial EditPolicies and/or reserves slots for dynamic ones.
	 * Should be implemented to install the inital EditPolicies based on the
	 * model's initial state. <code>null</code> can be used to reserve a "slot",
	 * should there be some desire to guarantee the ordering of EditPolcies.
	 * 
	 * @see EditPart#installEditPolicy(Object, EditPolicy)
	 */
	protected abstract void createEditPolicies();

	/**
	 * Deactivates this EditPart, and in turn deactivates its children and
	 * EditPolicies. Subclasses should <em>extend</em> this method to remove any
	 * listeners established in {@link #activate()}
	 * 
	 * @see EditPart#deactivate()
	 * @see #activate()
	 */
	public void deactivate() {
		List c = getChildren();
		for (int i = 0; i < c.size(); i++)
			((EditPart) c.get(i)).deactivate();

		deactivateEditPolicies();

		setFlag(FLAG_ACTIVE, false);
		fireDeactivated();
	}

	/**
	 * Deactivates all installed EditPolicies.
	 */
	protected void deactivateEditPolicies() {
		EditPolicyIterator i = getEditPolicyIterator();
		while (i.hasNext())
			i.next().deactivate();
	}

	/**
	 * This method will log a message to GEF's trace/debug system if the
	 * corresponding flag for EditParts is set to true.
	 * 
	 * @param message
	 *            a debug message
	 * @deprecated in 3.1
	 */
	protected final void debug(String message) {
	}

	/**
	 * This method will log the message to GEF's trace/debug system if the
	 * corrseponding flag for FEEDBACK is set to true.
	 * 
	 * @param message
	 *            Message to be passed
	 * @deprecated in 3.1
	 */
	protected final void debugFeedback(String message) {
	}

	/**
	 * Erases source feedback for the given <code>Request</code>. By default,
	 * this responsibility is delegated to this part's <code>EditPolicies</code>
	 * . Subclasses should rarely extend this method.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that feedback be handled by EditPolicies, and not
	 * directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @param request
	 *            identifies the type of feedback to erase.
	 * @see #showSourceFeedback(Request)
	 */
	public void eraseSourceFeedback(Request request) {
		if (isActive()) {
			EditPolicyIterator iter = getEditPolicyIterator();
			while (iter.hasNext())
				iter.next().eraseSourceFeedback(request);
		}
	}

	/**
	 * Erases target feedback for the given <code>Request</code>. By default,
	 * this responsibility is delegated to this part's EditPolicies. Subclasses
	 * should rarely extend this method.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that feedback be handled by EditPolicies, and not
	 * directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @param request
	 *            Command requesting the erase.
	 * @see #showTargetFeedback(Request)
	 */
	public void eraseTargetFeedback(Request request) {
		if (isActive()) {
			EditPolicyIterator iter = getEditPolicyIterator();
			while (iter.hasNext())
				iter.next().eraseTargetFeedback(request);
		}
	}

	/**
	 * Notifies <code>EditPartListeners</code> that this EditPart has been
	 * activated.
	 */
	protected void fireActivated() {
		Iterator listeners = getEventListeners(EditPartListener.class);
		while (listeners.hasNext())
			((EditPartListener) listeners.next()).partActivated(this);
	}

	/**
	 * Notifies <code>EditPartListeners</code> that a child has been added.
	 * 
	 * @param child
	 *            <code>EditPart</code> being added as child.
	 * @param index
	 *            Position child is being added into.
	 */
	protected void fireChildAdded(EditPart child, int index) {
		Iterator listeners = getEventListeners(EditPartListener.class);
		while (listeners.hasNext())
			((EditPartListener) listeners.next()).childAdded(child, index);
	}

	/**
	 * Notifies <code>EditPartListeners </code> that this EditPart has been
	 * deactivated.
	 */
	protected void fireDeactivated() {
		Iterator listeners = getEventListeners(EditPartListener.class);
		while (listeners.hasNext())
			((EditPartListener) listeners.next()).partDeactivated(this);
	}

	/**
	 * Notifies <code>EditPartListeners</code> that a child is being removed.
	 * 
	 * @param child
	 *            <code>EditPart</code> being removed.
	 * @param index
	 *            Position of the child in children list.
	 */
	protected void fireRemovingChild(EditPart child, int index) {
		Iterator listeners = getEventListeners(EditPartListener.class);
		while (listeners.hasNext())
			((EditPartListener) listeners.next()).removingChild(child, index);
	}

	/**
	 * Notifies <code>EditPartListeners</code> that the selection has changed.
	 */
	protected void fireSelectionChanged() {
		Iterator listeners = getEventListeners(EditPartListener.class);
		while (listeners.hasNext())
			((EditPartListener) listeners.next()).selectedStateChanged(this);
	}

	/**
	 * Returns the <code>AccessibleEditPart</code> adapter for this EditPart.
	 * The <B>same</B> adapter instance must be used throughout the editpart's
	 * existance. Each adapter has a unique ID which is registered during
	 * {@link #register()}. Accessibility clients can only refer to this
	 * editpart via that ID.
	 * 
	 * @return <code>null</code> or an AccessibleEditPart adapter
	 */
	protected AccessibleEditPart getAccessibleEditPart() {
		return null;
	}

	/**
	 * Returns the specified adapter if recognized. Delegates to the workbench
	 * adapter mechanism.
	 * <P>
	 * Additional adapter types may be added in the future. Subclasses should
	 * extend this method as needed.
	 * 
	 * @see IAdaptable#getAdapter(java.lang.Class)
	 */
	public Object getAdapter(Class key) {
		if (AccessibleEditPart.class == key)
			return getAccessibleEditPart();
		return Platform.getAdapterManager().getAdapter(this, key);
	}

	/**
	 * @see org.eclipse.gef.EditPart#getChildren()
	 */
	public List getChildren() {
		if (children == null)
			return Collections.EMPTY_LIST;
		return children;
	}

	/**
	 * Subclasses should rarely extend this method. The default implementation
	 * combines the contributions from each installed <code>EditPolicy</code>.
	 * This method is implemented indirectly using EditPolicies.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that Command creation be handled by EditPolicies,
	 * and not directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @see EditPart#getCommand(Request)
	 * @see EditPolicy#getCommand(Request)
	 * @param request
	 *            the Request
	 * @return a Command
	 */
	public Command getCommand(Request request) {
		Command command = null;
		EditPolicyIterator i = getEditPolicyIterator();
		while (i.hasNext()) {
			if (command != null)
				command = command.chain(i.next().getCommand(request));
			else
				command = i.next().getCommand(request);
		}
		return command;
	}

	/**
	 * Returns an iterator for the specified type of listener
	 * 
	 * @param clazz
	 *            the Listener type over which to iterate
	 * @return Iterator
	 */
	protected final Iterator getEventListeners(Class clazz) {
		return eventListeners.getListeners(clazz);
	}

	/**
	 * @see org.eclipse.gef.EditPart#getEditPolicy(Object)
	 */
	public EditPolicy getEditPolicy(Object key) {
		if (policies != null)
			for (int i = 0; i < policies.length; i += 2) {
				if (key.equals(policies[i]))
					return (EditPolicy) policies[i + 1];
			}
		return null;
	}

	/**
	 * Used internally to iterate over the installed EditPolicies. While
	 * EditPolicy slots may be reserved with <code>null</code>, the iterator
	 * only returns the non-null ones.
	 * 
	 * @return an EditPolicyIterator
	 */
	protected final EditPolicyIterator getEditPolicyIterator() {
		return new EditPolicyIterator(policies);
	}

	/**
	 * Returns the boolean value of the given flag. Specifically, returns
	 * <code>true</code> if the bitwise AND of the specified flag and the
	 * internal flags field is non-zero.
	 * 
	 * @param flag
	 *            Bitmask indicating which flag to return
	 * @return the requested flag's value
	 * @see #setFlag(int,boolean)
	 */
	protected final boolean getFlag(int flag) {
		return (flags & flag) != 0;
	}

	/**
	 * @see org.eclipse.gef.EditPart#getModel()
	 */
	public Object getModel() {
		return model;
	}

	/**
	 * Returns a <code>List</code> containing the children model objects. If
	 * this EditPart's model is a container, this method should be overridden to
	 * returns its children. This is what causes children EditParts to be
	 * created.
	 * <P>
	 * Callers must not modify the returned List. Must not return
	 * <code>null</code>.
	 * 
	 * @return the List of children
	 */
	protected List getModelChildren() {
		return Collections.EMPTY_LIST;
	}

	/**
	 * @see org.eclipse.gef.EditPart#getParent()
	 */
	public EditPart getParent() {
		return parent;
	}

	/**
	 * @see org.eclipse.gef.EditPart#getRoot()
	 */
	public RootEditPart getRoot() {
		if (getParent() == null) {
			return null;
		}
		return getParent().getRoot();
	}

	/**
	 * @see org.eclipse.gef.EditPart#getSelected()
	 */
	public int getSelected() {
		return selected;
	}

	/**
	 * Returns the <code>EditPart</code> which is the target of the
	 * <code>Request</code>. The default implementation delegates this method to
	 * the installed EditPolicies. The first non-<code>null</code> result
	 * returned by an EditPolicy is returned. Subclasses should rarely extend
	 * this method.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that targeting be handled by EditPolicies, and not
	 * directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @param request
	 *            Describes the type of target desired.
	 * @return <code>null</code> or the <i>target</i> <code>EditPart</code>
	 * @see EditPart#getTargetEditPart(Request)
	 * @see EditPolicy#getTargetEditPart(Request)
	 */
	public EditPart getTargetEditPart(Request request) {
		EditPolicyIterator i = getEditPolicyIterator();
		EditPart editPart;
		while (i.hasNext()) {
			editPart = i.next().getTargetEditPart(request);
			if (editPart != null)
				return editPart;
		}

		if (RequestConstants.REQ_SELECTION == request.getType()) {
			if (isSelectable())
				return this;
		}

		return null;
	}

	/**
	 * @see org.eclipse.gef.EditPart#getViewer()
	 */
	public EditPartViewer getViewer() {
		RootEditPart root = getRoot();
		if (root == null) {
			return null;
		}
		return root.getViewer();
	}

	/**
	 * @see org.eclipse.gef.EditPart#hasFocus()
	 */
	public boolean hasFocus() {
		return getFlag(FLAG_FOCUS);
	}

	/**
	 * @see EditPart#installEditPolicy(Object, EditPolicy)
	 */
	public void installEditPolicy(Object key, EditPolicy editPolicy) {
		Assert.isNotNull(key, "Edit Policies must be installed with keys");//$NON-NLS-1$
		if (policies == null) {
			policies = new Object[2];
			policies[0] = key;
			policies[1] = editPolicy;
		} else {
			int index = 0;
			while (index < policies.length && !key.equals(policies[index]))
				index += 2;
			if (index < policies.length) {
				index++;
				EditPolicy old = (EditPolicy) policies[index];
				if (old != null && isActive())
					old.deactivate();
				policies[index] = editPolicy;
			} else {
				Object newPolicies[] = new Object[policies.length + 2];
				System.arraycopy(policies, 0, newPolicies, 0, policies.length);
				policies = newPolicies;
				policies[index] = key;
				policies[index + 1] = editPolicy;
			}
		}

		if (editPolicy != null) {
			editPolicy.setHost(this);
			if (isActive())
				editPolicy.activate();
		}
	}

	/**
	 * @return <code>true</code> if this EditPart is active.
	 */
	public boolean isActive() {
		return getFlag(FLAG_ACTIVE);
	}

	/**
	 * By default, an EditPart is regarded to be selectable.
	 * 
	 * @see org.eclipse.gef.EditPart#isSelectable()
	 */
	public boolean isSelectable() {
		return true;
	}

	/**
	 * Subclasses should extend this method to handle Requests. For now, the
	 * default implementation does not handle any requests.
	 * 
	 * @see EditPart#performRequest(Request)
	 */
	public void performRequest(Request req) {
	}

	/**
	 * Refreshes all properties visually displayed by this EditPart. The default
	 * implementation will call {@link #refreshChildren()} to update its
	 * structural features. It also calls {@link #refreshVisuals()} to update
	 * its own displayed properties. Subclasses should extend this method to
	 * handle additional types of structural refreshing.
	 */
	public void refresh() {
		refreshVisuals();
		refreshChildren();
	}

	/**
	 * Updates the set of children EditParts so that it is in sync with the
	 * model children. This method is called from {@link #refresh()}, and may
	 * also be called in response to notification from the model. This method
	 * requires linear time to complete. Clients should call this method as few
	 * times as possible. Consider also calling {@link #removeChild(EditPart)}
	 * and {@link #addChild(EditPart, int)} which run in constant time.
	 * <P>
	 * The update is performed by comparing the existing EditParts with the set
	 * of model children returned from {@link #getModelChildren()}. EditParts
	 * whose models no longer exist are {@link #removeChild(EditPart) removed}.
	 * New models have their EditParts {@link #createChild(Object) created}.
	 * <P>
	 * This method should <em>not</em> be overridden.
	 * 
	 * @see #getModelChildren()
	 */
	protected void refreshChildren() {
		int i;
		EditPart editPart;
		Object model;

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

		List modelObjects = getModelChildren();
		for (i = 0; i < modelObjects.size(); i++) {
			model = modelObjects.get(i);

			// Do a quick check to see if editPart[i] == model[i]
			if (i < children.size()
					&& ((EditPart) children.get(i)).getModel() == model)
				continue;

			// Look to see if the EditPart is already around but in the
			// wrong location
			editPart = (EditPart) modelToEditPart.get(model);

			if (editPart != null)
				reorderChild(editPart, i);
			else {
				// An EditPart for this model doesn't exist yet. Create and
				// insert one.
				editPart = createChild(model);
				addChild(editPart, i);
			}
		}

		// remove the remaining EditParts
		size = children.size();
		if (i < size) {
			List trash = new ArrayList(size - i);
			for (; i < size; i++)
				trash.add(children.get(i));
			for (i = 0; i < trash.size(); i++) {
				EditPart ep = (EditPart) trash.get(i);
				removeChild(ep);
			}
		}
	}

	/**
	 * Refreshes this EditPart's <i>visuals</i>. This method is called by
	 * {@link #refresh()}, and may also be called in response to notifications
	 * from the model. This method does nothing by default. Subclasses may
	 * override.
	 */
	protected void refreshVisuals() {
	}

	/**
	 * Registers itself in the viewer's various registries. If your EditPart has
	 * a 1-to-1 relationship with a visual object and a 1-to-1 relationship with
	 * a model object, the default implementation should be sufficent.
	 * 
	 * @see #unregister()
	 * @see EditPartViewer#getVisualPartMap()
	 * @see EditPartViewer#getEditPartRegistry()
	 */
	protected void register() {
		registerModel();
		registerVisuals();
		registerAccessibility();
	}

	/**
	 * Registers the <code>AccessibleEditPart</code> adapter.
	 * 
	 * @see #getAccessibleEditPart()
	 */
	protected final void registerAccessibility() {
		if (getAccessibleEditPart() != null)
			getViewer().registerAccessibleEditPart(getAccessibleEditPart());
	}

	/**
	 * Registers the <i>model</i> in the
	 * {@link EditPartViewer#getEditPartRegistry()}. Subclasses should only
	 * extend this method if they need to register this EditPart in additional
	 * ways.
	 */
	protected void registerModel() {
		getViewer().getEditPartRegistry().put(getModel(), this);
	}

	/**
	 * Registers the <i>visuals</i> in the
	 * {@link EditPartViewer#getVisualPartMap()}. Subclasses should override
	 * this method for the visual part they support.
	 * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart}
	 * already do this.
	 */
	protected void registerVisuals() {
	}

	/**
	 * Removes a child <code>EditPart</code>. This method is called from
	 * {@link #refreshChildren()}. The following events occur in the order
	 * listed:
	 * <OL>
	 * <LI><code>EditPartListeners</code> are notified that the child is being
	 * removed
	 * <LI><code>deactivate()</code> is called if the child is active
	 * <LI>{@link EditPart#removeNotify()} is called on the child.
	 * <LI>{@link #removeChildVisual(EditPart)} is called to remove the child's
	 * visual object.
	 * <LI>The child's parent is set to <code>null</code>
	 * </OL>
	 * <P>
	 * Subclasses should implement {@link #removeChildVisual(EditPart)}.
	 * 
	 * @param child
	 *            EditPart being removed
	 * @see #addChild(EditPart,int)
	 */
	protected void removeChild(EditPart child) {
		Assert.isNotNull(child);
		int index = getChildren().indexOf(child);
		if (index < 0)
			return;
		fireRemovingChild(child, index);
		if (isActive())
			child.deactivate();
		child.removeNotify();
		removeChildVisual(child);
		child.setParent(null);
		getChildren().remove(child);
	}

	/**
	 * Removes the childs visual from this EditPart's visual. Subclasses should
	 * implement this method to support the visual type they introduce, such as
	 * Figures or TreeItems.
	 * 
	 * @param child
	 *            the child EditPart
	 */
	protected abstract void removeChildVisual(EditPart child);

	/**
	 * No reason to override
	 * 
	 * @see EditPart#removeEditPartListener(EditPartListener)
	 */
	public void removeEditPartListener(EditPartListener listener) {
		eventListeners.removeListener(EditPartListener.class, listener);
	}

	/**
	 * No reason to override
	 * 
	 * @see EditPart#removeEditPolicy(Object)
	 */
	public void removeEditPolicy(Object key) {
		if (policies == null)
			return;
		for (int i = 0; i < policies.length; i += 2) {
			if (key.equals(policies[i])) {
				i++;
				EditPolicy policy = (EditPolicy) policies[i];
				policies[i] = null;
				if (isActive() && policy != null)
					policy.deactivate();
			}
		}
	}

	/**
	 * Removes all references from the <code>EditPartViewer</code> to this
	 * EditPart. This includes:
	 * <UL>
	 * <LI>deselecting this EditPart if selected
	 * <LI>setting the Viewer's focus to <code>null</code> if this EditPart has
	 * <i>focus</i>
	 * <LI>{@link #unregister()} this EditPart
	 * </UL>
	 * <P>
	 * In addition, <code>removeNotify()</code> is called recursively on all
	 * children EditParts. Subclasses should <em>extend</em> this method to
	 * perform any additional cleanup.
	 * 
	 * @see EditPart#removeNotify()
	 */
	public void removeNotify() {
		if (getSelected() != SELECTED_NONE)
			getViewer().deselect(this);
		if (hasFocus())
			getViewer().setFocus(null);

		List children = getChildren();
		for (int i = 0; i < children.size(); i++)
			((EditPart) children.get(i)).removeNotify();
		unregister();
	}

	/**
	 * Moves a child <code>EditPart</code> into a lower index than it currently
	 * occupies. This method is called from {@link #refreshChildren()}.
	 * 
	 * @param editpart
	 *            the child being reordered
	 * @param index
	 *            new index for the child
	 */
	protected void reorderChild(EditPart editpart, int index) {
		removeChildVisual(editpart);
		List children = getChildren();
		children.remove(editpart);
		children.add(index, editpart);
		addChildVisual(editpart, index);
	}

	/**
	 * Sets the value of the specified flag. Flag values are decalared as static
	 * constants. Subclasses may define additional constants above
	 * {@link #MAX_FLAG}.
	 * 
	 * @param flag
	 *            Flag being set
	 * @param value
	 *            Value of the flag to be set
	 * @see #getFlag(int)
	 */
	protected final void setFlag(int flag, boolean value) {
		if (value)
			flags |= flag;
		else
			flags &= ~flag;
	}

	/**
	 * Called by {@link EditPartViewer} to indicate that the {@link EditPart}
	 * has gained or lost keyboard focus. Focus is considered to be part of the
	 * selected state. Therefore, only selectable {@link EditPart}s are able to
	 * obtain focus, and the method may thus only be called with a value of
	 * <code>true</code> in case the receiver is selectable, i.e.
	 * {@link #isSelectable()} returns <code>true</code>.
	 * 
	 * The method should rarely be overridden. Instead, EditPolicies that are
	 * selection-aware listen for notifications about the change of focus via
	 * {@link EditPartListener#selectedStateChanged(EditPart)}.
	 * 
	 * @see EditPart#setFocus(boolean)
	 * @see EditPartListener#selectedStateChanged(EditPart)
	 * @see SelectionEditPolicy
	 */
	public void setFocus(boolean value) {
		// only selectable edit parts may obtain focus
		Assert.isLegal(
				isSelectable() || !value,
				"An EditPart has to be selectable (isSelectable() == true) in order to obtain focus."); //$NON-NLS-1$

		if (hasFocus() == value)
			return;
		setFlag(FLAG_FOCUS, value);
		fireSelectionChanged();
	}

	/**
	 * Set the primary model object that this EditPart represents. This method
	 * is used by an <code>EditPartFactory</code> when creating an EditPart.
	 * 
	 * @see EditPart#setModel(Object)
	 */
	public void setModel(Object model) {
		this.model = model;
	}

	/**
	 * Sets the parent EditPart. There is no reason to override this method.
	 * 
	 * @see EditPart#setParent(EditPart)
	 */
	public void setParent(EditPart parent) {
		this.parent = parent;
	}

	/**
	 * Sets the selected state for this EditPart, which may be one of:
	 * <ul>
	 * <li>{@link EditPart#SELECTED_PRIMARY}</li>
	 * <li>{@link EditPart#SELECTED}</li>
	 * <li>{@link EditPart#SELECTED_NONE}</li>.
	 * </ul>
	 * 
	 * As only selectable {@link EditPart}s may get selected, the method may
	 * only be called with a selected value of {@link EditPart#SELECTED} or
	 * {@link EditPart#SELECTED_PRIMARY} in case the receiver is selectable,
	 * i.e. {@link #isSelectable()} returns <code>true</code>.
	 * 
	 * The method should rarely be overridden. Instead, EditPolicies that are
	 * selection-aware listen for notifications about the change of selection
	 * state via {@link EditPartListener#selectedStateChanged(EditPart)}.
	 * 
	 * @see EditPart#setSelected(int)
	 * @see EditPartListener#selectedStateChanged(EditPart)
	 * @see SelectionEditPolicy
	 * 
	 * @param value
	 *            the selected value
	 */
	public void setSelected(int value) {
		// only selectable edit parts may get selected.
		Assert.isLegal(
				isSelectable() || value == SELECTED_NONE,
				"An EditPart has to be selectable (isSelectable() == true) in order to get selected."); //$NON-NLS-1$

		if (selected == value)
			return;
		selected = value;
		fireSelectionChanged();
	}

	/**
	 * Shows or updates source feedback for the given <code>Request</code>. By
	 * default, this responsibility is delegated to this part's EditPolicies.
	 * Subclasses should rarely extend this method.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that feedback be handled by EditPolicies, and not
	 * directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @see EditPolicy#showSourceFeedback(Request)
	 * @see EditPart#showSourceFeedback(Request)
	 * @param request
	 *            the Request
	 */
	public void showSourceFeedback(Request request) {
		if (!isActive())
			return;
		EditPolicyIterator i = getEditPolicyIterator();
		while (i.hasNext())
			i.next().showSourceFeedback(request);
	}

	/**
	 * Shows or updates target feedback for the given <code>Request</code>. By
	 * default, this responsibility is delegated to this part's EditPolicies.
	 * Subclasses should rarely extend this method.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that feedback be handled by EditPolicies, and not
	 * directly by the EditPart.
	 * </tr>
	 * </table>
	 * 
	 * @see EditPolicy#showTargetFeedback(Request)
	 * @see EditPart#showTargetFeedback(Request)
	 * @param request
	 *            the Request
	 */
	public void showTargetFeedback(Request request) {
		if (!isActive())
			return;
		EditPolicyIterator i = getEditPolicyIterator();
		while (i.hasNext())
			i.next().showTargetFeedback(request);
	}

	/**
	 * Describes this EditPart for developmental debugging purposes.
	 * 
	 * @return a description
	 */
	public String toString() {
		String c = getClass().getName();
		c = c.substring(c.lastIndexOf('.') + 1);
		return c + "( " + getModel() + " )";//$NON-NLS-2$//$NON-NLS-1$
	}

	/**
	 * Returns <code>true</code> if this <code>EditPart</code> understand the
	 * given <code>Request</code>. By default, this responsibility is delegated
	 * to this part's installed EditPolicies.
	 * <P>
	 * <table>
	 * <tr>
	 * <td><img src="../doc-files/important.gif"/>
	 * <td>It is recommended that EditPolicies implement
	 * <code>understandsRequest()</code>
	 * </tr>
	 * </table>
	 * 
	 * @see EditPart#understandsRequest(Request)
	 */
	public boolean understandsRequest(Request req) {
		EditPolicyIterator iter = getEditPolicyIterator();
		while (iter.hasNext()) {
			if (iter.next().understandsRequest(req))
				return true;
		}
		return false;
	}

	/**
	 * Undoes any registration performed by {@link #register()}. The provided
	 * base classes will correctly unregister their visuals.
	 */
	protected void unregister() {
		unregisterAccessibility();
		unregisterVisuals();
		unregisterModel();
	}

	/**
	 * Unregisters the {@link #getAccessibleEditPart() AccessibleEditPart}
	 * adapter.
	 */
	protected final void unregisterAccessibility() {
		if (getAccessibleEditPart() != null)
			getViewer().unregisterAccessibleEditPart(getAccessibleEditPart());
	}

	/**
	 * Unregisters the <i>model</i> in the
	 * {@link EditPartViewer#getEditPartRegistry()}. Subclasses should only
	 * extend this method if they need to unregister this EditPart in additional
	 * ways.
	 */
	protected void unregisterModel() {
		Map registry = getViewer().getEditPartRegistry();
		if (registry.get(getModel()) == this)
			registry.remove(getModel());
	}

	/**
	 * Unregisters the <i>visuals</i> in the
	 * {@link EditPartViewer#getVisualPartMap()}. Subclasses should override
	 * this method for the visual part they support.
	 * {@link AbstractGraphicalEditPart} and {@link AbstractTreeEditPart}
	 * already do this.
	 */
	protected void unregisterVisuals() {
	}

}
