blob: 3d713c227e95d4355a99406f8a251eac816fd29b [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.uma.edit.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.command.StrictCompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.CopyCommand;
import org.eclipse.emf.edit.command.PasteFromClipboardCommand;
import org.eclipse.emf.edit.command.CopyCommand.Helper;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.epf.uma.MethodElement;
/**
* A traceable adapter factory editing domain used for copying method elements.
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class TraceableAdapterFactoryEditingDomain extends
AdapterFactoryEditingDomain {
// Maps copied method elements to their original counterparts.
// Note: Copied elements are copies of the clipboard copies.
private HashMap<Object, Object> copyToOriginalMap = null;
// Maps original elements to their clipboard copies.
private Map<Object, Object> originalToClipboardMap = null;
private Map<EObject, EObject> clipboardToOriginalMap;
/**
* Creates a new instance.
*
* @param adapterFactory
* an adapter factory used to create the adapter to which calls
* are delegated
* @param commandStack
* a command stack
*/
public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
CommandStack commandStack) {
super(adapterFactory, commandStack);
}
/**
* Creates a new instance.
*
* @param adapterFactory
* an adapter factory used to create the adapter to which calls
* are delegated
* @param commandStack
* a command stack
* @param resourceToReadOnlyMap
* controls whether the domain is read only
*/
public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
CommandStack commandStack, Map resourceToReadOnlyMap) {
super(adapterFactory, commandStack, resourceToReadOnlyMap);
}
/**
* Creates a new instance.
*
* @param adapterFactory
* an adapter factory used to create the adapter to which calls
* are delegated
* @param commandStack
* a command stack
* @param resourceSet
* a resource set
*/
public TraceableAdapterFactoryEditingDomain(AdapterFactory adapterFactory,
CommandStack commandStack, ResourceSet resourceSet) {
super(adapterFactory, commandStack, resourceSet);
}
/**
* Returns a map containing the copied elements mapped to their original
* counterparts.
*
* @return a map containing the copied elements mapped to their original
* counterparts
*/
public Map<?, ?> getCopyToOriginalMap() {
if (copyToOriginalMap == null) {
copyToOriginalMap = new HashMap<Object, Object>();
}
return copyToOriginalMap;
}
/**
* Returns a map containing the original elements mapped to their copied
* counterparts on clipboard
*
* @return a map containing the original elements mapped to their copied
* counterparts
*/
public Map getOriginalToClipboardMap() {
if (originalToClipboardMap == null) {
originalToClipboardMap = new HashMap();
}
return originalToClipboardMap;
}
/**
* Used by the CreateCopyCommand. Adds infomation to construct maps that
* keep track of the original method elements and their copies.
*
* @param c
* a collection to store the mapping info
* @param copyHelper
* a helper class that is used to keep track of copied objects
* and their associated copies
*/
public void addCopyInfo(Collection c, Helper copyHelper) {
if (isNewCopy(c, copyHelper)) {
addNewCopy(c, copyHelper);
return;
} else {
chainCopy(c, copyHelper);
return;
}
}
/**
* Adds a new element that is being copied to the clipboard.
*/
private void addNewCopy(Collection c, Helper copyHelper) {
// this means we are copying the Collection c to the clipboard
if (originalToClipboardMap == null)
originalToClipboardMap = new HashMap();
if(clipboardToOriginalMap == null) {
clipboardToOriginalMap = new HashMap<EObject, EObject>();
}
Iterator iter = copyHelper.keySet().iterator();
while (iter.hasNext()) {
EObject key = (EObject) iter.next();
EObject value = (EObject) copyHelper.get(key);
originalToClipboardMap.put(key, value);
clipboardToOriginalMap.put(value, key);
}
}
/**
* Creates a map from the copied elements to their original counterparts.
*/
private void chainCopy(Collection c, Helper copyHelper) {
// chain the maps - change the copyToOriginalMap
if (originalToClipboardMap != null) {
if (copyToOriginalMap == null)
copyToOriginalMap = new HashMap();
Iterator iter = originalToClipboardMap.keySet().iterator();
while (iter.hasNext()) {
Object o2CKey = iter.next();
Object o2CValue = originalToClipboardMap.get(o2CKey);
Object copyValue = copyHelper.get(o2CValue);
if (copyValue == null) {
// error
continue;
}
if (o2CKey instanceof MethodElement)
copyToOriginalMap.put(copyValue, o2CKey);
}
}
}
private boolean isNewCopy(Collection c, Helper copyHelper) {
// originalToClipboardMap was set to null at start of copy command
if (originalToClipboardMap == null)
return true;
// iterate through copyHelper map, see if any copyHelper keys are o2C
// values, which means we are copying clipboard
Iterator iter = copyHelper.keySet().iterator();
while (iter.hasNext()) {
Object clipKey = iter.next();
if (!originalToClipboardMap.containsValue(clipKey))
return true;
}
return false;
}
/**
* Initializes the copy maps. It should be called within the copy action.
*/
public void resetCopyMaps() {
if (originalToClipboardMap != null) {
originalToClipboardMap.clear();
originalToClipboardMap = null;
}
if(clipboardToOriginalMap != null) {
clipboardToOriginalMap.clear();
clipboardToOriginalMap = null;
}
if (copyToOriginalMap != null) {
copyToOriginalMap.clear();
copyToOriginalMap = null;
}
}
public Map<EObject, EObject> getClipboardToOriginalMap() {
return clipboardToOriginalMap;
}
private Map<Object, Object> extenalMaintainedCopyMap;
public Map<Object, Object> getExtenalMaintainedCopyMap() {
return extenalMaintainedCopyMap;
}
public void setExtenalMaintainedCopyMap(
Map<Object, Object> extenalMaintainedCopyMap) {
this.extenalMaintainedCopyMap = extenalMaintainedCopyMap;
}
protected static class InternalPasteFromClipboardCommand extends PasteFromClipboardCommand {
public InternalPasteFromClipboardCommand(EditingDomain domain, Object owner, Object feature, int index, boolean optimize) {
super(domain, owner, feature, index, optimize);
}
@Override
protected boolean prepare()
{
// Create a strict compound command to do a copy and then add the result
//
command = new StrictCompoundCommand();
// Create a command to copy the clipboard.
//
final Command copyCommand = CopyCommand.create(domain, domain.getClipboard());
command.append(copyCommand);
// Create a proxy that will create an add command.
//
command.append
(new CommandWrapper()
{
protected Collection<Object> original;
protected Collection<Object> copy;
@Override
protected Command createCommand()
{
original = domain.getClipboard();
copy = new ArrayList<Object>(copyCommand.getResult());
// Use the original to do the add, but only if it's of the same type as the copy.
// This ensures that if there is conversion being done as part of the copy,
// as would be the case for a cross domain copy in the mapping framework,
// that we do actually use the converted instance.
//
if (original.size() == copy.size())
{
for (Iterator<Object> i = original.iterator(), j = copy.iterator(); i.hasNext(); )
{
Object originalObject = i.next();
Object copyObject = j.next();
if (originalObject.getClass() != copyObject.getClass())
{
original = null;
break;
}
}
}
Command addCommand = AddCommand.create(domain, owner, feature, copy, index);
return addCommand;
}
@Override
public void execute()
{
if (original != null)
{
domain.setClipboard(copy);
}
super.execute();
}
@Override
public void undo()
{
super.undo();
if (original != null)
{
domain.setClipboard(original);
}
}
@Override
public void redo()
{
if (original != null)
{
domain.setClipboard(copy);
}
super.redo();
}
});
boolean result;
if (optimize)
{
// This will determine canExecute as efficiently as possible.
//
result = optimizedCanExecute();
}
else
{
// This will actually execute the copy command in order to check if the add can execute.
//
result = command.canExecute();
}
return result;
}
}
public Command createCommand(Class commandClass, CommandParameter commandParameter) {
if (commandClass == PasteFromClipboardCommand.class) {
return new InternalPasteFromClipboardCommand(this, commandParameter
.getOwner(), commandParameter.getFeature(),
commandParameter.getIndex(), getOptimizeCopy());
}
return super.createCommand(commandClass, commandParameter);
}
}