Bug 464510 - Introduce Delete View Model Service
https://bugs.eclipse.org/bugs/show_bug.cgi?id=464510

Change-Id: I08e5b02e92537053be4cf743dc27f72702a12b75
Signed-off-by: Johannes Faltermeier <jfaltermeier@eclipsesource.com>
diff --git a/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/DeleteService.java b/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/DeleteService.java
new file mode 100644
index 0000000..78c1c71
--- /dev/null
+++ b/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/DeleteService.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
+ *
+ * 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:
+ * Johannes Faltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.ecp.edit.spi;
+
+import java.util.Collection;
+
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecp.view.spi.context.ViewModelService;
+import org.eclipse.emf.edit.domain.EditingDomain;
+
+/**
+ * The DeleteService is used by renderers in order to delete/remove objects from the containment tree.
+ *
+ * @author jfaltermeier
+ * @since 1.6
+ *
+ */
+public interface DeleteService extends ViewModelService {
+
+	/**
+	 * Deletes the given objects from the containment tree. This will cut all references to the deleted objects.
+	 *
+	 * @param editingDomain the editing domain with command stack
+	 * @param toDelete the objects to delete
+	 */
+	void deleteElements(EditingDomain editingDomain, Collection<Object> toDelete);
+
+	/**
+	 * Deletes the given object from the containment tree. This will cut all references to the deleted object.
+	 *
+	 * @param editingDomain the editing domain with command stack
+	 * @param toDelete the object to delete
+	 */
+	void deleteElement(EditingDomain editingDomain, Object toDelete);
+
+	/**
+	 * <p>
+	 * Removes the given objects from the owning object. The elements might still be reachable from other references.
+	 * </p>
+	 * <p>
+	 * <b>Notice: </b>If the feature is a containment feature, consider using
+	 * {@link #deleteElements(EditingDomain, Collection)}
+	 * instead.
+	 * </p>
+	 *
+	 * @param editingDomain the editing domain with command stack
+	 * @param source the object which references the objects to be removed
+	 * @param feature the feature which references the objects to be removed
+	 * @param toRemove the objects to be removed
+	 */
+	void removeElements(EditingDomain editingDomain, Object source, EStructuralFeature feature,
+		Collection<Object> toRemove);
+
+	/**
+	 * <p>
+	 * Removes the given object from the owning object. The element might still be reachable from other references.
+	 * </p>
+	 * <p>
+	 * <b>Notice: </b>If the feature is a containment feature, consider using
+	 * {@link #deleteElement(EditingDomain, Object)}
+	 * instead.
+	 * </p>
+	 *
+	 * @param editingDomain the editing domain with command stack
+	 * @param source the object which references the object to be removed
+	 * @param feature the feature which references the object to be removed
+	 * @param toRemove the object to be removed
+	 */
+	void removeElement(EditingDomain editingDomain, Object source, EStructuralFeature feature, Object toRemove);
+
+}
diff --git a/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/EMFDeleteServiceImpl.java b/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/EMFDeleteServiceImpl.java
new file mode 100644
index 0000000..0db5cf9
--- /dev/null
+++ b/bundles/org.eclipse.emf.ecp.edit/src/org/eclipse/emf/ecp/edit/spi/EMFDeleteServiceImpl.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
+ *
+ * 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:
+ * Johannes Faltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.ecp.edit.spi;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
+import org.eclipse.emf.edit.command.DeleteCommand;
+import org.eclipse.emf.edit.command.RemoveCommand;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
+
+/**
+ * Default EMF implementation of the {@link DeleteService}. Uses {@link RemoveCommand} and {@link DeleteCommand}
+ * respectively.
+ *
+ * @author jfaltermeier
+ * @since 1.6
+ *
+ */
+public class EMFDeleteServiceImpl implements DeleteService {
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#instantiate(org.eclipse.emf.ecp.view.spi.context.ViewModelContext)
+	 */
+	@Override
+	public void instantiate(ViewModelContext context) {
+		// no op
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#dispose()
+	 */
+	@Override
+	public void dispose() {
+		// no op
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#getPriority()
+	 */
+	@Override
+	public int getPriority() {
+		return 1;
+	}
+
+	/**
+	 *
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.edit.spi.DeleteService#deleteElements(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.util.Collection)
+	 */
+	@Override
+	public void deleteElements(EditingDomain editingDomain, Collection<Object> toDelete) {
+		final Command deleteCommand = DeleteCommand.create(editingDomain, toDelete);
+		if (deleteCommand.canExecute()) {
+			deleteCommand.execute();
+		}
+	}
+
+	/**
+	 *
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.edit.spi.DeleteService#deleteElement(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.lang.Object)
+	 */
+	@Override
+	public void deleteElement(EditingDomain editingDomain, Object toDelete) {
+		final Command deleteCommand = DeleteCommand.create(editingDomain, toDelete);
+		if (deleteCommand.canExecute()) {
+			deleteCommand.execute();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.edit.spi.DeleteService#removeElements(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.lang.Object, org.eclipse.emf.ecore.EStructuralFeature, java.util.Collection)
+	 */
+	@Override
+	public void removeElements(EditingDomain editingDomain, Object source, EStructuralFeature feature,
+		Collection<Object> toRemove) {
+		final Command removeCommand = RemoveCommand.create(editingDomain, source, feature, toRemove);
+		if (removeCommand.canExecute()) {
+			removeCommand.execute();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.edit.spi.DeleteService#removeElement(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.lang.Object, org.eclipse.emf.ecore.EStructuralFeature, java.lang.Object)
+	 */
+	@Override
+	public void removeElement(EditingDomain editingDomain, Object source, EStructuralFeature feature, Object toRemove) {
+		if (feature.isMany()) {
+			removeElements(editingDomain, source, feature, Collections.singleton(toRemove));
+		} else {
+			final Command command = SetCommand.create(editingDomain, source, feature, SetCommand.UNSET_VALUE);
+			if (command.canExecute()) {
+				command.execute();
+			}
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.emf.ecp.editor.e3/src/org/eclipse/emf/ecp/editor/internal/e3/MEEditorPage.java b/bundles/org.eclipse.emf.ecp.editor.e3/src/org/eclipse/emf/ecp/editor/internal/e3/MEEditorPage.java
index e271311..bc68c9c 100644
--- a/bundles/org.eclipse.emf.ecp.editor.e3/src/org/eclipse/emf/ecp/editor/internal/e3/MEEditorPage.java
+++ b/bundles/org.eclipse.emf.ecp.editor.e3/src/org/eclipse/emf/ecp/editor/internal/e3/MEEditorPage.java
@@ -15,6 +15,7 @@
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.emf.ecp.editor.e3.ECPEditorContext;
+import org.eclipse.emf.ecp.spi.ui.ECPDeleteServiceImpl;
 import org.eclipse.emf.ecp.spi.ui.ECPReferenceServiceImpl;
 import org.eclipse.emf.ecp.ui.view.ECPRendererException;
 import org.eclipse.emf.ecp.ui.view.swt.ECPSWTView;
@@ -126,7 +127,7 @@
 		final EObject domainObject = modelElementContext.getDomainObject();
 		final VView view = ViewProviderHelper.getView(domainObject, null);
 		final ViewModelContext vmc = ViewModelContextFactory.INSTANCE.createViewModelContext(view, domainObject,
-			new ECPReferenceServiceImpl());
+			new ECPReferenceServiceImpl(), new ECPDeleteServiceImpl());
 		try {
 			ecpView = ECPSWTViewRenderer.INSTANCE.render(body, vmc);
 		} catch (final ECPRendererException ex) {
@@ -183,23 +184,23 @@
 
 		form.getToolBarManager().add(new Action("", Activator.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE)) { //$NON-NLS-1$
 
-				@Override
-				public void run() {
-					final EditingDomain editingDomain = AdapterFactoryEditingDomain
-						.getEditingDomainFor(modelElementContext
-							.getDomainObject());
-					new ECPCommand(modelElementContext.getDomainObject(), editingDomain) {
+			@Override
+			public void run() {
+				final EditingDomain editingDomain = AdapterFactoryEditingDomain
+					.getEditingDomainFor(modelElementContext
+						.getDomainObject());
+				new ECPCommand(modelElementContext.getDomainObject(), editingDomain) {
 
-						@Override
-						protected void doRun() {
-							EcoreUtil.delete(modelElementContext.getDomainObject(), true);
-						}
+					@Override
+					protected void doRun() {
+						EcoreUtil.delete(modelElementContext.getDomainObject(), true);
+					}
 
-					}.run(true);
+				}.run(true);
 
-					MEEditorPage.this.getEditor().close(true);
-				}
-			});
+				MEEditorPage.this.getEditor().close(true);
+			}
+		});
 		menuService.populateContributionManager((ContributionManager) form.getToolBarManager(),
 			TOOLBAR_ORG_ECLIPSE_EMF_ECP_EDITOR_INTERNAL_E3_ME_EDITOR_PAGE);
 		form.getToolBarManager().update(true);
diff --git a/bundles/org.eclipse.emf.ecp.ui.e4/src/org/eclipse/emf/ecp/ui/e4/editor/ECPE4Editor.java b/bundles/org.eclipse.emf.ecp.ui.e4/src/org/eclipse/emf/ecp/ui/e4/editor/ECPE4Editor.java
index 603fd25..b0ae031 100644
--- a/bundles/org.eclipse.emf.ecp.ui.e4/src/org/eclipse/emf/ecp/ui/e4/editor/ECPE4Editor.java
+++ b/bundles/org.eclipse.emf.ecp.ui.e4/src/org/eclipse/emf/ecp/ui/e4/editor/ECPE4Editor.java
@@ -28,6 +28,7 @@
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecp.core.ECPProject;
 import org.eclipse.emf.ecp.spi.core.InternalProvider;
+import org.eclipse.emf.ecp.spi.ui.ECPDeleteServiceImpl;
 import org.eclipse.emf.ecp.spi.ui.ECPReferenceServiceImpl;
 import org.eclipse.emf.ecp.ui.internal.e4.Activator;
 import org.eclipse.emf.ecp.ui.view.ECPRendererException;
@@ -96,7 +97,7 @@
 			// render = ECPSWTViewRenderer.INSTANCE.render(parent, modelElement);
 			final VView view = ViewProviderHelper.getView(modelElement, null);
 			final ViewModelContext vmc = ViewModelContextFactory.INSTANCE.createViewModelContext(view, modelElement,
-				new ECPReferenceServiceImpl());
+				new ECPReferenceServiceImpl(), new ECPDeleteServiceImpl());
 
 			render = ECPSWTViewRenderer.INSTANCE.render(parent, vmc);
 
diff --git a/bundles/org.eclipse.emf.ecp.ui/src/org/eclipse/emf/ecp/spi/ui/ECPDeleteServiceImpl.java b/bundles/org.eclipse.emf.ecp.ui/src/org/eclipse/emf/ecp/spi/ui/ECPDeleteServiceImpl.java
new file mode 100644
index 0000000..d8edcef
--- /dev/null
+++ b/bundles/org.eclipse.emf.ecp.ui/src/org/eclipse/emf/ecp/spi/ui/ECPDeleteServiceImpl.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
+ *
+ * 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:
+ * Johannes Faltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.ecp.spi.ui;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.emf.ecp.core.ECPProject;
+import org.eclipse.emf.ecp.core.util.ECPUtil;
+import org.eclipse.emf.ecp.edit.spi.EMFDeleteServiceImpl;
+import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
+import org.eclipse.emf.edit.domain.EditingDomain;
+
+/**
+ * ECP specific implementation of the {@link org.eclipse.emf.ecp.edit.spi.DeleteService DeleteService}.
+ *
+ * @author jfaltermeier
+ * @since 1.6
+ *
+ */
+public class ECPDeleteServiceImpl extends EMFDeleteServiceImpl {
+
+	private ECPProject ecpProject;
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#instantiate(org.eclipse.emf.ecp.view.spi.context.ViewModelContext)
+	 */
+	@Override
+	public void instantiate(ViewModelContext context) {
+		super.instantiate(context);
+		ecpProject = ECPUtil.getECPProjectManager().getProject(context.getDomainModel());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#dispose()
+	 */
+	@Override
+	public void dispose() {
+		ecpProject = null;
+		super.dispose();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.view.spi.context.ViewModelService#getPriority()
+	 */
+	@Override
+	public int getPriority() {
+		return super.getPriority() - 1;
+	}
+
+	/**
+	 *
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.emf.ecp.edit.spi.EMFDeleteServiceImpl#deleteElements(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.util.Collection)
+	 */
+	@Override
+	public void deleteElements(EditingDomain editingDomain, Collection<Object> toDelete) {
+		getECPProject().deleteElements(toDelete);
+	}
+
+	/**
+	 * 
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.emf.ecp.edit.spi.EMFDeleteServiceImpl#deleteElement(org.eclipse.emf.edit.domain.EditingDomain,
+	 *      java.lang.Object)
+	 */
+	@Override
+	public void deleteElement(EditingDomain editingDomain, Object toDelete) {
+		getECPProject().deleteElements(Collections.singleton(toDelete));
+	}
+
+	/**
+	 * Returns the ECPProject.
+	 *
+	 * @return the project
+	 */
+	ECPProject getECPProject() {
+		return ecpProject;
+	}
+
+}
diff --git a/bundles/org.eclipse.emf.ecp.view.control.multireference/src/org/eclipse/emf/ecp/view/internal/control/multireference/MultiReferenceSWTRenderer.java b/bundles/org.eclipse.emf.ecp.view.control.multireference/src/org/eclipse/emf/ecp/view/internal/control/multireference/MultiReferenceSWTRenderer.java
index 5268b2a..bfbd2c8 100644
--- a/bundles/org.eclipse.emf.ecp.view.control.multireference/src/org/eclipse/emf/ecp/view/internal/control/multireference/MultiReferenceSWTRenderer.java
+++ b/bundles/org.eclipse.emf.ecp.view.control.multireference/src/org/eclipse/emf/ecp/view/internal/control/multireference/MultiReferenceSWTRenderer.java
@@ -22,6 +22,7 @@
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.EStructuralFeature.Setting;
 import org.eclipse.emf.ecp.edit.internal.swt.controls.TableViewerColumnBuilder;
+import org.eclipse.emf.ecp.edit.spi.DeleteService;
 import org.eclipse.emf.ecp.edit.spi.ReferenceService;
 import org.eclipse.emf.ecp.view.model.common.edit.provider.CustomReflectiveItemProviderAdapterFactory;
 import org.eclipse.emf.ecp.view.spi.core.swt.AbstractControlSWTRenderer;
@@ -31,7 +32,6 @@
 import org.eclipse.emf.ecp.view.spi.swt.layout.GridDescriptionFactory;
 import org.eclipse.emf.ecp.view.spi.swt.layout.SWTGridCell;
 import org.eclipse.emf.ecp.view.spi.swt.layout.SWTGridDescription;
-import org.eclipse.emf.edit.command.RemoveCommand;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
 import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
@@ -361,13 +361,27 @@
 	 * @param tableViewer the {@link TableViewer}
 	 * @param mainSetting the {@link Setting} to delete from
 	 */
-	protected void handleDelete(TableViewer tableViewer, Setting mainSetting) {
-		final List<?> deletionList = IStructuredSelection.class.cast(tableViewer.getSelection()).toList();
+	protected void handleDelete(TableViewer tableViewer, Setting setting) {
+		final DeleteService deleteService = getViewModelContext().getService(DeleteService.class);
+		if (deleteService == null) {
+			/*
+			 * #getService(Class<?>) will report to the reportservice if it could not be found
+			 * -> simply return here
+			 */
+			return;
+		}
+		@SuppressWarnings("unchecked")
+		final List<Object> deletionList = IStructuredSelection.class.cast(tableViewer.getSelection()).toList();
+		final EditingDomain editingDomain = getEditingDomain(setting);
 
-		final EObject modelElement = mainSetting.getEObject();
-		final EditingDomain editingDomain = getEditingDomain(mainSetting);
-		editingDomain.getCommandStack().execute(
-			RemoveCommand.create(editingDomain, modelElement, mainSetting.getEStructuralFeature(), deletionList));
+		/* assured by #isApplicable */
+		final EReference reference = EReference.class.cast(setting.getEStructuralFeature());
+
+		if (reference.isContainment()) {
+			deleteService.deleteElements(editingDomain, deletionList);
+		} else {
+			deleteService.removeElements(editingDomain, setting.getEObject(), reference, deletionList);
+		}
 	}
 
 	/**
diff --git a/bundles/org.eclipse.emf.ecp.view.table.ui.swt/src/org/eclipse/emf/ecp/view/spi/table/swt/TableControlSWTRenderer.java b/bundles/org.eclipse.emf.ecp.view.table.ui.swt/src/org/eclipse/emf/ecp/view/spi/table/swt/TableControlSWTRenderer.java
index dc6362c..e16ca03 100644
--- a/bundles/org.eclipse.emf.ecp.view.table.ui.swt/src/org/eclipse/emf/ecp/view/spi/table/swt/TableControlSWTRenderer.java
+++ b/bundles/org.eclipse.emf.ecp.view.table.ui.swt/src/org/eclipse/emf/ecp/view/spi/table/swt/TableControlSWTRenderer.java
@@ -42,6 +42,7 @@
 import org.eclipse.emf.ecp.edit.internal.swt.controls.ECPFocusCellDrawHighlighter;
 import org.eclipse.emf.ecp.edit.internal.swt.controls.TableViewerColumnBuilder;
 import org.eclipse.emf.ecp.edit.internal.swt.util.CellEditorFactory;
+import org.eclipse.emf.ecp.edit.spi.DeleteService;
 import org.eclipse.emf.ecp.edit.spi.swt.table.ECPCellEditor;
 import org.eclipse.emf.ecp.edit.spi.swt.util.ECPDialogExecutor;
 import org.eclipse.emf.ecp.view.internal.table.swt.Activator;
@@ -65,7 +66,6 @@
 import org.eclipse.emf.ecp.view.template.style.tableValidation.model.VTTableValidationFactory;
 import org.eclipse.emf.ecp.view.template.style.tableValidation.model.VTTableValidationStyleProperty;
 import org.eclipse.emf.edit.command.AddCommand;
-import org.eclipse.emf.edit.command.RemoveCommand;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
 import org.eclipse.emf.emfforms.spi.localization.LocalizationServiceHelper;
@@ -484,8 +484,7 @@
 			if (getRemoveButton() != null) {
 				getRemoveButton().setEnabled(false);
 			}
-		}
-		else {
+		} else {
 			if (getRemoveButton() != null) {
 				getRemoveButton().setEnabled(true);
 			}
@@ -617,8 +616,7 @@
 		removeButton.setEnabled(false);
 		final String instanceName = clazz.getInstanceClass() == null ? "" : clazz.getInstanceClass().getSimpleName(); //$NON-NLS-1$
 		removeButton.setToolTipText(String.format(
-			LocalizationServiceHelper.getString(getClass(), MessageKeys.TableControl_RemoveSelected)
-			, instanceName));
+			LocalizationServiceHelper.getString(getClass(), MessageKeys.TableControl_RemoveSelected), instanceName));
 
 		final List<?> containments = (List<?>) mainSetting.get(true);
 		if (containments.size() <= mainSetting.getEStructuralFeature().getLowerBound()) {
@@ -658,7 +656,8 @@
 			LocalizationServiceHelper.getString(getClass(), MessageKeys.TableControl_DeleteAreYouSure),
 			MessageDialog.CONFIRM, new String[] {
 				JFaceResources.getString(IDialogLabelKeys.YES_LABEL_KEY),
-				JFaceResources.getString(IDialogLabelKeys.NO_LABEL_KEY) }, 0);
+				JFaceResources.getString(IDialogLabelKeys.NO_LABEL_KEY) },
+			0);
 
 		new ECPDialogExecutor(dialog) {
 
@@ -689,10 +688,24 @@
 	 * @param mainSetting the containment reference setting
 	 */
 	protected void deleteRows(List<EObject> deletionList, Setting mainSetting) {
-		final EObject modelElement = mainSetting.getEObject();
+		final DeleteService deleteService = getViewModelContext().getService(DeleteService.class);
+		if (deleteService == null) {
+			/*
+			 * #getService(Class<?>) will report to the reportservice if it could not be found
+			 * -> simply return here
+			 */
+			return;
+		}
 		final EditingDomain editingDomain = getEditingDomain(mainSetting);
-		editingDomain.getCommandStack().execute(
-			RemoveCommand.create(editingDomain, modelElement, mainSetting.getEStructuralFeature(), deletionList));
+
+		/* assured by #isApplicable */
+		final EReference reference = EReference.class.cast(mainSetting.getEStructuralFeature());
+		final List<Object> toDelete = new ArrayList<Object>(deletionList);
+		if (reference.isContainment()) {
+			deleteService.deleteElements(editingDomain, toDelete);
+		} else {
+			deleteService.removeElements(editingDomain, mainSetting.getEStructuralFeature(), reference, toDelete);
+		}
 	}
 
 	/**
@@ -711,7 +724,8 @@
 				.log(
 					new Status(
 						IStatus.WARNING,
-						"org.eclipse.emf.ecp.view.table.ui.swt", "The class " + clazz.getName() + " is abstract or an interface.")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+						"org.eclipse.emf.ecp.view.table.ui.swt", //$NON-NLS-1$
+						"The class " + clazz.getName() + " is abstract or an interface.")); //$NON-NLS-1$ //$NON-NLS-2$
 		}
 		final EObject modelElement = mainSetting.getEObject();
 		final EObject instance = clazz.getEPackage().getEFactoryInstance().create(clazz);
@@ -1055,8 +1069,7 @@
 				return false;
 			}
 			editable &= getItemPropertyDescriptor(setting).canSetProperty(null);
-			editable &= !CellReadOnlyTesterHelper.getInstance().isReadOnly(getVElement(), setting
-				);
+			editable &= !CellReadOnlyTesterHelper.getInstance().isReadOnly(getVElement(), setting);
 
 			if (ECPCellEditor.class.isInstance(cellEditor)) {
 				ECPCellEditor.class.cast(cellEditor).setEditable(editable);
diff --git a/bundles/org.eclipse.emf.ecp.view.treemasterdetail.ui.swt/src/org/eclipse/emf/ecp/view/spi/treemasterdetail/ui/swt/TreeMasterDetailSWTRenderer.java b/bundles/org.eclipse.emf.ecp.view.treemasterdetail.ui.swt/src/org/eclipse/emf/ecp/view/spi/treemasterdetail/ui/swt/TreeMasterDetailSWTRenderer.java
index 1ee9a11..1633490 100644
--- a/bundles/org.eclipse.emf.ecp.view.treemasterdetail.ui.swt/src/org/eclipse/emf/ecp/view/spi/treemasterdetail/ui/swt/TreeMasterDetailSWTRenderer.java
+++ b/bundles/org.eclipse.emf.ecp.view.treemasterdetail.ui.swt/src/org/eclipse/emf/ecp/view/spi/treemasterdetail/ui/swt/TreeMasterDetailSWTRenderer.java
@@ -33,6 +33,7 @@
 import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
 import org.eclipse.emf.ecp.common.spi.ChildrenDescriptorCollector;
 import org.eclipse.emf.ecp.edit.internal.swt.util.OverlayImageDescriptor;
+import org.eclipse.emf.ecp.edit.spi.DeleteService;
 import org.eclipse.emf.ecp.edit.spi.ReferenceService;
 import org.eclipse.emf.ecp.edit.spi.swt.util.SWTValidationHelper;
 import org.eclipse.emf.ecp.ui.view.ECPRendererException;
@@ -57,7 +58,6 @@
 import org.eclipse.emf.ecp.view.treemasterdetail.ui.swt.internal.TreeMasterDetailSelectionManipulatorHelper;
 import org.eclipse.emf.edit.command.AddCommand;
 import org.eclipse.emf.edit.command.CommandParameter;
-import org.eclipse.emf.edit.command.RemoveCommand;
 import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
@@ -752,10 +752,16 @@
 			@Override
 			public void run() {
 				super.run();
-				for (final Object obj : selection.toList())
-				{
-					editingDomain.getCommandStack().execute(
-						RemoveCommand.create(editingDomain, obj));
+				final DeleteService deleteService = getViewModelContext().getService(DeleteService.class);
+				if (deleteService == null) {
+					/*
+					 * #getService(Class<?>) will report to the reportservice if it could not be found
+					 * -> simply return here
+					 */
+					return;
+				}
+				for (final Object obj : selection.toList()) {
+					deleteService.deleteElement(editingDomain, obj);
 				}
 				treeViewer.setSelection(new StructuredSelection(getViewModelContext().getDomainModel()));
 			}
@@ -792,8 +798,7 @@
 			// TODO refactor
 			if (getViewModelContext().hasService(ReferenceService.class)) {
 				referenceService = getViewModelContext().getService(ReferenceService.class);
-			}
-			else {
+			} else {
 				referenceService = new DefaultReferenceService();
 			}
 		}
@@ -811,9 +816,8 @@
 					}
 					childComposite = createComposite();
 
-					final Object root = manipulateSelection(((RootObject) ((TreeViewer)
-						event.getSource()).getInput())
-							.getRoot());
+					final Object root = manipulateSelection(((RootObject) ((TreeViewer) event.getSource()).getInput())
+						.getRoot());
 					final Map<String, Object> context = new LinkedHashMap<String, Object>();
 					context.put(DETAIL_KEY, true);
 
diff --git a/tests/org.eclipse.emf.ecp.edit.swt.test/META-INF/MANIFEST.MF b/tests/org.eclipse.emf.ecp.edit.swt.test/META-INF/MANIFEST.MF
index ac8e3b7..1c1b162 100644
--- a/tests/org.eclipse.emf.ecp.edit.swt.test/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.emf.ecp.edit.swt.test/META-INF/MANIFEST.MF
@@ -6,6 +6,8 @@
 Bundle-Vendor: Eclipse Modeling Project
 Fragment-Host: org.eclipse.emf.ecp.edit.swt;bundle-version="[1.5.0,2.0.0)"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
-Require-Bundle: org.junit;bundle-version="[4.11.0,5.0.0)"
+Require-Bundle: org.junit;bundle-version="[4.11.0,5.0.0)",
+ org.eclipse.emf.emfstore.examplemodel;bundle-version="[1.5.0,2.0.0)",
+ org.eclipse.emf.ecore.xmi;bundle-version="[2.10.2,3.0.0)"
 Export-Package: org.eclipse.emf.ecp.edit.internal.swt.util;version="1.
  6.0";x-internal:=true
diff --git a/tests/org.eclipse.emf.ecp.edit.swt.test/src/org/eclipse/emf/ecp/edit/internal/swt/util/EMFDeleteSerivceImpl_PTest.java b/tests/org.eclipse.emf.ecp.edit.swt.test/src/org/eclipse/emf/ecp/edit/internal/swt/util/EMFDeleteSerivceImpl_PTest.java
new file mode 100644
index 0000000..2a10374
--- /dev/null
+++ b/tests/org.eclipse.emf.ecp.edit.swt.test/src/org/eclipse/emf/ecp/edit/internal/swt/util/EMFDeleteSerivceImpl_PTest.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2015 EclipseSource Muenchen GmbH and others.
+ *
+ * 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:
+ * jfaltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.ecp.edit.internal.swt.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.eclipse.emf.common.command.BasicCommandStack;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.emf.ecp.edit.spi.DeleteService;
+import org.eclipse.emf.ecp.edit.spi.EMFDeleteServiceImpl;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
+import org.eclipse.emf.emfstore.bowling.BowlingFactory;
+import org.eclipse.emf.emfstore.bowling.BowlingPackage;
+import org.eclipse.emf.emfstore.bowling.Game;
+import org.eclipse.emf.emfstore.bowling.League;
+import org.eclipse.emf.emfstore.bowling.Player;
+import org.eclipse.emf.emfstore.bowling.Tournament;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author jfaltermeier
+ *
+ */
+public class EMFDeleteSerivceImpl_PTest {
+
+	private DeleteService deleteService;
+	private AdapterFactoryEditingDomain domain;
+	private Resource resource;
+	private League league;
+	private Game game;
+	private Player player1;
+	private Player player2;
+	private Player player3;
+	private Tournament tournament;
+
+	@Before
+	public void setUp() {
+		deleteService = new EMFDeleteServiceImpl();
+
+		final ResourceSet resourceSet = new ResourceSetImpl();
+		resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", new XMIResourceFactoryImpl()); //$NON-NLS-1$
+		domain = new AdapterFactoryEditingDomain(
+			new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE),
+			new BasicCommandStack(), resourceSet);
+		resourceSet.eAdapters().add(new AdapterFactoryEditingDomain.EditingDomainProvider(domain));
+		resource = resourceSet.createResource(URI.createURI("VIRTUAL_URI")); //$NON-NLS-1$
+
+		league = BowlingFactory.eINSTANCE.createLeague();
+		game = BowlingFactory.eINSTANCE.createGame();
+		tournament = BowlingFactory.eINSTANCE.createTournament();
+
+		resource.getContents().add(league);
+		resource.getContents().add(game);
+		resource.getContents().add(tournament);
+
+		player1 = BowlingFactory.eINSTANCE.createPlayer();
+		player2 = BowlingFactory.eINSTANCE.createPlayer();
+		player3 = BowlingFactory.eINSTANCE.createPlayer();
+		league.getPlayers().add(player1);
+		league.getPlayers().add(player2);
+		league.getPlayers().add(player3);
+		tournament.getPlayers().add(player1);
+		tournament.getPlayers().add(player2);
+		tournament.getPlayers().add(player3);
+
+		game.setPlayer(player1);
+	}
+
+	@Test
+	public void testDeleteElements() {
+		/* act */
+		deleteService.deleteElements(domain, Arrays.asList(Object.class.cast(player1), player2));
+
+		/* assert */
+		assertEquals(1, league.getPlayers().size());
+		assertTrue(league.getPlayers().contains(player3));
+		assertEquals(1, tournament.getPlayers().size());
+		assertTrue(tournament.getPlayers().contains(player3));
+		assertNull(game.getPlayer());
+
+	}
+
+	@Test
+	public void testRemoveElementsContainment() {
+		/* act */
+		deleteService.removeElements(domain, league, BowlingPackage.eINSTANCE.getLeague_Players(),
+			Arrays.asList(Object.class.cast(player1), player2));
+
+		/* assert */
+		assertEquals(1, league.getPlayers().size());
+		assertTrue(league.getPlayers().contains(player3));
+		assertSame(player1, game.getPlayer());
+		assertEquals(3, tournament.getPlayers().size());
+	}
+
+	@Test
+	public void testDeleteElement() {
+		/* act */
+		deleteService.deleteElement(domain, player1);
+
+		/* assert */
+		assertEquals(2, league.getPlayers().size());
+		assertTrue(league.getPlayers().contains(player2));
+		assertTrue(league.getPlayers().contains(player3));
+		assertEquals(2, tournament.getPlayers().size());
+		assertTrue(tournament.getPlayers().contains(player2));
+		assertTrue(tournament.getPlayers().contains(player3));
+		assertNull(game.getPlayer());
+	}
+
+	@Test
+	public void testRemoveElementsNonContainment() {
+		/* act */
+		deleteService.removeElements(domain, tournament, BowlingPackage.eINSTANCE.getTournament_Players(),
+			Arrays.asList(Object.class.cast(player1), player2));
+
+		/* assert */
+		assertEquals(3, league.getPlayers().size());
+		assertEquals(1, tournament.getPlayers().size());
+		assertTrue(tournament.getPlayers().contains(player3));
+		assertSame(player1, game.getPlayer());
+	}
+
+	@Test
+	public void testRemoveElementNonContainment() {
+		/* act */
+		deleteService.removeElement(domain, game, BowlingPackage.eINSTANCE.getGame_Player(), player1);
+
+		/* assert */
+		assertEquals(3, league.getPlayers().size());
+		assertEquals(3, tournament.getPlayers().size());
+		assertNull(game.getPlayer());
+	}
+}