/** * Copyright (c) 2005-2010 IBM Corporation 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: * IBM - Initial API and implementation */ package org.eclipse.emf.edit.command; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Map; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer; import org.eclipse.emf.edit.EMFEditPlugin; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; /** * This {@link RemoveCommand removes} an object from its parent and, * if that leaves the object orphaned from any resource, * i.e. in the usual case where its parent was its container, * additionally deletes all other references to it from within the editing domain. * @since 2.2 */ public class DeleteCommand extends CompoundCommand { /** * This creates a command that deletes the given object. */ public static Command create(EditingDomain domain, Object object) { return create(domain, Collections.singleton(object)); } /** * This creates a command that deletes the objects in the given collection. */ public static Command create(EditingDomain domain, final Collection<?> collection) { return domain.createCommand(DeleteCommand.class, new CommandParameter(null, null, collection)); } /** * This caches the label. */ protected static final String LABEL = EMFEditPlugin.INSTANCE.getString("_UI_DeleteCommand_label"); /** * This caches the description. */ protected static final String DESCRIPTION = EMFEditPlugin.INSTANCE.getString("_UI_DeleteCommand_description"); /** * This constructs a command that deletes the objects in the given collection. */ public DeleteCommand(EditingDomain domain, Collection<?> collection) { super(0, LABEL, DESCRIPTION); this.domain = domain; this.collection = collection; } /** * This is the editing domain in which this command operates. */ protected EditingDomain domain; /** * This is the collection of objects to be deleted. */ protected Collection<?> collection; /** * This returns the collection of objects to be deleted. */ public Collection<?> getCollection() { return collection; } @Override protected boolean prepare() { prepareCommand(); return super.prepare(); } protected void prepareCommand() { append(RemoveCommand.create(domain, collection)); } @Override public void execute() { Collection<EObject> eObjects = new LinkedHashSet<EObject>(); for (Object wrappedObject : collection) { Object object = AdapterFactoryEditingDomain.unwrap(wrappedObject); if (object instanceof EObject) { eObjects.add((EObject)object); for (Iterator<EObject> j = ((EObject)object).eAllContents(); j.hasNext(); ) { eObjects.add(j.next()); } } else if (object instanceof Resource) { for (Iterator<EObject> j = ((Resource)object).getAllContents(); j.hasNext(); ) { eObjects.add(j.next()); } } } Map<EObject, Collection<EStructuralFeature.Setting>> usages = findReferences(eObjects); super.execute(); for (Map.Entry<EObject, Collection<EStructuralFeature.Setting>> entry : usages.entrySet()) { EObject eObject = entry.getKey(); if (eObject.eResource() == null) { Collection<EStructuralFeature.Setting> settings = entry.getValue(); for (EStructuralFeature.Setting setting : settings) { EObject referencingEObject = setting.getEObject(); if (!eObjects.contains(referencingEObject)) { EStructuralFeature eStructuralFeature = setting.getEStructuralFeature(); if (eStructuralFeature.isChangeable()) { if (eStructuralFeature.isMany()) { appendAndExecute(RemoveCommand.create(domain, referencingEObject, eStructuralFeature, eObject)); } else { appendAndExecute(SetCommand.create(domain, referencingEObject, eStructuralFeature, SetCommand.UNSET_VALUE)); } } } } } } } /** * Returns the references to the objects in the given collection that are to be cleared. * The default implementation uses {@link UsageCrossReferencer} to find all incoming cross references. * @see UsageCrossReferencer * @since 2.6 */ protected Map<EObject, Collection<EStructuralFeature.Setting>> findReferences(Collection<EObject> eObjects) { return EcoreUtil.UsageCrossReferencer.findAll(eObjects, domain.getResourceSet()); } }