| //------------------------------------------------------------------------------ |
| // 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.util; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| 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.core.runtime.Assert; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.emf.common.command.BasicCommandStack; |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.common.command.CompoundCommand; |
| import org.eclipse.emf.common.command.UnexecutableCommand; |
| import org.eclipse.emf.common.notify.AdapterFactory; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.edit.command.CommandParameter; |
| import org.eclipse.emf.edit.command.CopyCommand; |
| 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.emf.edit.provider.AdapterFactoryTreeIterator; |
| import org.eclipse.emf.edit.provider.ITreeItemContentProvider; |
| import org.eclipse.epf.library.edit.IConfigurator; |
| import org.eclipse.epf.library.edit.TngAdapterFactory; |
| import org.eclipse.epf.library.edit.process.IBSItemProvider; |
| import org.eclipse.epf.library.edit.process.command.ActivityDeepCopyCommand; |
| import org.eclipse.epf.library.edit.process.command.CopyHelper; |
| import org.eclipse.epf.uma.Activity; |
| import org.eclipse.epf.uma.BreakdownElement; |
| import org.eclipse.epf.uma.Constraint; |
| import org.eclipse.epf.uma.Descriptor; |
| import org.eclipse.epf.uma.MethodConfiguration; |
| import org.eclipse.epf.uma.MethodElement; |
| import org.eclipse.epf.uma.Milestone; |
| import org.eclipse.epf.uma.Process; |
| import org.eclipse.epf.uma.ProcessComponent; |
| import org.eclipse.epf.uma.ProcessPackage; |
| import org.eclipse.epf.uma.TaskDescriptor; |
| import org.eclipse.epf.uma.UmaFactory; |
| import org.eclipse.epf.uma.VariabilityType; |
| import org.eclipse.epf.uma.WorkBreakdownElement; |
| import org.eclipse.epf.uma.edit.domain.TraceableAdapterFactoryEditingDomain; |
| import org.eclipse.epf.uma.util.Scope; |
| import org.eclipse.epf.uma.util.UmaUtil; |
| |
| /** |
| * Used to extend/copy activities |
| * |
| * @author Phong Nguyen Le |
| * @since 1.0 |
| */ |
| public class ActivityHandler { |
| |
| private ArrayList<ProcessPackage> procPackages; |
| |
| /** |
| * List of activities or activity wrappers to deep copy. |
| */ |
| private ArrayList<Object> activitiesToDeepCopy; |
| |
| private MethodConfiguration deepCopyConfig; |
| private List deepCopies; |
| private Map deepCopyToOriginalMap; |
| private ArrayList<Activity> activities; |
| |
| private Map copyToOriginal; |
| |
| private AdapterFactoryEditingDomain editingDomain; |
| |
| private Helper copyHelper; |
| |
| private CopyHelper deepCopyHelper; |
| |
| private Process targetProcess; |
| |
| private IProgressMonitor monitor; |
| |
| private IConfigurator activityDeepCopyConfigurator; |
| |
| private boolean copyExternalVariations = true; |
| |
| /** |
| * Constructs a new ActivityHandler |
| */ |
| public ActivityHandler() { |
| activities = new ArrayList(); |
| activitiesToDeepCopy = new ArrayList<Object>(); |
| deepCopies = new ArrayList(); |
| deepCopyToOriginalMap = new HashMap(); |
| copyToOriginal = new HashMap(); |
| procPackages = new ArrayList(); |
| copyHelper = new Helper(); |
| } |
| |
| public Map<Object, Object> cloneOrignaltoCopyMap() { |
| Map oMap = null; |
| if (deepCopyToOriginalMap != null && !deepCopyToOriginalMap.isEmpty()) { |
| oMap = getDeepCopyHelper().getObjectToCopyMap(); |
| } else if (editingDomain instanceof TraceableAdapterFactoryEditingDomain) { |
| TraceableAdapterFactoryEditingDomain td = (TraceableAdapterFactoryEditingDomain) editingDomain; |
| oMap = copy(td.getOriginalToClipboardMap()); |
| } |
| return oMap; |
| } |
| |
| public static Map copy(Map map) { |
| if (map == null) { |
| return null; |
| } |
| Map ret = new HashMap(); |
| for (Map.Entry entry: (Set<Map.Entry>) map.entrySet()) { |
| Object key = entry.getKey(); |
| Object val = entry.getValue(); |
| ret.put(key, val); |
| } |
| return ret; |
| } |
| |
| public void dispose() { |
| activities.clear(); |
| activitiesToDeepCopy.clear(); |
| copyToOriginal.clear(); |
| procPackages.clear(); |
| copyHelper.clear(); |
| deepCopies.clear(); |
| if(deepCopyHelper != null) { |
| deepCopyHelper.clear(); |
| } |
| deepCopyToOriginalMap.clear(); |
| } |
| |
| public void setCopyExternalVariations(boolean copyExternalVariations) { |
| this.copyExternalVariations = copyExternalVariations; |
| } |
| |
| public void copy(Activity activity) { |
| procPackages.add((ProcessPackage) activity.eContainer()); |
| } |
| |
| public MethodConfiguration getDeepCopyConfig() { |
| return deepCopyConfig; |
| } |
| |
| public void setDeepCopyConfig(MethodConfiguration deepCopyConfig) { |
| this.deepCopyConfig = deepCopyConfig; |
| } |
| |
| public Process getTargetProcess() { |
| return targetProcess; |
| } |
| |
| public void setTargetProcess(org.eclipse.epf.uma.Process proc) { |
| targetProcess = proc; |
| } |
| |
| public void setMonitor(IProgressMonitor monitor) { |
| this.monitor = monitor; |
| } |
| |
| public List getDeepCopies() { |
| return deepCopies; |
| } |
| |
| public void deepCopy(Object activityOrWrapper) { |
| Object unwrapped = TngUtil.unwrap(activityOrWrapper); |
| if(unwrapped instanceof Activity && ((Activity)unwrapped).eContainer() != null) { |
| activitiesToDeepCopy.add(activityOrWrapper); |
| } |
| } |
| |
| public void extend(Activity act) { |
| Activity extendedAct = ProcessUtil.generalize(act, |
| VariabilityType.EXTENDS); |
| activities.add(extendedAct); |
| } |
| |
| public List<Activity> getActivities() { |
| if (!procPackages.isEmpty() || !activitiesToDeepCopy.isEmpty()) { |
| editingDomain = new TraceableAdapterFactoryEditingDomain( |
| TngAdapterFactory.INSTANCE.getWBS_ComposedAdapterFactory(), |
| new BasicCommandStack()); |
| if(!procPackages.isEmpty()) { |
| activities.addAll(copy(procPackages)); |
| fixGuidReferences(copyHelper, false, false, null); |
| } |
| if(!activitiesToDeepCopy.isEmpty()) { |
| if (monitor == null) { |
| monitor = new NullProgressMonitor(); |
| } |
| for (Object act : activitiesToDeepCopy) { |
| ActivityDeepCopyCommand cmd = new ActivityDeepCopyCommand( |
| act, getDeepCopyHelper(), deepCopyConfig, targetProcess, monitor,activityDeepCopyConfigurator); |
| cmd.setCopyExternalVariations(copyExternalVariations); |
| try { |
| long time = 0; |
| if (TngUtil.DEBUG) { |
| time = System.currentTimeMillis(); |
| } |
| cmd.execute(); |
| if (TngUtil.DEBUG) { |
| System.out |
| .println("ActivityDeepCopyCommand executed: " //$NON-NLS-1$ |
| + (System.currentTimeMillis() - time) |
| + " ms"); //$NON-NLS-1$ |
| time = System.currentTimeMillis(); |
| } |
| Collection<?> result = cmd.getResult(); |
| if (!result.isEmpty()) { |
| Activity deepCopy = (Activity) result.iterator() |
| .next(); |
| ProcessUtil |
| .fixBreakdonwElementOrderRecursively(deepCopy); |
| if (TngUtil.DEBUG) { |
| System.out |
| .println("ProcessUtil.fixBreakdonwElementOrderRecursively(): " //$NON-NLS-1$ |
| + (System.currentTimeMillis() - time) |
| + " ms"); //$NON-NLS-1$ |
| time = System.currentTimeMillis(); |
| } |
| cmd.copySuppressionStates(); |
| if (TngUtil.DEBUG) { |
| System.out |
| .println("ActivityDeepCopyCommand.copySuppressionStates(): " //$NON-NLS-1$ |
| + (System.currentTimeMillis() - time) |
| + " ms"); //$NON-NLS-1$ |
| time = System.currentTimeMillis(); |
| } |
| cmd.fixReferences(); |
| deepCopies.add(deepCopy); |
| deepCopyToOriginalMap.put(deepCopy, act); |
| } |
| } finally { |
| cmd.dispose(); |
| } |
| fixGuidReferences(deepCopyHelper); |
| } |
| |
| activities.addAll(deepCopies); |
| } |
| } |
| |
| return activities; |
| } |
| |
| public static void fixGuidReferences(Map<? extends Object, ? extends Object> objectToCopyMap) { |
| fixGuidReferences(objectToCopyMap, true, false, null); |
| } |
| |
| public static void fixGuidReferences(Map<? extends Object, ? extends Object> objectToCopyMap, |
| boolean deepCopy, boolean reverseMap, Set<Resource> resouresToSave) { |
| Set<MethodElement> cpySet = new HashSet<MethodElement>(); |
| Map<String, String> srcGuidToCpyGuidMap = new HashMap<String, String>(); |
| |
| for (Map.Entry entry : objectToCopyMap.entrySet()) { |
| Object cpy = reverseMap ? entry.getKey() : entry.getValue(); |
| if (cpy instanceof Process) { |
| Process cpyProcess = (Process) cpy; |
| Scope scope = ProcessScopeUtil.getInstance().getScope(cpyProcess); |
| if (scope != null) { |
| cpyProcess.setDefaultContext(null); |
| cpyProcess.getValidContext().clear(); |
| } |
| } |
| } |
| |
| if (! ProcessUtil.isSynFree()) { |
| return; |
| } |
| for (Map.Entry entry : objectToCopyMap.entrySet()) { |
| // Object src = entry.getKey(); |
| // Object cpy = entry.getValue(); |
| Object src = reverseMap ? entry.getValue() : entry.getKey(); |
| Object cpy = reverseMap ? entry.getKey() : entry.getValue(); |
| // if (src instanceof Process || src instanceof ProcessComponent) { |
| // System.out.println("LD> src: " + src); |
| // System.out.println("LD> cpy: " + cpy); |
| // System.out.println(""); |
| // } |
| if (src == cpy) { |
| continue; |
| } |
| if (src instanceof Descriptor && cpy instanceof Descriptor) { |
| Descriptor srcDes = (Descriptor) src; |
| Descriptor cpyDes = (Descriptor) cpy; |
| srcGuidToCpyGuidMap.put(srcDes.getGuid(), cpyDes.getGuid()); |
| if (cpy instanceof TaskDescriptor) { |
| cpySet.add(cpyDes); |
| } |
| } else if (src instanceof Milestone && cpy instanceof Milestone) { |
| cpySet.add((Milestone) cpy); |
| } |
| } |
| |
| DescriptorPropUtil propUtil = DescriptorPropUtil.getDesciptorPropUtil(); |
| for (MethodElement cpy : cpySet) { |
| if (cpy instanceof TaskDescriptor) { |
| TaskDescriptor cpyDes = (TaskDescriptor) cpy; |
| propUtil.replaceLocalUseGuidStrings(cpyDes, srcGuidToCpyGuidMap); |
| String oldGreenParent = propUtil.getGreenParent(cpyDes); |
| if (oldGreenParent != null) { |
| String newGreenParent = srcGuidToCpyGuidMap.get(oldGreenParent); |
| if (newGreenParent != null && ! newGreenParent.equals(oldGreenParent)) { |
| if (deepCopy) { |
| propUtil.setGreenParent(cpyDes, null); |
| Activity parentAct = cpyDes.getSuperActivities(); |
| if (parentAct != null) { |
| for (BreakdownElement be : parentAct.getBreakdownElements()) { |
| if (be.getGuid().equals(newGreenParent)) { |
| parentAct.getBreakdownElements().remove(be); |
| break; |
| } |
| } |
| } |
| } else { |
| propUtil.setGreenParent(cpyDes, newGreenParent); |
| } |
| } |
| } |
| } |
| if (cpy instanceof TaskDescriptor || cpy instanceof Milestone) { |
| WorkBreakdownElement wbe = (WorkBreakdownElement) cpy; |
| for (Constraint c : ConstraintManager.getWpStates(wbe)) { |
| String oldWpdGuid = c.getBody(); |
| String newWpdGuid = srcGuidToCpyGuidMap.get(oldWpdGuid); |
| if (newWpdGuid != null && ! newWpdGuid.equals(oldWpdGuid)) { |
| c.setBody(newWpdGuid); |
| } |
| } |
| |
| if (resouresToSave != null) { |
| ProcessComponent proc = UmaUtil.getProcessComponent(wbe.getSuperActivities()); |
| if (proc != null && proc.eResource() != null) { |
| resouresToSave.add(proc.eResource()); |
| } |
| } |
| } |
| } |
| |
| } |
| |
| private void updatePredecessors(List workBreakdownElements) { |
| // get the predessor lists of original work breakdown elements |
| // |
| List predecessorLists = new ArrayList(); |
| Object original = copyToOriginal.get(workBreakdownElements.get(0)); |
| AdapterFactory adapterFactory = editingDomain.getAdapterFactory(); |
| IBSItemProvider bsItemProvider = (IBSItemProvider) adapterFactory.adapt(original, ITreeItemContentProvider.class); |
| int firstID = bsItemProvider.getId(); |
| predecessorLists.add(bsItemProvider.getPredecessors()); |
| // Item provider of last work breakdown element in the subtree whose root is original activity |
| IBSItemProvider lastWBIp = null; |
| for(Iterator iter = new AdapterFactoryTreeIterator(adapterFactory, original, false); iter.hasNext();) { |
| Object obj = iter.next(); |
| Object e = TngUtil.unwrap(obj); |
| if(e instanceof WorkBreakdownElement) { |
| IBSItemProvider bsIp = null; |
| if(obj instanceof IBSItemProvider) { |
| bsIp = ((IBSItemProvider)obj); |
| predecessorLists.add(bsIp.getPredecessors()); |
| } |
| else { |
| Object ip = adapterFactory.adapt(obj, ITreeItemContentProvider.class); |
| if(ip instanceof IBSItemProvider) { |
| bsIp = ((IBSItemProvider)ip); |
| predecessorLists.add(bsIp.getPredecessors()); |
| } |
| } |
| if(bsIp != null) { |
| lastWBIp = bsIp; |
| } |
| } |
| } |
| int lastID = lastWBIp != null ? lastWBIp.getId() : firstID; |
| |
| // update predecessors |
| // |
| int size = workBreakdownElements.size(); |
| Assert.isTrue(size == predecessorLists.size()); |
| for (int i = 0; i < size; i++) { |
| WorkBreakdownElement e = (WorkBreakdownElement) workBreakdownElements.get(i); |
| e.getLinkToPredecessor().clear(); |
| PredecessorList predList = (PredecessorList) predecessorLists.get(i); |
| for (Iterator iterator = predList.iterator(); iterator.hasNext();) { |
| bsItemProvider = (IBSItemProvider) iterator.next(); |
| int id = bsItemProvider.getId(); |
| if(id >= firstID && id <= lastID) { |
| WorkBreakdownElement pred = (WorkBreakdownElement) workBreakdownElements.get(id - firstID); |
| e.getLinkToPredecessor().add(UmaUtil.createDefaultWorkOrder(e, pred)); |
| } |
| else { |
| // predecessor is outside of the subtree, don't select it for now |
| } |
| } |
| } |
| } |
| |
| private Collection<?> copyProcessPackages(Collection<ProcessPackage> procPackages) { |
| Command command = createCopyCommand(editingDomain, procPackages); |
| if(command != null) { |
| try { |
| command.execute(); |
| return command.getResult(); |
| } finally { |
| command.dispose(); |
| } |
| } |
| return Collections.EMPTY_LIST; |
| } |
| |
| /** |
| * This creates a command that copies the given collection of objects. If the collection contains more than one object, |
| * then a compound command will be created containing individual copy commands for each object. |
| */ |
| private Command createCopyCommand(final EditingDomain domain, final Collection collection) |
| { |
| if (collection == null || collection.isEmpty()) |
| { |
| return UnexecutableCommand.INSTANCE; |
| } |
| |
| CompoundCommand copyCommand = new CompoundCommand(CompoundCommand.MERGE_COMMAND_ALL); |
| for (Iterator objects = collection.iterator(); objects.hasNext(); ) |
| { |
| copyCommand.append(domain.createCommand(CopyCommand.class, new CommandParameter(objects.next(), null, copyHelper))); |
| } |
| |
| return copyCommand.unwrap(); |
| } |
| |
| |
| /** |
| * Copies the given process packages |
| * |
| * @param editingDomain |
| * @param procPackages |
| * @return activities of the copies |
| */ |
| private List<Activity> copy(List<ProcessPackage> procPackages) { |
| Collection<?> copyPackages = copyProcessPackages(procPackages); |
| ArrayList<Activity> activities = new ArrayList<Activity>(); |
| for (Iterator<?> iter = copyPackages.iterator(); iter.hasNext();) { |
| ProcessPackage copy = (ProcessPackage) iter.next(); |
| if (copy instanceof ProcessComponent) { |
| Activity actCopy = ((ProcessComponent) copy) |
| .getProcess(); |
| // copy data from ProcessComponent to a new |
| // ProcessPackage |
| ProcessPackage pkgCopy = UmaFactory.eINSTANCE |
| .createProcessPackage(); |
| pkgCopy.setName(actCopy.getName()); |
| pkgCopy.getProcessElements().add(actCopy); |
| pkgCopy.getProcessElements().addAll( |
| copy.getProcessElements()); |
| pkgCopy.getDiagrams().addAll(copy.getDiagrams()); |
| pkgCopy.getChildPackages().addAll( |
| copy.getChildPackages()); |
| |
| activities.add(actCopy); |
| } else { |
| activities.add(ProcessUtil.findActivity(copy)); |
| } |
| } |
| return activities; |
| } |
| |
| public Map getDeepCopyToOriginalMap() { |
| return deepCopyToOriginalMap; |
| } |
| |
| public Helper getCopyHelper(){ |
| return copyHelper; |
| } |
| |
| public CopyHelper getDeepCopyHelper() { |
| if(deepCopyHelper == null) { |
| deepCopyHelper = new CopyHelper(); |
| } |
| return deepCopyHelper; |
| } |
| |
| public void setActivityDeepCopyConfigurator( |
| IConfigurator activityDeepCopyConfigurator) { |
| this.activityDeepCopyConfigurator = activityDeepCopyConfigurator; |
| } |
| |
| |
| } |