166438: Sync Wizard does not sync "replace" variability correctly for configurations that do not contain replacing elements
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/SynchronizeCommand.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/SynchronizeCommand.java
index a827523..75288a1 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/SynchronizeCommand.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/process/command/SynchronizeCommand.java
@@ -13,10 +13,12 @@
 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.ListIterator;
+import java.util.Map;
 import java.util.Set;
 
 import org.eclipse.emf.common.CommonPlugin;
@@ -25,29 +27,33 @@
 import org.eclipse.emf.common.command.CompoundCommand;
 import org.eclipse.emf.common.util.AbstractTreeIterator;
 import org.eclipse.emf.common.util.WrappedException;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.edit.command.RemoveCommand;
 import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.epf.library.edit.IConfigurator;
-import org.eclipse.epf.library.edit.LibraryEditPlugin;
 import org.eclipse.epf.library.edit.LibraryEditResources;
 import org.eclipse.epf.library.edit.Providers;
 import org.eclipse.epf.library.edit.TngAdapterFactory;
+import org.eclipse.epf.library.edit.command.BatchCommand;
 import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
 import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
 import org.eclipse.epf.library.edit.util.Messenger;
+import org.eclipse.epf.library.edit.util.ProcessUtil;
 import org.eclipse.epf.library.edit.util.TngUtil;
 import org.eclipse.epf.uma.Activity;
 import org.eclipse.epf.uma.BreakdownElement;
 import org.eclipse.epf.uma.Deliverable;
 import org.eclipse.epf.uma.Descriptor;
 import org.eclipse.epf.uma.MethodConfiguration;
+import org.eclipse.epf.uma.MethodElement;
 import org.eclipse.epf.uma.Process;
 import org.eclipse.epf.uma.Role;
 import org.eclipse.epf.uma.RoleDescriptor;
 import org.eclipse.epf.uma.Task;
 import org.eclipse.epf.uma.TaskDescriptor;
 import org.eclipse.epf.uma.TeamProfile;
+import org.eclipse.epf.uma.VariabilityElement;
 import org.eclipse.epf.uma.WorkProduct;
 import org.eclipse.epf.uma.WorkProductDescriptor;
 import org.eclipse.swt.custom.BusyIndicator;
@@ -88,6 +94,9 @@
 	private boolean showSuccessfulMsg = true;
 
 	private boolean intialized;
+	
+	private BatchCommand batchCommand = new BatchCommand(false);
+	private Map<VariabilityElement, VariabilityElement> replacerToBaseMap = new HashMap<VariabilityElement, VariabilityElement>();  
 
 //	private Object UIContext;
 
@@ -131,6 +140,8 @@
 	}
 	
 	private boolean doInitialize() {
+		commandList.clear();
+		
 		if (elements == null || elements.isEmpty()) {
 			return false;
 		}
@@ -146,7 +157,7 @@
 			}
 		}
 		elements.removeAll(deleteList);
-
+		
 		for (Iterator iter = elements.iterator(); iter.hasNext();) {
 			Object object = iter.next();
 			if (object instanceof Descriptor) {
@@ -169,12 +180,18 @@
 						if (object instanceof TaskDescriptor) {
 							Task task = ((TaskDescriptor) object).getTask();
 							if (task != null) {
+								if(replacerToBaseMap.containsKey(task)) {
+									task = (Task) replacerToBaseMap.get(task);
+								}
 								append(new WBSDropCommand(act, Collections
 										.singletonList(task), config, synchFeatures));
 							}
 						} else if (object instanceof RoleDescriptor) {
 							Role role = ((RoleDescriptor) object).getRole();
 							if (role != null) {
+								if(replacerToBaseMap.containsKey(role)) {
+									role = (Role) replacerToBaseMap.get(role);
+								}
 								append(new OBSDropCommand(act, Collections
 										.singletonList(role), config, synchFeatures, configurator));
 							}
@@ -182,6 +199,9 @@
 							WorkProduct wp = ((WorkProductDescriptor) object)
 							.getWorkProduct();
 							if (wp != null) {
+								if(replacerToBaseMap.containsKey(wp)) {
+									wp = (WorkProduct) replacerToBaseMap.get(wp);
+								}
 								append(new PBSDropCommand(act, Collections
 										.singletonList(wp), config, synchFeatures, configurator));
 							}
@@ -302,8 +322,11 @@
 	public Collection getModifiedResources() {
 		HashSet modifiedResources = new HashSet();
 		for (Iterator iter = commandList.iterator(); iter.hasNext();) {
-			IResourceAwareCommand cmd = (IResourceAwareCommand) iter.next();
-			modifiedResources.addAll(cmd.getModifiedResources());
+			
+			Object cmd = iter.next();
+			if(cmd instanceof IResourceAwareCommand) {
+				modifiedResources.addAll(((IResourceAwareCommand)cmd).getModifiedResources());
+			}
 		}
 		return modifiedResources;
 	}
@@ -327,7 +350,9 @@
 				deleteCommandList.add(cmd);
 			}
 		}
-
+		
+		batchCommand.execute();
+		
 		if (!aborted) {
 //			IRunnableWithProgress runnable = new IRunnableWithProgress() {
 //
@@ -461,7 +486,29 @@
 	private void addToDeleteList(Object element, List deleteList) {
 		if (element instanceof Descriptor) {
 			if (!getConfigurator().accept(element)) {
-				deleteList.add(element);
+				MethodElement linkedElement = ProcessUtil.getAssociatedElement((Descriptor) element);				
+				if(linkedElement instanceof VariabilityElement && TngUtil.isReplacer((VariabilityElement) linkedElement)) {
+					// if the linked element of the descriptor is a replacer, delete the descriptor in this synchronization
+					// only if the base of linked element is not in the configuration
+					//
+					VariabilityElement base = ((VariabilityElement)linkedElement).getVariabilityBasedOnElement();
+					while(base != null && TngUtil.isContributorOrReplacer(base)) {
+						base = base.getVariabilityBasedOnElement();
+					}
+					if(base != null) {
+						if(!getConfigurator().accept(base)) {
+							deleteList.add(element);
+						}
+						else {
+							batchCommand.addFeatureValue((EObject) element, 
+									ProcessUtil.getLinkReference((Descriptor) element), base);
+							replacerToBaseMap.put((VariabilityElement) linkedElement, base);
+						}
+					}
+				}
+				else {
+					deleteList.add(element);
+				}
 			}
 		} else if (element instanceof Activity) {
 			for (Iterator iter = ((Activity) element).getBreakdownElements()
@@ -517,6 +564,8 @@
 				}
 
 				superUndo();
+				
+				batchCommand.undo();
 			}
 
 		});
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/ProcessUtil.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/ProcessUtil.java
index b69d0cf..62f0f9d 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/ProcessUtil.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/ProcessUtil.java
@@ -31,6 +31,7 @@
 import org.eclipse.emf.ecore.EAttribute;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
 import org.eclipse.emf.edit.provider.IChangeNotifier;
@@ -982,6 +983,18 @@
 		}
 		return null;
 	}
+	
+	public static EReference getLinkReference(Descriptor descriptor) {
+		if (descriptor instanceof RoleDescriptor) {
+			return UmaPackage.eINSTANCE.getRoleDescriptor_Role();
+		} else if (descriptor instanceof TaskDescriptor) {
+			return UmaPackage.eINSTANCE.getTaskDescriptor_Task();
+		} else if (descriptor instanceof WorkProductDescriptor) {
+			return UmaPackage.eINSTANCE.getWorkProductDescriptor_WorkProduct();
+		}
+		return null;
+
+	}
 
 	public static void disposeWrappers(Collection children) {
 		if (children == null)
diff --git a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
index f6403d5..d8a4281 100755
--- a/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
+++ b/plugins/org.eclipse.epf.library.edit/src/org/eclipse/epf/library/edit/util/TngUtil.java
@@ -2050,6 +2050,11 @@
 		&& (e.getVariabilityType() == VariabilityType.CONTRIBUTES_LITERAL);
 	}
 	
+	public static boolean isReplacer(VariabilityElement e) {
+		return e.getVariabilityBasedOnElement() != null
+		&& (e.getVariabilityType() == VariabilityType.REPLACES_LITERAL);
+	}
+	
 	public static boolean isContributorOrReplacer(VariabilityElement e) {
 		VariabilityElement base = e.getVariabilityBasedOnElement();
 		VariabilityType type = e.getVariabilityType();