| /******************************************************************************* |
| * Copyright (c) 2008-2011 Chair for Applied Software Engineering, |
| * Technische Universitaet Muenchen. |
| * 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: |
| ******************************************************************************/ |
| package org.eclipse.emf.emfstore.internal.server.model.versioning.operations.impl; |
| |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedHashSet; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.NotificationChain; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.emfstore.internal.common.model.IdEObjectCollection; |
| import org.eclipse.emf.emfstore.internal.common.model.ModelElementId; |
| import org.eclipse.emf.emfstore.internal.common.model.impl.IdEObjectCollectionImpl; |
| import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.OperationsFactory; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.OperationsPackage; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.SingleReferenceOperation; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.UnkownFeatureException; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.UnsetType; |
| |
| /** |
| * <!-- begin-user-doc --> An implementation of the model object ' <em><b>Single Reference Operation</b></em>'. <!-- |
| * end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * <ul> |
| * <li> |
| * {@link org.eclipse.emf.emfstore.internal.server.model.versioning.operations.impl.SingleReferenceOperationImpl#getOldValue |
| * <em>Old Value</em>}</li> |
| * <li> |
| * {@link org.eclipse.emf.emfstore.internal.server.model.versioning.operations.impl.SingleReferenceOperationImpl#getNewValue |
| * <em>New Value</em>}</li> |
| * </ul> |
| * </p> |
| * |
| * @generated |
| */ |
| public class SingleReferenceOperationImpl extends ReferenceOperationImpl implements SingleReferenceOperation { |
| /** |
| * The cached value of the '{@link #getOldValue() <em>Old Value</em>}' containment reference. |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @see #getOldValue() |
| * @generated |
| * @ordered |
| */ |
| protected ModelElementId oldValue; |
| |
| /** |
| * The cached value of the '{@link #getNewValue() <em>New Value</em>}' containment reference. |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @see #getNewValue() |
| * @generated |
| * @ordered |
| */ |
| protected ModelElementId newValue; |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| protected SingleReferenceOperationImpl() { |
| super(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() { |
| return OperationsPackage.Literals.SINGLE_REFERENCE_OPERATION; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public ModelElementId getOldValue() { |
| if (oldValue != null && oldValue.eIsProxy()) |
| { |
| InternalEObject oldOldValue = (InternalEObject) oldValue; |
| oldValue = (ModelElementId) eResolveProxy(oldOldValue); |
| if (oldValue != oldOldValue) |
| { |
| InternalEObject newOldValue = (InternalEObject) oldValue; |
| NotificationChain msgs = oldOldValue.eInverseRemove(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, null, null); |
| if (newOldValue.eInternalContainer() == null) |
| { |
| msgs = newOldValue.eInverseAdd(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, null, msgs); |
| } |
| if (msgs != null) |
| msgs.dispatch(); |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.RESOLVE, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, oldOldValue, oldValue)); |
| } |
| } |
| return oldValue; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public ModelElementId basicGetOldValue() { |
| return oldValue; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public NotificationChain basicSetOldValue(ModelElementId newOldValue, NotificationChain msgs) { |
| ModelElementId oldOldValue = oldValue; |
| oldValue = newOldValue; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, oldOldValue, newOldValue); |
| if (msgs == null) |
| msgs = notification; |
| else |
| msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public void setOldValue(ModelElementId newOldValue) { |
| if (newOldValue != oldValue) |
| { |
| NotificationChain msgs = null; |
| if (oldValue != null) |
| msgs = ((InternalEObject) oldValue).eInverseRemove(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, null, msgs); |
| if (newOldValue != null) |
| msgs = ((InternalEObject) newOldValue).eInverseAdd(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, null, msgs); |
| msgs = basicSetOldValue(newOldValue, msgs); |
| if (msgs != null) |
| msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE, newOldValue, newOldValue)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public ModelElementId getNewValue() { |
| if (newValue != null && newValue.eIsProxy()) |
| { |
| InternalEObject oldNewValue = (InternalEObject) newValue; |
| newValue = (ModelElementId) eResolveProxy(oldNewValue); |
| if (newValue != oldNewValue) |
| { |
| InternalEObject newNewValue = (InternalEObject) newValue; |
| NotificationChain msgs = oldNewValue.eInverseRemove(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, null, null); |
| if (newNewValue.eInternalContainer() == null) |
| { |
| msgs = newNewValue.eInverseAdd(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, null, msgs); |
| } |
| if (msgs != null) |
| msgs.dispatch(); |
| if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.RESOLVE, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, oldNewValue, newValue)); |
| } |
| } |
| return newValue; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public ModelElementId basicGetNewValue() { |
| return newValue; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public NotificationChain basicSetNewValue(ModelElementId newNewValue, NotificationChain msgs) { |
| ModelElementId oldNewValue = newValue; |
| newValue = newNewValue; |
| if (eNotificationRequired()) |
| { |
| ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, oldNewValue, newNewValue); |
| if (msgs == null) |
| msgs = notification; |
| else |
| msgs.add(notification); |
| } |
| return msgs; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| public void setNewValue(ModelElementId newNewValue) { |
| if (newNewValue != newValue) |
| { |
| NotificationChain msgs = null; |
| if (newValue != null) |
| msgs = ((InternalEObject) newValue).eInverseRemove(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, null, msgs); |
| if (newNewValue != null) |
| msgs = ((InternalEObject) newNewValue).eInverseAdd(this, EOPPOSITE_FEATURE_BASE |
| - OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, null, msgs); |
| msgs = basicSetNewValue(newNewValue, msgs); |
| if (msgs != null) |
| msgs.dispatch(); |
| } |
| else if (eNotificationRequired()) |
| eNotify(new ENotificationImpl(this, Notification.SET, |
| OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE, newNewValue, newNewValue)); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { |
| switch (featureID) |
| { |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE: |
| return basicSetOldValue(null, msgs); |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE: |
| return basicSetNewValue(null, msgs); |
| } |
| return super.eInverseRemove(otherEnd, featureID, msgs); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) { |
| switch (featureID) |
| { |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE: |
| if (resolve) |
| return getOldValue(); |
| return basicGetOldValue(); |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE: |
| if (resolve) |
| return getNewValue(); |
| return basicGetNewValue(); |
| } |
| return super.eGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| public void eSet(int featureID, Object newValue) { |
| switch (featureID) |
| { |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE: |
| setOldValue((ModelElementId) newValue); |
| return; |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE: |
| setNewValue((ModelElementId) newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) { |
| switch (featureID) |
| { |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE: |
| setOldValue((ModelElementId) null); |
| return; |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE: |
| setNewValue((ModelElementId) null); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> <!-- end-user-doc --> |
| * |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) { |
| switch (featureID) |
| { |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__OLD_VALUE: |
| return oldValue != null; |
| case OperationsPackage.SINGLE_REFERENCE_OPERATION__NEW_VALUE: |
| return newValue != null; |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| @SuppressWarnings("serial") |
| public void apply(IdEObjectCollection project) { |
| final EObject modelElement = getModelElement(project, getModelElementId()); |
| EObject oldModelElementValue = getModelElement(project, getOldValue()); |
| final EObject newModelElementValue = getModelElement(project, getNewValue()); |
| |
| if (modelElement == null) { |
| // silently fail |
| return; |
| } |
| |
| EReference reference; |
| |
| try { |
| // FIXME: updating of old value should be replaced by re-recording mechanism |
| reference = (EReference) this.getFeature(modelElement); |
| final EObject oldModelElementReferenceValue = (EObject) modelElement.eGet(reference); |
| if (oldModelElementReferenceValue != null) { |
| ModelElementId updatedOldValue = project.getModelElementId(oldModelElementReferenceValue); |
| |
| if (updatedOldValue == null) { |
| updatedOldValue = ((IdEObjectCollectionImpl) project) |
| .getDeletedModelElementId(oldModelElementReferenceValue); |
| } |
| |
| if (updatedOldValue != null && !updatedOldValue.equals(oldValue)) { |
| oldModelElementValue = oldModelElementReferenceValue; |
| setOldValue(updatedOldValue); |
| } else if (updatedOldValue == null && oldValue != null) { |
| oldModelElementValue = null; |
| setOldValue(null); |
| } |
| } else if (oldValue != null) { |
| oldModelElementValue = null; |
| setOldValue(null); |
| } |
| |
| switch (getUnset().getValue()) { |
| case UnsetType.IS_UNSET_VALUE: |
| modelElement.eUnset(reference); |
| break; |
| case UnsetType.NONE_VALUE: |
| modelElement.eSet(reference, newModelElementValue); |
| break; |
| case UnsetType.WAS_UNSET_VALUE: |
| modelElement.eSet(reference, newModelElementValue); |
| break; |
| } |
| |
| // keep elements in the project if they are disconnected, if they |
| // really need to be deleted there will be a |
| // delete operation |
| if (reference.isContainer() && newModelElementValue == null) { |
| project.allocateModelElementIds(new LinkedHashMap<EObject, ModelElementId>() { |
| { |
| put(modelElement, getModelElementId()); |
| } |
| }); |
| project.addModelElement(modelElement); |
| } else if (reference.isContainment() && newModelElementValue == null && oldModelElementValue != null) { |
| final LinkedHashMap<EObject, ModelElementId> ids = new LinkedHashMap<EObject, ModelElementId>(); |
| ids.put(oldModelElementValue, getOldValue()); |
| project.allocateModelElementIds(ids); |
| project.addModelElement(oldModelElementValue); |
| } |
| } catch (final UnkownFeatureException e) { |
| // silently fail |
| return; |
| } |
| |
| } |
| |
| private EObject getModelElement(IdEObjectCollection collection, ModelElementId modelElementId) { |
| EObject modelElement = collection.getModelElement(modelElementId); |
| |
| if (modelElement == null) { |
| modelElement = ((IdEObjectCollectionImpl) collection).getDeletedModelElement(modelElementId); |
| } |
| |
| return modelElement; |
| } |
| |
| @Override |
| public AbstractOperation reverse() { |
| final SingleReferenceOperation singleReferenceOperation = OperationsFactory.eINSTANCE |
| .createSingleReferenceOperation(); |
| reverse(singleReferenceOperation); |
| if (getOldValue() != null) { |
| singleReferenceOperation.setNewValue(ModelUtil.clone(getOldValue())); |
| } |
| if (getNewValue() != null) { |
| singleReferenceOperation.setOldValue(ModelUtil.clone(getNewValue())); |
| } |
| |
| setUnsetForReverseOperation(singleReferenceOperation); |
| |
| return singleReferenceOperation; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.emfstore.internal.server.model.versioning.operations.ReferenceOperation#getOtherInvolvedModelElements() |
| */ |
| @Override |
| public Set<ModelElementId> getOtherInvolvedModelElements() { |
| final HashSet<ModelElementId> result = new LinkedHashSet<ModelElementId>(); |
| final ModelElementId newValue = getNewValue(); |
| if (newValue != null) { |
| result.add(newValue); |
| } |
| final ModelElementId oldValue = getOldValue(); |
| if (oldValue != null) { |
| result.add(oldValue); |
| } |
| return result; |
| } |
| |
| } // SingleReferenceOperationImpl |