/*****************************************************************************
* Copyright (c) 2010 CEA LIST.
*
* 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:
* Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
*****************************************************************************/
package org.eclipse.papyrus.uml.tools.databinding;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
import org.eclipse.papyrus.infra.emf.databinding.EMFObservableValue;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils;
import org.eclipse.papyrus.infra.services.edit.service.IElementEditService;
import org.eclipse.papyrus.infra.tools.databinding.AggregatedObservable;
import org.eclipse.papyrus.uml.tools.Activator;
/**
* An ObservableValue used to edit EObject properties through
* Papyrus commands
*
* @author Camille Letavernier
*
*/
public class PapyrusObservableValue extends EMFObservableValue implements AggregatedObservable, CommandBasedObservableValue {
/**
*
* Constructor.
*
* @param eObject
* The EObject to edit
* @param eStructuralFeature
* The structural feature to edit
* @param domain
* The editing domain on which the commands will be executed
*/
public PapyrusObservableValue(EObject eObject, EStructuralFeature eStructuralFeature, EditingDomain domain) {
this(Realm.getDefault(), eObject, eStructuralFeature, domain);
}
/**
*
* Constructor.
*
* @param realm
* @param eObject
* The EObject to edit
* @param eStructuralFeature
* The structural feature to edit
* @param domain
* The editing domain on which the commands will be executed
*/
public PapyrusObservableValue(Realm realm, EObject eObject, EStructuralFeature eStructuralFeature, EditingDomain domain) {
super(eObject, eStructuralFeature, domain);
}
@Override
protected void doSetValue(Object value) {
Command emfCommand = getCommand(value);
domain.getCommandStack().execute(emfCommand);
}
/**
* {@inheritDoc}
*/
public Command getCommand(Object value) {
EObject eObjectValue = EMFHelper.getEObject(value);
if(eObjectValue != null) {
value = eObjectValue;
}
Object oldValue = getValue();
try {
IElementEditService provider = ElementEditServiceUtils.getCommandProvider(getObserved());
if(provider != null) {
CompositeCommand cc = new CompositeCommand("Edit value");
if (oldValue instanceof EObject && eStructuralFeature instanceof EReference && ((EReference)eStructuralFeature).isContainment()) {
cc.add(provider.getEditCommand(new DestroyElementRequest((TransactionalEditingDomain)domain, (EObject)oldValue, false)));
}
cc.add(provider.getEditCommand(new SetRequest((TransactionalEditingDomain)domain, eObject, eStructuralFeature, value)));
return new GMFtoEMFCommandWrapper(cc);
}
} catch (Exception ex) {
Activator.log.error(ex);
}
return UnexecutableCommand.INSTANCE;
}
/**
*
* @return the {@link EStructuralFeature} observed by this object
*/
public EStructuralFeature getEStructuralFeature() {
return eStructuralFeature;
}
/**
*
* @return the {@link EObject} observed by this object
*/
public EObject getEObject() {
return eObject;
}
public AggregatedObservable aggregate(IObservable observable) {
try {
return new AggregatedPapyrusObservableValue(domain, this, observable);
} catch (IllegalArgumentException ex) {
return null; //The observable cannot be aggregated
}
}
public boolean hasDifferentValues() {
return false; //The value is not aggregated yet
}
}