//------------------------------------------------------------------------------ // Copyright (c) 2005, 2007 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.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.util.AbstractTreeIterator; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.epf.library.edit.IConfigurator; import org.eclipse.epf.library.edit.Providers; import org.eclipse.epf.library.edit.command.BatchCommand; 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.epf.library.edit.validation.UniqueNamePNameHandler; import org.eclipse.epf.uma.Activity; import org.eclipse.epf.uma.Artifact; import org.eclipse.epf.uma.Deliverable; import org.eclipse.epf.uma.MethodConfiguration; import org.eclipse.epf.uma.ProcessPackage; import org.eclipse.epf.uma.RoleDescriptor; import org.eclipse.epf.uma.Task; import org.eclipse.epf.uma.TaskDescriptor; import org.eclipse.epf.uma.UmaPackage; import org.eclipse.epf.uma.VariabilityElement; import org.eclipse.epf.uma.WorkProduct; import org.eclipse.epf.uma.WorkProductDescriptor; /** * Command to drag and drop work products to Work Product Usage breakdown * structure * * @author Phong Nguyen Le * @author Shilpa Toraskar * @since 1.0 */ public class PBSDropCommand extends BSDropCommand { private ArrayList wpDescList; private ArrayList roleDescList; private Map wpDescToDeliverableParts; private HashMap<WorkProductDescriptor, WorkProductDescriptor> wpdToDeliverableDescriptorMap; private BatchCommand updateDeliverablePartsCmd; private boolean newDuplicatesRemoved; private IConfigurator configurator; private ArrayList linkedTasks; private HashMap wpdToTaskFeaturesMap; public PBSDropCommand(Activity activity, List workProducts) { super(activity, workProducts); this.activity = activity; for (Iterator iter = dropElements.iterator(); iter.hasNext();) { Object element = iter.next(); if (!(element instanceof WorkProduct)) { iter.remove(); } } } /** * @param activity * @param dropElements * @param synch */ public PBSDropCommand(Activity activity, List dropElements, boolean synch) { super(activity, dropElements, synch); } /** * @param activity * @param dropElements * @param config * @param synchFeatures */ public PBSDropCommand(Activity activity, List dropElements, MethodConfiguration config, Set synchFeatures, IConfigurator configurator) { super(activity, dropElements, config, synchFeatures); this.configurator = configurator; } /* * (non-Javadoc) * * @see com.ibm.library.edit.process.command.BSDropCommand#preExecute() */ protected boolean preExecute() { if (!super.preExecute()) return false; wpDescList = new ArrayList(); taskDescList = new ArrayList(); roleDescList = new ArrayList(); wpDescToDeliverableParts = new HashMap(); wpdToDeliverableDescriptorMap = new HashMap(); if(!synchronize || (synchronize && synchFeatures.contains(UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts()))) { // add subartifacts to dropElements list if there is any // for (Iterator iter = new ArrayList(dropElements).iterator(); iter .hasNext();) { Object element = iter.next(); if (element instanceof Artifact) { Iterator iterator = new AbstractTreeIterator(element, false) { /** * Comment for <code>serialVersionUID</code> */ private static final long serialVersionUID = -4820477887426087262L; protected Iterator getChildren(Object object) { Object subArtifacts = Providers.getConfigurationApplicator().getReference( (VariabilityElement) object, UmaPackage.eINSTANCE.getArtifact_ContainedArtifacts(), getMethodConfiguration()); return ((Collection)subArtifacts).iterator(); } }; while (iterator.hasNext()) { Artifact subArtifact = (Artifact) iterator.next(); if (!dropElements.contains(subArtifact) && prepareAdd((WorkProduct) subArtifact)) { dropElements.add(subArtifact); } } } } } MethodConfiguration config = getMethodConfiguration(); Set descriptorsToRefresh = synchronize ? batchCommand.getDescriptorsToRefresh() : null; List bes = activity.getBreakdownElements(); UniqueNamePNameHandler uniqueNamesHandler = new UniqueNamePNameHandler(bes); for (int i = 0; i < dropElements.size(); i++) { WorkProduct wp = (WorkProduct) dropElements.get(i); if (TngUtil.isContributor(wp)) { wp = (WorkProduct) TngUtil.getBase(wp); } WorkProductDescriptor wpDesc = null; if (synchronize) { wpDesc = (WorkProductDescriptor) ProcessCommandUtil .getBestDescriptor(wp, activity, config); } if (wpDesc == null) { wpDesc = ProcessCommandUtil.createWorkProductDescriptor(wp, config, wpDescToDeliverableParts); // uniqueNamesHandler.ensureUnique(wpDesc); wpDescList.add(wpDesc); // automatic adding to the existing deliverable descriptor in // the activity's scope if there is any // valid one. // WorkProductDescriptor descriptor = UserInteractionHelper .getDeliverable(activity, wp); if (descriptor != null) { wpdToDeliverableDescriptorMap.put(wpDesc, descriptor); } if(wpdToTaskFeaturesMap != null) { // replace work product with its work product descriptor in wpdToTaskFeaturesMap // Map featuresMap = (Map) wpdToTaskFeaturesMap.get(wp); if(featuresMap != null) { wpdToTaskFeaturesMap.remove(wp); wpdToTaskFeaturesMap.put(wpDesc, featuresMap); } } } else { if (descriptorsToRefresh != null && wpDesc.getIsSynchronizedWithSource().booleanValue()) { descriptorsToRefresh.add(wpDesc); } if (wp instanceof Deliverable && synchFeatures.contains(UmaPackage.eINSTANCE.getDeliverable_DeliveredWorkProducts())) { ProcessCommandUtil.createDeliverableParts(wpDesc, (Deliverable) wp, config, wpDescToDeliverableParts, descriptorsToRefresh); } if(wpdToTaskFeaturesMap != null) { wpdToTaskFeaturesMap.remove(wp); } } if (!synchronize) { // get all possible tasks for this workproduct for // which task descriptor needs to be created List tasks = ProcessUtil.getTasksForWorkProduct(wp, config); if ((tasks != null) && (tasks.size() > 0)) { // show task selections dialog final List finalTasks = tasks; final WorkProduct finalWp = wp; final List finalSelected = new ArrayList(); List selectedTasks = new ArrayList(); // show task selections dialog UserInteractionHelper.getUIHelper().runSafely(new Runnable() { public void run() { List selected = UserInteractionHelper.selectTasks( finalTasks, finalWp); finalSelected.addAll(selected); } }, true); selectedTasks.addAll(finalSelected); // create task descriptors for this workproduct if ((selectedTasks != null) && (!(selectedTasks.isEmpty()))) { for (int j = 0; j < selectedTasks.size(); j++) { Task task = (Task) selectedTasks.get(j); // call this method even the descriptor for the // given task already exists in this activity // to add any additional relationships in case of // recent change in the default configuration // of the process. PBSDropCommand.addToDescriptorLists(task, activity, taskDescList, roleDescList, wpDescList, wpDescToDeliverableParts, descriptorsToRefresh, batchCommand.getObjectToNewFeatureValuesMap(), config, true, synchFeatures); } } else { // If no tasks are selected, add Responsible role to wp ProcessCommandUtil.addResponsibleRoleDescriptors(wpDesc, activity, roleDescList, descriptorsToRefresh, config); } } else { // If there are no tasks to show, add Responsible role to wp ProcessCommandUtil.addResponsibleRoleDescriptors(wpDesc, activity, roleDescList, descriptorsToRefresh, config); } } // else { // // in case of synchronization, add Responsible role to wp // if (synchFeatures.contains(UmaPackage.eINSTANCE.getRole_ResponsibleFor())) // PBSDropCommand.addResponsibleRole(wpDesc, activity, roleDescList, descriptorsToRefresh, config); // } } if(!wpDescToDeliverableParts.isEmpty()) { updateDeliverablePartsCmd = new BatchCommand(true); for (Iterator iter = wpDescToDeliverableParts.entrySet().iterator(); iter .hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); Object wpDesc = entry.getKey(); updateDeliverablePartsCmd.getObjectToNewFeatureValuesMap().put(wpDesc, Collections.singletonMap(UmaPackage.eINSTANCE.getWorkProductDescriptor_DeliverableParts(), entry.getValue())); } } // ensure unique names for wp descriptors for (int i = 0; i < wpDescList.size(); i++) { WorkProductDescriptor wpDesc = (WorkProductDescriptor) wpDescList .get(i); if (wpDesc != null) { uniqueNamesHandler.ensureUnique(wpDesc); } } return !taskDescList.isEmpty() || !roleDescList.isEmpty() || !wpDescList.isEmpty() || (updateDeliverablePartsCmd != null && updateDeliverablePartsCmd.canExecute()) || !wpdToDeliverableDescriptorMap.isEmpty() || (descriptorsToRefresh != null && !descriptorsToRefresh .isEmpty()) || batchCommand.canExecute(); } /** * @param subArtifact * @return */ private boolean prepareAdd(WorkProduct wp) { if (synchronize) { // get linked tasks of the task descriptors in the activity for the configuration // List tasks = getLinkedTasks(); if(!tasks.isEmpty()) { // select only work products that are input or output of an existing task in the activity // Map featuresMap = ProcessCommandUtil.getFeaturesMap(tasks, wp, getMethodConfiguration()); if(!featuresMap.isEmpty()) { // use the wp to the key in the map right now and replace it with // its work product descriptor later // if(wpdToTaskFeaturesMap == null) { wpdToTaskFeaturesMap = new HashMap(); } wpdToTaskFeaturesMap.put(wp, featuresMap); return true; } } return false; } return true; } /** * @return */ private List getLinkedTasks() { if(linkedTasks == null) { linkedTasks = new ArrayList(); for (Iterator iter = activity.getBreakdownElements().iterator(); iter.hasNext();) { Object element = iter.next(); if(element instanceof TaskDescriptor) { Task task = ((TaskDescriptor)element).getTask(); if(task != null && configurator.accept(element)) { linkedTasks.add(task); } } } } return linkedTasks; } /** * Removes new elements that are duplicate b/c they are created by the previous WBSDropCommand */ private void removeNewDuplicates() { if(synchronize) { if(!newDuplicatesRemoved) { for (Iterator iter = roleDescList.iterator(); iter.hasNext();) { RoleDescriptor roleDesc = (RoleDescriptor) iter.next(); Object desc = ProcessCommandUtil.getDescriptor(roleDesc.getRole(), activity, getMethodConfiguration()); if(desc != null) { iter.remove(); } } newDuplicatesRemoved = true; } } } /* * (non-Javadoc) * * @see com.ibm.library.edit.process.command.BSDropCommand#doExecute() */ protected void doExecute() { removeNewDuplicates(); // automatically add work product descriptor to deliverable part // if (!wpdToDeliverableDescriptorMap.isEmpty()) { for (Map.Entry<WorkProductDescriptor, WorkProductDescriptor> entry : wpdToDeliverableDescriptorMap.entrySet()) { WorkProductDescriptor deliverable = (WorkProductDescriptor) entry .getValue(); deliverable.getDeliverableParts().add(entry.getKey()); } } // add work product descriptors // activity.getBreakdownElements().addAll(wpDescList); // add task descriptors // activity.getBreakdownElements().addAll(taskDescList); // add role descriptors // activity.getBreakdownElements().addAll(roleDescList); // associate new work product descriptors with task descriptors // if(wpdToTaskFeaturesMap != null) { for (Iterator iter = wpdToTaskFeaturesMap.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); Map taskFeatures = (Map) entry.getValue(); for (Iterator iterator = taskFeatures.entrySet().iterator(); iterator .hasNext();) { Map.Entry ent = (Map.Entry) iterator.next(); TaskDescriptor taskDesc = (TaskDescriptor) ProcessCommandUtil.getDescriptor(ent.getKey(), activity.getBreakdownElements(), getMethodConfiguration(), false); for (Iterator iterator1 = ((Collection)ent.getValue()).iterator(); iterator1 .hasNext();) { EStructuralFeature f = (EStructuralFeature) iterator1.next(); EStructuralFeature descFeature = (EStructuralFeature) FEATURE_MAP.get(f); if(descFeature.isMany()) { ((List)taskDesc.eGet(descFeature)).add(entry.getKey()); } else { // TODO: need to back up old value here // taskDesc.eSet(descFeature, entry.getKey()); } } } } } // add new descriptors to activity's package // ProcessPackage pkg = (ProcessPackage) activity.eContainer(); if (pkg != null) { pkg.getProcessElements().addAll(taskDescList); pkg.getProcessElements().addAll(roleDescList); pkg.getProcessElements().addAll(wpDescList); for (Iterator iter = wpDescToDeliverableParts.values().iterator(); iter .hasNext();) { pkg.getProcessElements().addAll((Collection) iter.next()); } } // getModifiedResources().add(activity.eResource()); } /* (non-Javadoc) * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#updateDescriptors() */ protected void updateDescriptors() { super.updateDescriptors(); // add deliverable parts to the work product descriptors // if(updateDeliverablePartsCmd != null) { updateDeliverablePartsCmd.execute(); } } /* (non-Javadoc) * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#undoUpdateDescriptors() */ protected void undoUpdateDescriptors() { // remove deliverable parts of the work product descriptors // if(updateDeliverablePartsCmd != null) { updateDeliverablePartsCmd.undo(); } super.undoUpdateDescriptors(); } /* * (non-Javadoc) * * @see com.ibm.library.edit.process.command.BSDropCommand#doUndo() */ protected void doUndo() { // remove work product descriptors // activity.getBreakdownElements().removeAll(wpDescList); // remove role descriptors // activity.getBreakdownElements().removeAll(roleDescList); // remove task descriptors // activity.getBreakdownElements().removeAll(taskDescList); // remove work product descriptor from deliverable part // if (!wpdToDeliverableDescriptorMap.isEmpty()) { for (Iterator iter = wpdToDeliverableDescriptorMap.entrySet() .iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); WorkProductDescriptor deliverable = (WorkProductDescriptor) entry .getValue(); deliverable.getDeliverableParts().remove(entry.getKey()); } } // remove descriptors from activity's package // ProcessPackage pkg = (ProcessPackage) activity.eContainer(); if (pkg != null) { pkg.getProcessElements().removeAll(taskDescList); pkg.getProcessElements().removeAll(roleDescList); pkg.getProcessElements().removeAll(wpDescList); for (Iterator iter = wpDescToDeliverableParts.values().iterator(); iter .hasNext();) { pkg.getProcessElements().removeAll((Collection) iter.next()); } } // disassociate new work product descriptors with task descriptors // if(wpdToTaskFeaturesMap != null) { for (Iterator iter = wpdToTaskFeaturesMap.entrySet().iterator(); iter.hasNext();) { Map.Entry entry = (Map.Entry) iter.next(); Map taskFeatures = (Map) entry.getValue(); for (Iterator iterator = taskFeatures.entrySet().iterator(); iterator .hasNext();) { Map.Entry ent = (Map.Entry) iterator.next(); TaskDescriptor taskDesc = (TaskDescriptor) ProcessCommandUtil.getDescriptor(ent.getKey(), activity, getMethodConfiguration()); for (Iterator iterator1 = ((Collection)ent.getValue()).iterator(); iterator1 .hasNext();) { EStructuralFeature f = (EStructuralFeature) iterator1.next(); EStructuralFeature descFeature = (EStructuralFeature) FEATURE_MAP.get(f); if(descFeature.isMany()) { ((List)taskDesc.eGet(descFeature)).remove(entry.getKey()); } else { taskDesc.eSet(descFeature, null); } } } } } } /* * (non-Javadoc) * * @see org.eclipse.emf.common.command.AbstractCommand#getAffectedObjects() */ public Collection getAffectedObjects() { if (wpDescList != null) { return wpDescList; } return super.getAffectedObjects(); } /** * * @param task * @param activity * @param taskDescList * @param roleDescList * @param wpDescList * @param wpDescToDeliverableParts * @param descriptorsToRefresh * @return <code>true</code> if a new TaskDescriptor is created for the * given task, <code>false</code> otherwise */ static boolean addToDescriptorLists(Task task, Activity activity, List taskDescList, List roleDescList, List wpDescList, Map wpDescToDeliverableParts, Set descriptorsToRefresh, Map descriptorToNewFeatureValuesMap, MethodConfiguration config, boolean useExistingDescriptor, Set synchFeatures) { TaskDescriptor desc = ProcessCommandUtil.createTaskDescriptor(task, activity, roleDescList, wpDescList, wpDescToDeliverableParts, null, descriptorsToRefresh, descriptorToNewFeatureValuesMap, config, useExistingDescriptor, synchFeatures); if ((desc != null) && (taskDescList != null) && !taskDescList.contains(desc)) { taskDescList.add(desc); } return desc != null; } /* (non-Javadoc) * @see org.eclipse.epf.library.edit.process.command.BSDropCommand#dispose() */ public void dispose() { if(roleDescList != null) { roleDescList.clear(); } if(wpDescList != null) { wpDescList.clear(); } if(wpDescToDeliverableParts != null) { wpDescToDeliverableParts.clear(); } if(wpdToDeliverableDescriptorMap != null) { wpdToDeliverableDescriptorMap.clear(); } if(wpdToTaskFeaturesMap != null) { wpdToTaskFeaturesMap.clear(); } super.dispose(); } }