/**
 * File:    EditPartAdapter.java
 * Created: 15.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
 *******************************************************************************/

package org.eclipse.jwt.we.parts;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartListener;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.RootEditPart;
import org.eclipse.jwt.we.commands.editdomain.GefEmfEditingDomain;
import org.eclipse.jwt.we.misc.logging.Logger;
import org.eclipse.jwt.we.parts.core.EdgeModelElementEditPart;
import org.eclipse.jwt.we.parts.core.GraphicalModelElementEditPart;
import org.eclipse.jwt.we.parts.internal.EditPartAdapterSupport;

/**
 * An adapter implementation for an EditPart.
 * 
 * The EditPartAdapter is an adapter for the corresponding model element of an
 * EditPart, i.e. it extends the model to be also an EditPart without
 * subclassing.
 * 
 * The EditPart cannot directly implement from the Adapter class because the
 * getTarget() Method of Adapter collides with getTarget() of a
 * AbstractConnectionEditPart. Therefore the EditPart and its Adapter are two
 * classes with a 1-to-1 relationship.
 * 
 * @version $Id: EditPartAdapter.java,v 1.13 2009-12-21 10:30:47 chsaad 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 EditPartAdapter extends AdapterImpl implements EditPartListener
{

	/**
	 * The {@link EditPartAdapterSupport} that this adapter represents.
	 */
	private EditPartAdapterSupport editPart;

	@SuppressWarnings("unused")
	private Logger logger = Logger.getLogger(this.getClass());


	/**
	 * Creates a new adapter for an {@link EditPartAdapterSupport}.
	 * 
	 * @param editPart
	 *            Listener to changes.
	 */
	public EditPartAdapter(EditPartAdapterSupport editPart)
	{
		setEditPart(editPart);
	}


	/**
	 * @return Returns the editPart.
	 */
	public EditPartAdapterSupport getEditPart()
	{
		return editPart;
	}


	/**
	 * @param newEditPart
	 *            The editPart to set.
	 */
	protected void setEditPart(EditPartAdapterSupport newEditPart)
	{
		assert newEditPart != null : "The EditPartAdapter must always have an EditPart"; //$NON-NLS-1$

		if (editPart != null)
		{
			editPart.removeEditPartListener(this);
		}

		editPart = newEditPart;
		editPart.addEditPartListener(this);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.emf.common.notify.impl.AdapterImpl#notifyChanged(org.eclipse
	 * .emf.common.notify.Notification)
	 */
	@Override
	public void notifyChanged(Notification msg)
	{
		editPart.notifyChanged(msg);
	}


	/**
	 * Returns whether the adapter is of the given type. In general, an adapter
	 * may be the adapter for many types.
	 * 
	 * An EditPart is an adapter for its model element. It knows which model
	 * element it represent and it will be asked for it by the AdapterFactory.
	 * 
	 * The implementation delegates the request to the EditPartAdapterSupport.
	 * It knows which types are supported.
	 * 
	 * @param type
	 *            the type.
	 * @return whether the adapter is of the given type.
	 */
	@Override
	public boolean isAdapterForType(Object type)
	{
		return type == editPart.getModelClass() || type == EditPartAdapter.class;
	}


	/**
	 * Delegates the newTarget to the EditPartAdapterSupport as model.
	 * 
	 * This method is called when the target model is associated with the
	 * adapter.
	 * 
	 * @param newTarget
	 *            the new notifier.
	 */
	@Override
	@SuppressWarnings("nls")
	public void setTarget(Notifier newTarget)
	{
		if (getTarget() == newTarget)
		{
			return;
		}

		assert newTarget == null
				|| editPart.getModelClass().isAssignableFrom(newTarget.getClass()) : "The model \"" //$NON-NLS-1$
				+ newTarget + "\" is not of the type \"" //$NON-NLS-1$
				+ editPart.getModelClass().getName() + "\"."; //$NON-NLS-1$

		super.setTarget(newTarget);

		if (newTarget != null)
		{
			editPart.setModel(newTarget);
		}
	}


	/**
	 * Returns the EMF editing domain of the {@link EditPart}.
	 * 
	 * This method is placed here so it can be used by
	 * {@link GraphicalModelElementEditPart} and
	 * {@link EdgeModelElementEditPart} together.
	 * 
	 * @return The {@link EditingDomain} or <code>null</code>.
	 */
	public EditingDomain getEmfEditingDomain()
	{
		if (editPart != null)
		{
			RootEditPart root = editPart.getRoot();
			if (root != null)
			{
				EditPartViewer viewer = root.getViewer();
				if (viewer != null)
				{
					EditDomain editDomain = viewer.getEditDomain();

					if (editDomain != null && editDomain instanceof GefEmfEditingDomain)
					{
						return ((GefEmfEditingDomain) editDomain).getEmfEditingDomain();
					}
				}
			}
		}

		return null;
	}


	/**
	 * Returns the EMF {@link AdapterFactory} that can be used to adapt model
	 * elements.
	 * 
	 * @return The factory.
	 */
	public AdapterFactory getModelAdapterFactory()
	{
		EditingDomain editingDomain = getEmfEditingDomain();
		if (editingDomain != null && editingDomain instanceof AdapterFactoryEditingDomain)
		{
			return ((AdapterFactoryEditingDomain) editingDomain).getAdapterFactory();
		}

		return null;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#partActivated(org.eclipse.gef.EditPart)
	 */
	public void partActivated(EditPart editpart)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#partDeactivated(org.eclipse.gef.EditPart
	 * )
	 */
	public void partDeactivated(EditPart editpart)
	{
		if (getTarget() != null)
		{
			getTarget().eAdapters().remove(this);
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#childAdded(org.eclipse.gef.EditPart,
	 * int)
	 */
	public void childAdded(EditPart child, int index)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#removingChild(org.eclipse.gef.EditPart,
	 * int)
	 */
	public void removingChild(EditPart child, int index)
	{
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.gef.EditPartListener#selectedStateChanged(org.eclipse.gef
	 * .EditPart)
	 */
	public void selectedStateChanged(EditPart editpart)
	{
	}
}
