blob: a89ee674293094d37fe9310ef40b7d8b13721e00 [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.library.edit.process.command;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.command.AbstractCommand;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.epf.library.edit.IConfigurationApplicator;
import org.eclipse.epf.library.edit.Providers;
import org.eclipse.epf.library.edit.category.ObjectLinkItemProvider;
import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.ProcessUtil;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import com.ibm.uma.Activity;
import com.ibm.uma.DescribableElement;
import com.ibm.uma.Descriptor;
import com.ibm.uma.MethodConfiguration;
import com.ibm.uma.MethodElement;
import com.ibm.uma.MethodPackage;
import com.ibm.uma.MethodPlugin;
import com.ibm.uma.Process;
import com.ibm.uma.Role;
import com.ibm.uma.RoleDescriptor;
import com.ibm.uma.Task;
import com.ibm.uma.TaskDescriptor;
import com.ibm.uma.UmaPackage;
import com.ibm.uma.WorkProductDescriptor;
/**
* Abstract base DropCommand class for breakdown structure editor
*
* @author Phong Nguyen Le
* @since 1.0
*/
public abstract class BSDropCommand extends AbstractCommand implements
IResourceAwareCommand {
protected Activity activity;
protected List dropElements;
private Set modifiedResources;
protected List elementsToAddToDefaultConfig;
private HashSet addedObjects;
private Process process;
private boolean addedToDefaultConfig = false;
protected boolean synchronize = false;
protected ArrayList taskDescList;
protected ArrayList taskDescriptorsToUpdate;
protected Set descriptorsToRefresh;
/**
* Map of descriptor to old refreshable feature map
*/
private Map descriptorToOldRefreshableFeaturesMap;
/**
* Map of descriptor to map of feature to new values
*/
protected Map descriptorToNewFeatureValuesMap;
private HashMap wpdToOldResponsibleRoleMap;
/**
* Map of TaskDescriptor to list of newly added steps
*/
private Map taskDescToNewStepsMap;
private HashMap descriptorToOldFeatureValuesMap;
protected boolean canceled;
private MethodConfiguration config;
private List synchFeatures;
/**
* @param activity
* the activity that the given elements are dropped on
* @param dropElements
* the elements to drop on the given activity
*/
public BSDropCommand(Activity activity, List dropElements) {
super();
this.activity = activity;
process = TngUtil.getOwningProcess(activity);
this.dropElements = new ArrayList();
for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
Object element = TngUtil.unwrap(iter.next());
if (element instanceof ObjectLinkItemProvider) {
element = ((ObjectLinkItemProvider) element).getTarget();
}
if (!this.dropElements.contains(element)
&& !(element instanceof EObject && ((EObject) element)
.eIsProxy())) {
this.dropElements.add(element);
}
}
}
/**
* @param synch
* if true, the command will clean the content and relationships
* of existing descriptors and refresh them with the linked
* MethodElement
*/
public BSDropCommand(Activity activity, List dropElements, boolean synch) {
this(activity, dropElements);
this.synchronize = synch;
}
/**
* Synchronize the given content elements to its TaskDescriptors in the
* given activity using the given MethodConfiguration and list of
* synchronizable features.
*
* @param activity
* @param dropElements
* the elements to synchronize
* @param config
* @param synchFeatures
* the synchronizable features
*/
public BSDropCommand(Activity activity, List dropElements,
MethodConfiguration config, List synchFeatures) {
this(activity, dropElements, true);
this.config = config;
this.synchFeatures = synchFeatures;
}
public MethodConfiguration getMethodConfiguration() {
if (config == null) {
config = TngUtil.getOwningProcess(activity).getDefaultContext();
}
return config;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.command.AbstractCommand#dispose()
*/
public void dispose() {
if (dropElements != null) {
dropElements.clear();
}
if (modifiedResources != null) {
modifiedResources.clear();
}
if (elementsToAddToDefaultConfig != null) {
elementsToAddToDefaultConfig.clear();
}
if (addedObjects != null) {
addedObjects.clear();
}
if (descriptorToOldRefreshableFeaturesMap != null) {
descriptorToOldRefreshableFeaturesMap.clear();
}
if (taskDescList != null) {
taskDescList.clear();
}
if (taskDescToNewStepsMap != null) {
taskDescToNewStepsMap.clear();
}
if (wpdToOldResponsibleRoleMap != null) {
wpdToOldResponsibleRoleMap.clear();
}
if (taskDescriptorsToUpdate != null) {
taskDescriptorsToUpdate.clear();
}
if (descriptorsToRefresh != null) {
descriptorsToRefresh.clear();
}
activity = process = null;
super.dispose();
}
/*
* (non-Javadoc)
*
* @see com.ibm.library.edit.command.IResourceAwareCommand#getModifiedResources()
*/
public Collection getModifiedResources() {
if (modifiedResources == null) {
modifiedResources = new HashSet();
if (activity.eResource() != null) {
modifiedResources.add(activity.eResource());
}
}
return modifiedResources;
}
/**
* Clears all the refreshable features of the given descriptor
*
* @param descriptor
*/
private boolean clearDescriptor(Descriptor descriptor) {
boolean ret = ProcessUtil.clearDescriptor(descriptor,
descriptorToOldRefreshableFeaturesMap);
if (ret && descriptor instanceof TaskDescriptor) {
if (taskDescriptorsToUpdate == null) {
taskDescriptorsToUpdate = new ArrayList();
}
taskDescriptorsToUpdate.add(descriptor);
}
return ret;
}
protected boolean preExecute() {
boolean b = !dropElements.isEmpty();
if (b) {
descriptorToNewFeatureValuesMap = new HashMap();
if (synchronize) {
descriptorsToRefresh = new HashSet();
}
}
return b;
}
/**
* Checks and adds elements to the default configuration
*
* @return false if user canceled the operation
*/
private boolean addToDefaultConfiguration() {
if (elementsToAddToDefaultConfig == null) {
elementsToAddToDefaultConfig = new ArrayList();
for (Iterator iter = dropElements.iterator(); iter.hasNext();) {
Object element = iter.next();
switch (UserInteractionHelper.checkAgainstDefaultConfiguration(
process, element)) {
case 0:
iter.remove();
break;
case 2:
elementsToAddToDefaultConfig.add(element);
break;
case -1:
return false;
}
}
if (!elementsToAddToDefaultConfig.isEmpty()) {
addedObjects = new HashSet();
for (Iterator iter = elementsToAddToDefaultConfig.iterator(); iter
.hasNext();) {
EObject element = (EObject) iter.next();
ProcessUtil.addToDefaultConfiguration(process, element,
addedObjects);
}
if (!addedObjects.isEmpty()) {
getModifiedResources().add(
process.getDefaultContext().eResource());
}
addedToDefaultConfig = true;
}
}
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.command.Command#execute()
*/
public void execute() {
// BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
//
// public void run() {
// canceled = !addToDefaultConfiguration();
// }
//
// });
//
// //TODO: This caused NullPointerException or ThreadAccessError when
// showing selection dialog is needed
// //
// IRunnableWithProgress runnable = new IRunnableWithProgress() {
//
// public void run(IProgressMonitor monitor) throws
// InvocationTargetException, InterruptedException {
// canceled = !preExecute();
// }
//
// };
// UserInteractionHelper.runWithProgress(runnable, null);
//
// if(!canceled) {
// BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
//
// public void run() {
// redo();
// }
//
// });
// }
BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
public void run() {
if (addToDefaultConfiguration() && preExecute()) {
redo();
}
}
});
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.command.Command#redo()
*/
public void redo() {
// add elements to the default configuration if needed
//
if (!addedToDefaultConfig) {
addToDefaultConfiguration();
}
updateDescriptors();
doExecute();
}
/**
* Updates descriptors
*/
private void updateDescriptors() {
if (synchronize) {
clearDescriptors();
}
for (Iterator iter = descriptorToNewFeatureValuesMap.entrySet()
.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
Descriptor desc = (Descriptor) entry.getKey();
Map featureMap = (Map) entry.getValue();
for (Iterator iterator = featureMap.entrySet().iterator(); iterator
.hasNext();) {
entry = (Map.Entry) iterator.next();
EStructuralFeature feature = (EStructuralFeature) entry
.getKey();
if (feature.isMany()) {
if (((List) desc.eGet(feature)).addAll((Collection) entry
.getValue())) {
System.out
.println("BSDropCommand.updateDescriptors(): changed");
System.out.println(" descriptor: " + desc);
System.out.println(" feature: " + feature);
}
} else {
Object oldValue = desc.eGet(feature);
if (oldValue != entry.getValue()) {
saveOldFeatureValue(desc, feature, oldValue);
desc.eSet(feature, entry.getValue());
System.out
.println("BSDropCommand.updateDescriptors(): changed");
System.out.println(" descriptor: " + desc);
System.out.println(" feature: " + feature);
}
}
}
}
if (synchronize) {
// refresh name, presentation name of descriptors with the value
// from associated content element
//
for (Iterator iter = descriptorsToRefresh.iterator(); iter
.hasNext();) {
Descriptor descriptor = (Descriptor) iter.next();
MethodElement e = ProcessUtil.getAssociatedElement(descriptor);
if (!descriptor.getName().equals(e.getName())) {
saveOldFeatureValue(descriptor, UmaPackage.eINSTANCE
.getNamedElement_Name(), descriptor.getName());
descriptor.setName(e.getName());
System.out
.println("BSDropCommand.updateDescriptors(): name changed "
+ descriptor);
}
if (e instanceof DescribableElement) {
String presName = ((DescribableElement) e)
.getPresentationName();
if (!presName.equals(descriptor.getPresentationName())) {
saveOldFeatureValue(descriptor, UmaPackage.eINSTANCE
.getDescribableElement_PresentationName(),
descriptor.getPresentationName());
descriptor.setPresentationName(presName);
System.out
.println("BSDropCommand.updateDescriptors(): presentation name changed "
+ descriptor);
}
}
}
}
updateTaskDescriptors();
setResponsibleRole();
}
/**
* @param desc
* @param feature
* @param value
*/
private void saveOldFeatureValue(Descriptor desc,
EStructuralFeature feature, Object value) {
if (descriptorToOldFeatureValuesMap == null) {
descriptorToOldFeatureValuesMap = new HashMap();
}
Map featureMap = (Map) descriptorToOldFeatureValuesMap.get(desc);
if (featureMap == null) {
featureMap = new HashMap();
descriptorToOldFeatureValuesMap.put(desc, featureMap);
}
featureMap.put(feature, value);
}
private void undoUpdateDescriptors() {
undoSetResponsibleRole();
undoUpdateTaskDescriptors();
if (descriptorToNewFeatureValuesMap != null) {
for (Iterator iter = descriptorToNewFeatureValuesMap.entrySet()
.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
Descriptor desc = (Descriptor) entry.getKey();
Map featureMap = (Map) entry.getValue();
for (Iterator iterator = featureMap.entrySet().iterator(); iterator
.hasNext();) {
entry = (Map.Entry) iterator.next();
EStructuralFeature feature = (EStructuralFeature) entry
.getKey();
if (feature.isMany()) {
((List) desc.eGet(feature))
.removeAll((Collection) entry.getValue());
}
}
}
}
// restore single-value feature
//
if (descriptorToOldFeatureValuesMap != null) {
for (Iterator iter = descriptorToOldFeatureValuesMap.entrySet()
.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
Descriptor desc = (Descriptor) entry.getKey();
Map featureMap = (Map) entry.getValue();
for (Iterator iterator = featureMap.entrySet().iterator(); iterator
.hasNext();) {
entry = (Map.Entry) iterator.next();
EStructuralFeature feature = (EStructuralFeature) entry
.getKey();
desc.eSet(feature, entry.getValue());
}
}
}
// restore value for refreshable features that had been cleared
//
if (synchronize) {
undoClearDescriptors();
}
}
/**
*
*/
private void clearDescriptors() {
if (descriptorToOldRefreshableFeaturesMap == null) {
descriptorToOldRefreshableFeaturesMap = new HashMap();
if (!descriptorsToRefresh.isEmpty()) {
for (Iterator iter = descriptorsToRefresh.iterator(); iter
.hasNext();) {
clearDescriptor((Descriptor) iter.next());
}
// descriptorsToRefresh.clear();
}
}
}
/**
* Updates affected task descriptors with new data from method content
*/
private void updateTaskDescriptors() {
if (taskDescriptorsToUpdate != null) {
if (taskDescToNewStepsMap == null) {
taskDescToNewStepsMap = new HashMap();
}
IConfigurationApplicator configApplicator = Providers
.getConfigurationApplicator();
for (Iterator iter = taskDescriptorsToUpdate.iterator(); iter
.hasNext();) {
TaskDescriptor taskDesc = (TaskDescriptor) iter.next();
Task task = taskDesc.getTask();
if (task != null && !((EObject) task).eIsProxy()) {
List steps = (List) configApplicator.getReference(task
.getPresentation(), UmaPackage.eINSTANCE
.getContentDescription_Sections(), config);
// add those steps to TaskDescriptor if they are not there
// yet.
//
ArrayList newSteps = new ArrayList();
taskDesc.getSelectedSteps().retainAll(steps);
for (Iterator iter1 = steps.iterator(); iter1.hasNext();) {
Object step = iter1.next();
if (!taskDesc.getSelectedSteps().contains(step)) {
newSteps.add(step);
}
}
if (!newSteps.isEmpty()) {
taskDesc.getSelectedSteps().addAll(newSteps);
taskDescToNewStepsMap.put(taskDesc, newSteps);
System.out
.println("BSDropCommand.updateTaskDescriptors(): changed");
}
}
}
}
}
private void undoUpdateTaskDescriptors() {
if (taskDescToNewStepsMap != null) {
for (Iterator iter = taskDescToNewStepsMap.entrySet().iterator(); iter
.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
TaskDescriptor taskDesc = (TaskDescriptor) entry.getKey();
taskDesc.getSelectedSteps().removeAll(
(Collection) entry.getValue());
}
}
}
/**
* Go thru all the work product descriptors of this activity and set the
* responsible role for them if there is any
*/
private void setResponsibleRole() {
if (wpdToOldResponsibleRoleMap == null) {
wpdToOldResponsibleRoleMap = new HashMap();
}
List brElements = activity.getBreakdownElements();
List wpDescList = new ArrayList();
List roleDescriptors = new ArrayList();
for (Iterator itor = brElements.iterator(); itor.hasNext();) {
Object obj = itor.next();
if (obj instanceof WorkProductDescriptor) {
wpDescList.add(obj);
} else if (obj instanceof RoleDescriptor) {
roleDescriptors.add(obj);
}
}
for (Iterator itor = roleDescriptors.iterator(); itor.hasNext();) {
RoleDescriptor roleDesc = (RoleDescriptor) itor.next();
Role role = roleDesc.getRole();
if (role != null) {
List responsibleWorkProducts = role.getResponsibleFor();
for (int j = wpDescList.size() - 1; j > -1; j--) {
WorkProductDescriptor wpDesc = (WorkProductDescriptor) wpDescList
.get(j);
if (responsibleWorkProducts.contains(wpDesc
.getWorkProduct())
&& wpDesc.getResponsibleRole() != roleDesc) {
wpdToOldResponsibleRoleMap.put(wpDesc, wpDesc
.getResponsibleRole());
wpDesc.setResponsibleRole(roleDesc);
System.out
.println("BSDropCommand.setResponsibleRole(): changed");
}
}
}
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.common.command.AbstractCommand#undo()
*/
public void undo() {
// remove any object that had been added to the default configuration
//
if (addedObjects != null && !addedObjects.isEmpty()) {
MethodConfiguration config = process.getDefaultContext();
for (Iterator iter = addedObjects.iterator(); iter.hasNext();) {
Object element = iter.next();
if (element instanceof MethodPlugin) {
config.getMethodPluginSelection().remove(element);
} else if (element instanceof MethodPackage) {
config.getMethodPackageSelection().remove(element);
}
}
addedToDefaultConfig = false;
}
undoUpdateDescriptors();
doUndo();
}
/**
*
*/
private void undoClearDescriptors() {
for (Iterator iter = descriptorToOldRefreshableFeaturesMap.entrySet()
.iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
Descriptor desc = (Descriptor) entry.getKey();
Map featureMap = (Map) entry.getValue();
for (Iterator iterator = featureMap.entrySet().iterator(); iterator
.hasNext();) {
entry = (Map.Entry) iterator.next();
desc
.eSet((EStructuralFeature) entry.getKey(), entry
.getValue());
}
}
}
/**
* Undoes the change made by
* {@link #setResponsibleRole() setResponsibleRole() }
*/
private void undoSetResponsibleRole() {
for (Iterator iter = wpdToOldResponsibleRoleMap.entrySet().iterator(); iter
.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
WorkProductDescriptor wpd = (WorkProductDescriptor) entry.getKey();
wpd.setResponsibleRole((RoleDescriptor) entry.getValue());
}
}
protected boolean prepare() {
return true;
}
protected abstract void doExecute();
protected abstract void doUndo();
public static interface IExecutor {
boolean preExecute();
void doExcecute();
void doUndo();
}
}