/**
 * File:    InitializeCopyCommandWithAspects.java
 * Created: 10.05.2010
 *
 *
/*******************************************************************************
 * Copyright (c) 2010 Open Wide SA <www.openwide.fr>
 *
 * 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:
 *    Marc Dutoo, Open Wide SA 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.conf.edit.aspects.provider.command;

import java.util.Collection;
import java.util.ListIterator;

import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.InitializeCopyCommand;
import org.eclipse.emf.edit.command.CopyCommand.Helper;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jwt.we.conf.model.AspectInstance;
import org.eclipse.jwt.we.conf.model.ConfPackage;


/**
 * Command that (in addition to "traditional" InitializeCopy)
 *    * on a model element, sets its aspects' target to itself
 *    * on an aspect, doesn't copy its target model element
 * (since it's rather initialized in the case above)
 * 
 * @version $Id: InitializeCopyCommandWithAspects.java,v 1.2 2010-05-27 15:42:49 mdutoo Exp $
 * @author Marc Dutoo, Open Wide SA
 *
 */
public class InitializeCopyCommandWithAspects extends InitializeCopyCommand implements
		Command {

	public InitializeCopyCommandWithAspects(EditingDomain domain, EObject owner,
			Helper copyHelper) {
		super(domain, owner, copyHelper);
	}


	/**
	 * Copies all references, save an aspect's target (thanks to getReferencesToCopy()),
	 * and on a model element sets its aspects' target to itself (done in setCopiedAspects()).
	 */
	protected void copyReferences() {
		//copyAspectTargetReference();
		setCopiedAspects();

		// normal behaviour for non aspect instances
		super.copyReferences();
	}


	/**
	 * Returns all references, save ConfPackage.eINSTANCE.getAspectInstance_TargetModelElement().
	 */
	@SuppressWarnings("unchecked")
	protected Collection<? extends EReference> getReferencesToCopy() {
		Collection<? extends EReference> superReferencesToCopy = super.getReferencesToCopy();
		if (!(owner instanceof AspectInstance)) {
			// normal behaviour for non aspect instances
			return superReferencesToCopy;
		}

		// removing the targetModelElementRef from the list
		EReference targetModelElementRef = ConfPackage.eINSTANCE.getAspectInstance_TargetModelElement();
		BasicEList<? extends EReference> eRefs = (BasicEList<? extends EReference>) new BasicEList(superReferencesToCopy);
		for (ListIterator<? extends EReference> eRefIt = eRefs.listIterator(); eRefIt.hasNext();) {
			if (eRefIt.next().getEType().equals(targetModelElementRef)) {
				eRefIt.remove();
				break;
			}
		}
		return eRefs;
	}

	/**
	 * Sets the current copy's aspects target to this command's owner.
	 */
	protected void setCopiedAspects() {
		if (this.owner instanceof AspectInstance) {
			return;
		}

		for (EObject element : copyHelper.values()) {
			if (element instanceof AspectInstance) {
				AspectInstance aspectInstance = (AspectInstance) element;

				if (this.owner.equals(aspectInstance.getTargetModelElement())) {
					// it is an aspect targeting the original of the copyied element being inited
					// so update its target element to the copy
					EObject foundCopiedAspectInstance = copyHelper.getCopy(aspectInstance);
					if (!(foundCopiedAspectInstance instanceof AspectInstance)) {
						// TODO log warn ; null ?!!
						continue;
					}
					AspectInstance copiedAspectInstance = (AspectInstance) foundCopiedAspectInstance;
					copiedAspectInstance.setTargetModelElement(copy);
					continue;
				}
			}
		}
	}

}
