/**
 * File:    GraphicalModelElementEditPart.java
 * Created: 24.01.2006
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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:
 *    Markus Bauer, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *    Marc Blachon, Bull SAS, Grenoble, France
 *      - getting ImageFactory and FigureFactory from factory registry.
 *******************************************************************************/

package org.eclipse.jwt.we.parts.core;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.requests.SelectionRequest;
import org.eclipse.jwt.meta.model.core.ModelElement;
import org.eclipse.jwt.we.Plugin;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.figures.IImageFactory;
import org.eclipse.jwt.we.figures.core.ModelElementFigure;
import org.eclipse.jwt.we.figures.core.NamedElementFigure;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.jwt.we.misc.util.GeneralHelper;
import org.eclipse.jwt.we.misc.views.Views;
import org.eclipse.jwt.we.parts.EditPartAdapter;
import org.eclipse.jwt.we.parts.core.doubleClick.DoubleClickHandler;
import org.eclipse.jwt.we.parts.internal.EditPartAdapterSupport;

/**
 * Basic implementation of a {@link GraphicalEditPart} for a
 * {@link ModelElement}.
 * 
 * <p>
 * Subclasses <emp>must</emp> override {@link #getModelClass()}.
 * </p>
 * 
 * @version $Id: GraphicalModelElementEditPart.java,v 1.4 2008/01/31 09:51:26
 *          flautenba Exp $
 * @author Markus Bauer (markusbauer@users.sourceforge.net), Programming
 *         distributed Systems Lab, University of Augsburg, Germany,
 *         www.ds-lab.org
 * @since 0.6.0
 */
public class GraphicalModelElementEditPart extends AbstractGraphicalEditPart implements
		EditPartAdapterSupport
{

	/**
	 * A Logger.
	 */
	private static final Logger logger = Logger
			.getLogger(GraphicalModelElementEditPart.class);

	/**
	 * The workflow editor.
	 */
	protected WEEditor weeditor;

	/**
	 * Adapter which forwards the changes to this edit part.
	 */
	private EditPartAdapter adapter = new EditPartAdapter(this);


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jwt.we.parts.EditPartAdapterSupport#getAdapter()
	 */
	public Adapter getAdapter()
	{
		return adapter;
	}


	/**
	 * Returns the class of the model that the implementing EditPart represents.
	 * 
	 * Sublcasses <emp>must</emp> override this class to return their own model
	 * class.
	 * 
	 * @return The class of the model.
	 */
	public Class getModelClass()
	{
		return ModelElement.class;
	}


	/**
	 * @return An imageFactory that can be used to handle images with this
	 *         EditPart.
	 */
	public IImageFactory getImageFactory()
	{
		return Plugin.getInstance().getFactoryRegistry().getImageFactory(
				Views.getInstance().getSelectedView());
	}


	/**
	 * Returns the EMF {@link AdapterFactory} that can be used to adapt model
	 * elements.
	 * 
	 * @return The factory.
	 */
	public AdapterFactory getModelAdapterFactory()
	{
		return adapter.getModelAdapterFactory();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure()
	{
		// create the figure for the model class using the figure factory
		IFigure figure = Plugin.getInstance().getFactoryRegistry().getFigureFactory()
				.createFigure(getModelClass());

		// set image factory
		if (figure instanceof NamedElementFigure)
		{
			((NamedElementFigure) figure).setImageFactory(getImageFactory());
		}

		return figure;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getContentPane()
	 */
	@Override
	public IFigure getContentPane()
	{
		if (getFigure() != null && getFigure() instanceof ModelElementFigure)
		{
			return ((ModelElementFigure) getFigure()).getContentPane();
		}
		return super.getContentPane();
	}


	/**
	 * Does nothing. Sublcasses should override this method.
	 * 
	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
	 */
	@Override
	protected void createEditPolicies()
	{
		// installEditPolicy(EditPolicy.LAYOUT_ROLE,
		// new ModelElementLayoutEditPolicy());
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jwt.we.parts.EditPartAdapterSupport#notifyChanged(org.eclipse
	 * .emf.common .notify.Notification)
	 */
	public void notifyChanged(Notification notification)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractGraphicalEditPart#getAdapter(java.lang
	 * .Class)
	 */
	@Override
	public Object getAdapter(Class key)
	{
		logger.enter(key.getName());

		if (EditingDomain.class.isAssignableFrom(key))
		{
			return adapter.getEmfEditingDomain();
		}

		return super.getAdapter(key);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractGraphicalEditPart#refreshSourceConnections
	 * ()
	 */
	@Override
	protected void refreshSourceConnections()
	{
		// Features may be set with this editpart not yet added to the parent
		// The DeleteCommand for example will first remove the model from its
		// container and then remove features. When undoing features will be set
		// first and then added to its container.
		if (getParent() == null)
		{
			return;
		}

		super.refreshSourceConnections();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractGraphicalEditPart#refreshTargetConnections
	 * ()
	 */
	@Override
	protected void refreshTargetConnections()
	{
		if (getParent() == null)
		{
			return;
		}

		super.refreshTargetConnections();
	}


	protected String getDebugMessage(Request request)
	{
		if (logger.isDebugEnabled())
		{
			return "(" + getModelClass().getSimpleName() + ") " //$NON-NLS-1$ //$NON-NLS-2$
					+ request.getClass().getSimpleName() + ": " //$NON-NLS-1$
					+ request.getType().toString();
		}

		return null;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse
	 * .gef.Request)
	 */
	@Override
	public void performRequest(Request request)
	{
		logger.debug(getDebugMessage(request));
		super.performRequest(request);
		if (request instanceof SelectionRequest
				&& request.getType().equals(RequestConstants.REQ_OPEN))
		{
			IConfigurationElement[] extensions = Platform.getExtensionRegistry()
					.getConfigurationElementsFor("org.eclipse.jwt.we.doubleclick"); //$NON-NLS-1$
			for (int i = 0; i < extensions.length; i++)
			{
				IConfigurationElement extension = extensions[i];
				try
				{
					DoubleClickHandler factory = (DoubleClickHandler) extension
							.createExecutableExtension("DoubleClickHandler"); //$NON-NLS-1$
					if (factory.appliesTo((ModelElement) this.getModel()))
					{
						factory.processDoubleClick((ModelElement) this.getModel(),
								getViewer().getEditDomain());
					}
				}
				catch (Exception ex)
				{
					Logger.getLogger(this.getClass()).warning(
							"Could not process double-click extension", ex); //$NON-NLS-1$
				}
			}
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.editparts.AbstractEditPart#getCommand(org.eclipse.gef
	 * .Request)
	 */
	@Override
	public Command getCommand(Request request)
	{
		logger.debug(getDebugMessage(request));
		return super.getCommand(request);
	}


	/**
	 * Returns the workflow editor.
	 * 
	 * @return
	 */
	public WEEditor getWEEditor()
	{
		if (weeditor == null)
		{
			weeditor = GeneralHelper.getInstanceForEObject((EObject) getModel());
		}

		return weeditor;
	}
}
