uidesigner/com.nokia.sdt.emf.dm/src/com/nokia/sdt/emf/dm/impl/RemoveChildInstancesCommand.java
/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.sdt.emf.dm.impl;
import com.nokia.sdt.datamodel.util.ModelUtils;
import com.nokia.sdt.editor.IComponentEditor;
import com.nokia.sdt.emf.dm.INode;
import com.nokia.sdt.emf.dm.impl.NodeCopier.IFilter;
import com.nokia.cpp.internal.api.utils.core.Check;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.EMFEditPlugin;
import java.util.*;
/**
*
*/
public class RemoveChildInstancesCommand extends AbstractCommand {
protected static final String LABEL =
EMFEditPlugin.INSTANCE.getString("_UI_RemoveCommand_label");
protected static final String DESCRIPTION =
EMFEditPlugin.INSTANCE.getString("_UI_RemoveCommand_description");
private List affectedObjects;
private Map<String, List<NodeInfo>> ownerToInfoListMap;
private Map<String, NodesCopier> ownerToNodesCopierMap;
class NodeInfo {
int savedIndex;
String ownerName;
String nodeName;
}
private final List<String> objectsToRemove;
private List<NodeReferencesRestorer> nodeRestorers;
private INode rootContainer;
public RemoveChildInstancesCommand(List objectsToRemove) {
super(LABEL, DESCRIPTION);
Check.checkArg(objectsToRemove);
Set noDuplicates = new HashSet(objectsToRemove);
this.objectsToRemove = new ArrayList<String>();
for (Iterator<INode> iter = noDuplicates.iterator(); iter.hasNext();) {
INode node = iter.next();
if (rootContainer == null)
rootContainer = node.getRootContainer();
String name = node.getName();
Check.checkContract(name != null);
this.objectsToRemove.add(name);
}
}
private void sortInfoLists() {
// sort info lists by savedIndex
// so that reverse iteration will allow removal by index and
// restoration in undo preserves integrity of the saved index
for (Iterator<List<NodeInfo>> iter = ownerToInfoListMap.values().iterator(); iter.hasNext();) {
List<NodeInfo> infoList = iter.next();
Collections.sort(infoList, new Comparator<NodeInfo>() {
public int compare(NodeInfo o1, NodeInfo o2) {
return o1.savedIndex - o2.savedIndex;
}
});
}
}
private List createNodesList(List infoList) {
List<INode> nodesList = new ArrayList();
for (Iterator<NodeInfo> iter = infoList.iterator(); iter.hasNext();) {
NodeInfo info = iter.next();
INode node = rootContainer.findByNameProperty(info.nodeName);
nodesList.add(node);
}
return nodesList;
}
private static boolean containsRecursive(INode rootContainer, List<String> objectsToRemove, String nodeName) {
if (objectsToRemove.contains(nodeName))
return true;
INode node = rootContainer.findByNameProperty(nodeName);
EObject owner = node.eContainer();
if (owner instanceof INode) {
String name = ((INode) owner).getName();
Check.checkContract(name != null);
return containsRecursive(rootContainer, objectsToRemove, name);
}
return false;
}
private void initialize() {
saveNodesReferences();
ownerToInfoListMap = new HashMap();
for (Iterator<String> iter = objectsToRemove.iterator(); iter.hasNext();) {
String nodeName = iter.next();
INode node = rootContainer.findByNameProperty(nodeName);
EObject owner = node.eContainer();
// don't add any child node whose owner is also to be removed
Check.checkState(owner instanceof INode);
INode ownerNode = (INode) owner;
String ownerName = ownerNode.getName();
Check.checkContract(ownerName != null);
if (!containsRecursive(rootContainer, objectsToRemove, ownerName)) {
List infoList = ownerToInfoListMap.get(ownerName);
if (infoList == null) {
infoList = new ArrayList();
ownerToInfoListMap.put(ownerName, infoList);
}
NodeInfo info = new NodeInfo();
info.savedIndex = ownerNode.getChildren().indexOf(node);
info.ownerName = ownerName;
String name = node.getName();
Check.checkContract(name != null);
info.nodeName = name;
infoList.add(info);
}
}
sortInfoLists();
ownerToNodesCopierMap = new HashMap();
for (Iterator<String> iter = ownerToInfoListMap.keySet().iterator(); iter.hasNext();) {
String ownerName = iter.next();
List infoList = ownerToInfoListMap.get(ownerName);
List<INode> nodesList = createNodesList(infoList);
NodesCopier copier = new NodesCopier(nodesList, true, new IFilter() {
public boolean test(INode node) {
IComponentEditor componentEditor = ModelUtils.getComponentEditor(node);
return (componentEditor == null) || !componentEditor.isTemporaryObject();
}
});
ownerToNodesCopierMap.put(ownerName, copier);
}
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.command.AbstractCommand#prepare()
*/
protected boolean prepare() {
return true;
}
private void saveNodesReferences() {
// if a reference is found to a node that is being removed,
// the node is mapped to the reference owner
nodeRestorers = new ArrayList();
for (Iterator<String> iter = objectsToRemove.iterator(); iter.hasNext();) {
String nodeName = iter.next();
INode node = rootContainer.findByNameProperty(nodeName);
NodeReferencesRestorer nodeReferences = NodeReferencesRestorer.getReferencesForNode(rootContainer, node);
if (nodeReferences != null)
nodeRestorers.add(nodeReferences);
}
}
private void restoreReferences() {
for (Iterator<NodeReferencesRestorer> iter = nodeRestorers.iterator(); iter.hasNext();) {
NodeReferencesRestorer restorer = iter.next();
restorer.restoreReferences(rootContainer);
}
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.command.Command#execute()
*/
public void execute() {
if (!canExecute())
return;
if (ownerToInfoListMap == null)
initialize();
for (Iterator<String> iter = ownerToInfoListMap.keySet().iterator(); iter.hasNext();) {
String ownerName = iter.next();
INode owner = rootContainer.findByNameProperty(ownerName);
EList children = owner.getChildren();
List infoList = ownerToInfoListMap.get(ownerName);
for (Iterator<NodeInfo> iterator = infoList.iterator(); iterator.hasNext();) {
NodeInfo info = iterator.next();
INode node = rootContainer.findByNameProperty(info.nodeName);
if (node != null)
children.remove(node);
}
}
// only return affected objects for undo
affectedObjects = Collections.EMPTY_LIST;
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.command.Command#redo()
*/
public void redo() {
execute();
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.command.AbstractCommand#undo()
*/
public void undo() {
for (Iterator<String> iter = ownerToInfoListMap.keySet().iterator(); iter.hasNext();) {
String ownerName = iter.next();
List<NodeInfo> infoList = ownerToInfoListMap.get(ownerName);
NodesCopier copier = ownerToNodesCopierMap.get(ownerName);
INode owner = rootContainer.findByNameProperty(ownerName);
affectedObjects = new ArrayList();
for (int i = 0; i < infoList.size(); i++) {
NodeInfo info = infoList.get(i);
INode copy = copier.getCopy(i);
if (!hasChildWithName(owner, copy.getName())) { // may have not been deleted due to containment error
INode node = NodeCopier.copyNode(copy, owner, info.savedIndex, true, true);
String nodeName = node.getName();
Check.checkContract(nodeName != null);
info.nodeName = nodeName; // save the new node in the node info, in case of redo!
ModelUtils.getPropertyInformation(node).refresh();
affectedObjects.add(node);
}
}
}
restoreReferences();
}
private boolean hasChildWithName(INode owner, String name) {
for (Object child : owner.getChildren()) {
if (child instanceof INode) {
if (((INode) child).getName().equals(name))
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.emf.common.command.AbstractCommand#getAffectedObjects()
*/
public Collection getAffectedObjects() {
return affectedObjects;
}
}