//------------------------------------------------------------------------------
// 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.emf.common.command.AbstractCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.AdapterFactoryTreeIterator;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.provider.WrapperItemProvider;
import org.eclipse.epf.library.edit.IConfigurator;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
import org.eclipse.epf.library.edit.process.BSActivityItemProvider;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.ComposedBreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.library.edit.process.command.RemoveUnusedDescriptorsCommand;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.Artifact;
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.Process;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.TaskDescriptor;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.UmaUtil;

import com.ibm.icu.util.StringTokenizer;

/**
 * This class calculates the suppression state, both direct and indirect, of any
 * breakdown element or its wrapper in the specified process.
 * 
 * @author Phong Nguyen Le - Aug 9, 2005
 * @since 1.0
 */
public class Suppression {

	public static final String WBS = "wbs"; //$NON-NLS-1$

	private static final String TBS = "tbs"; //$NON-NLS-1$

	private static final String WPBS = "wpbs"; //$NON-NLS-1$

	private static final String CBS = "cbs"; //$NON-NLS-1$

	private static final Map procToSuppressionMap = new HashMap();

	private static boolean autoInheritIntermediateSuppressionState = true;

	private Process process;

	private Set suppressedExternalElementPaths;

	private boolean modified;

	private Set internalUnsuppressedElements = new HashSet();

	public static final void clearCachedSuppressions() {
		procToSuppressionMap.clear();
	}

	/**
	 * Removes suppressions of invalid processes
	 */
	public static final void cleanUp() {
		ArrayList listToRemove = new ArrayList();
		for (Iterator iter = new ArrayList(procToSuppressionMap.keySet())
				.iterator(); iter.hasNext();) {
			Process proc = (Process) iter.next();
			if (proc.eIsProxy()) {
				listToRemove.add(proc);
			}
		}
		int size = listToRemove.size();
		for (int i = 0; i < size; i++) {
			procToSuppressionMap.remove(listToRemove.get(i));
		}
	}

	public static final void setAutoInheritSuppressionStates(boolean b) {
		autoInheritIntermediateSuppressionState = b;
	}

	public Suppression(Process process) {
		this.process = process;
		suppressedExternalElementPaths = loadSuppressedElementPaths();
	}

	public Process getProcess() {
		return process;
	}

	private Set loadSuppressedElementPaths() {
		Constraint rule = ConstraintManager.getConstraint(process,
				ConstraintManager.PROCESS_SUPPRESSION, false); // (Constraint)
		// process.getOwnedRules().get(0);
		if (rule != null && rule.getBody().length() > 0) {
			Set paths = new HashSet();
			for (StringTokenizer tokens = new StringTokenizer(rule.getBody()); tokens
					.hasMoreTokens();) {
				paths.add(tokens.nextToken());
			}
			return paths;
		}
		return null;
	}

	private Set getSuppressedExternalElementPaths() {
		if (suppressedExternalElementPaths == null) {
			suppressedExternalElementPaths = loadSuppressedElementPaths();
			if (suppressedExternalElementPaths == null) {
				suppressedExternalElementPaths = new HashSet();
			}
		}
		return suppressedExternalElementPaths;
	}

	/**
	 * @param process
	 * @param selection
	 * @return
	 */
	public boolean hasSuppressed(Collection selection) {
		for (Iterator iter = selection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof BreakdownElementWrapperItemProvider) {
				if (isSuppressed((BreakdownElementWrapperItemProvider) element)) {
					return true;
				}
			} else if (element instanceof BreakdownElement) {
				if (isSuppressed((BreakdownElement) element)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Checks if the given selection has any element that is not suppressed yet
	 * in this suppression's process
	 * 
	 * @param selection
	 * @return
	 */
	public boolean canSuppress(Collection selection) {
		return canDo(selection, true);
	}

	/**
	 * Checks if the given selection has any element that is suppressed in this
	 * suppression's process
	 * 
	 * @param selection
	 * @return
	 */
	public boolean canReveal(Collection selection) {
		return canDo(selection, false);
	}

	/**
	 * Extracts items from the given selection that can be suppressed/revealed
	 * (depending on the <code>suppressed</code> parameter)
	 * 
	 * @param selection
	 * @param suppressed
	 * @return
	 */
	private Collection getApplicableItems(Collection selection,
			boolean suppressed) {
		ArrayList applicableItems = new ArrayList();
		for (Iterator iter = selection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof BreakdownElementWrapperItemProvider) {
				BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) element;
				if (wrapper.isReadOnly()) {
					if (isInSuppressedList(wrapper) != suppressed) {
						applicableItems.add(element);
					}
				} else {
					Object e = TngUtil.unwrap(wrapper);
					if (e instanceof MethodElement
							&& ((MethodElement) e).getSuppressed()
									.booleanValue() != suppressed) {
						applicableItems.add(element);
					}
				}
			} else if (element instanceof MethodElement) {
				if (((MethodElement) element).getSuppressed().booleanValue() != suppressed) {
					applicableItems.add(element);
				}
			}
		}
		return applicableItems;
	}

	/**
	 * Checks if the given element is valid to suppress/reveal upon
	 * 
	 * @param element
	 * @return
	 */
	public static boolean isValid(Object element) {
		// don't show suppress/reveal for roledescriptor under team, work
		// product descriptor under deliverable work product,
		// and rolled-up item
		//
		BreakdownElement obj = null;
		if (element instanceof BreakdownElementWrapperItemProvider) {
			BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) element;
			if (wrapper.isRollupChild()) {
				return false;
			}
			obj = (BreakdownElement) TngUtil.unwrap(wrapper);
		} else if (element instanceof BreakdownElement)
			obj = (BreakdownElement) element;
		if (obj instanceof RoleDescriptor
				|| obj instanceof WorkProductDescriptor) {
			if (obj.getSuperActivities() == null
					|| obj.getSuperActivities() == null) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Checks if the given selection has any item that can be
	 * suppressed/revealed (depending on the <code>suppressed</code>
	 * parameter)
	 * 
	 * @param selection
	 * @param suppressed
	 * @return
	 */
	private boolean canDo(Collection selection, boolean suppressed) {
		for (Iterator iter = selection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (isValid(element)) {
				if (element instanceof BreakdownElementWrapperItemProvider) {
					BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) element;
					if (wrapper.isReadOnly()) {
						if (isInSuppressedList(wrapper) != suppressed) {
							return true;
						}
					} else {
						Object e = TngUtil.unwrap(wrapper);
						if (e instanceof MethodElement
								&& ((MethodElement) e).getSuppressed()
										.booleanValue() != suppressed) {
							return true;
						}
					}
				} else if (element instanceof MethodElement) {
					if (((MethodElement) element).getSuppressed()
							.booleanValue() != suppressed) {
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * A breakdown element is suppressed if itself or any of its parent activity
	 * is suppressed
	 * 
	 * @param e
	 * @return
	 */
	private boolean __isSuppressed(BreakdownElement e) {
		return getSuppressed(e, true, null) != null;
	}

	private static boolean isDirectlySuppressed(MethodElement e) {
		Boolean b = e.getSuppressed();
		if (b != null && b.booleanValue()) {
			return true;
		}
		if (e instanceof VariabilityElement) {
			VariabilityElement ve = (VariabilityElement) e;
			VariabilityType variabilityType = ve.getVariabilityType();
			if (variabilityType == VariabilityType.EXTENDS_LITERAL
					|| variabilityType == VariabilityType.CONTRIBUTES_LITERAL) {
				if (ve.getVariabilityBasedOnElement() != null) {
					return isDirectlySuppressed(ve
							.getVariabilityBasedOnElement());
				}
			}
		}

		return false;
	}

	/**
	 * Gets the suppressed breakdown element that made the given breakdown
	 * element become suppressed. This method will check the suppression state
	 * of the parent upto the specified <code>top</code> only if
	 * <code>checkParent</code> is <code>true</code>. It will not check the
	 * suppression state of <code>top</code>
	 * 
	 * @param e
	 * @return
	 */
	private static BreakdownElement getSuppressed(BreakdownElement e,
			boolean checkParent, Object top) {
		if (e.getSuppressed().booleanValue()) {
			return e;
		}

		if (checkParent) {
			for (BreakdownElement be = e; be != top
					&& be.getSuperActivities() != null;) {
				be = be.getSuperActivities();
				if (be.getSuppressed().booleanValue()) {
					return be;
				}
			}

			// special handling for nested artifact descriptors and deliverable
			// parts
			//
			if (e instanceof WorkProductDescriptor) {
				WorkProductDescriptor wpDesc = ((WorkProductDescriptor) e);
				WorkProduct wp = wpDesc.getWorkProduct();
				if (wp instanceof Artifact) {
					// look for parent artifact descriptor in the same activity
					// and check their suppression state
					//
					Activity act = UmaUtil.getParentActivity(e);
					if (act != null) {
						for (Iterator iter = act.getBreakdownElements()
								.iterator(); iter.hasNext();) {
							Object element = iter.next();
							if (element != e
									&& element instanceof WorkProductDescriptor) {
								WorkProductDescriptor wpd = ((WorkProductDescriptor) element);
								WorkProduct otherWp = wpd.getWorkProduct();
								if (otherWp instanceof Artifact
										&& UmaUtil.isContainedBy(wp, otherWp)
										&& wpd.getSuppressed().booleanValue()) {
									return wpd;
								}
							}
						}
					}
				}
				if (wpDesc != top && wpDesc.getSuperActivities() == null) {
					List list = AssociationHelper
							.getDeliverableDescriptors(wpDesc);
					if (list.size() == 1) {
						// this work product descriptor is a deliverable part of
						// a deliverable work product descriptor
						// check the suppression state of the deliverable work
						// product descriptor
						//
						return getSuppressed((BreakdownElement) list.get(0),
								checkParent, top);
					}
				}
			}
			// special handling for team profile own role descriptor
			//
			else if (e instanceof RoleDescriptor) {
				if (e.getSuperActivities() == null) {
					List list = AssociationHelper
							.getTeamProfiles((RoleDescriptor) e);
					if (list.size() == 1) {
						TeamProfile team = (TeamProfile) list.get(0);
						if (team != top && team != null) {
							return getSuppressed(team, checkParent, top);
						}
					}
				}
			}
			// special handling for sub team profile
			//
			else if (e instanceof TeamProfile) {
				if (e.getSuperActivities() == null) {
					TeamProfile superTeam = ((TeamProfile) e).getSuperTeam();
					if (superTeam != top && superTeam != null) {
						return getSuppressed(superTeam, checkParent, top);
					}
				}
			}
		}

		return null;
	}

	public boolean isInSuppressedList(
			BreakdownElementWrapperItemProvider wrapper) {
		if (suppressedExternalElementPaths == null) {
			return false;
		}

		// check if wrapper's path is in suppressedExternalElementPaths set
		//
		String path = getPath(wrapper);
		return suppressedExternalElementPaths.contains(path);
	}

	/**
	 * Gets the suppressed breakdown element that made the given wrapper become
	 * suppressed
	 * 
	 * @param wrapper
	 * @return
	 */
	private BreakdownElement getSuppressed(
			BreakdownElementWrapperItemProvider wrapper) {
		return getSuppressed(wrapper, true);
	}

	/**
	 * Gets the suppressed breakdown element that made the given wrapper become
	 * suppressed
	 * 
	 * @param wrapper
	 * @return
	 */
	private BreakdownElement getSuppressed(
			BreakdownElementWrapperItemProvider wrapper, boolean checkBase) {
		return getSuppressed(wrapper, checkBase, true,
				autoInheritIntermediateSuppressionState);
	}

	/**
	 * Gets the suppressed breakdown element that made the given wrapper become
	 * suppressed
	 * 
	 * @param wrapper
	 * @return
	 */
	private BreakdownElement getSuppressed(
			BreakdownElementWrapperItemProvider wrapper, boolean checkBase,
			boolean checkLocal, boolean inheritSuppressionState) {
		return getSuppressed(wrapper, checkBase, checkLocal,
				inheritSuppressionState, true, null);
	}

	private BreakdownElement getSuppressed(
			BreakdownElementWrapperItemProvider wrapper, boolean checkBase,
			boolean checkLocal, boolean inheritSuppressionState,
			boolean checkParent, Object top) {
		BreakdownElement e = (BreakdownElement) TngUtil.unwrap(wrapper);
		if (!wrapper.isReadOnly()) {
			// this is a wrapper of local element
			//
			return getSuppressed(e, checkParent, top);
		}

		// check if the base breakdown element is suppressed, directly or
		// indirectly, in its own process
		//
		if (checkBase) {
			BreakdownElement suppressed = getSuppressed(e, checkParent, top);
			if (suppressed != null) {
				return suppressed;
			}
		}

		Object parent = null;
		if (checkLocal) {
			// check if the wrapper is suppressed in this process
			//
			if (isInSuppressedList(wrapper)) {
				return e;
			}

			// check if the any local parent is suppressed
			//
			if (checkParent) {
				parent = wrapper.getParent(wrapper);
				if (parent instanceof BreakdownElement && parent != top) {
					BreakdownElement suppressed = getSuppressed(
							(BreakdownElement) parent, checkParent, top);
					if (suppressed != null) {
						return suppressed;
					}
				}
			}
		}

		// check if the breakdown element is suppressed in one of the immediate
		// base process
		//
		if (inheritSuppressionState) {
			Process proc = TngUtil.getOwningProcess(e);
			Activity inheritor = ProcessUtil.getInheritor(wrapper);
			BreakdownElement base = (BreakdownElement) inheritor
					.getVariabilityBasedOnElement();
			if (base != null) {
				Process immediateBaseProc = TngUtil.getOwningProcess(base);
				if (proc != immediateBaseProc) {
					// find the object in the breakdown structure of the
					// immediate
					// base process that represents the same breakdown element
					//
					Object object = inheritor.getVariabilityBasedOnElement();
					ArrayList objects = new ArrayList(ProcessUtil
							.getParentList(inheritor, wrapper));
					objects.add(e);
					for (Iterator iter = objects.iterator(); iter.hasNext();) {
						Object element = iter.next();
						ITreeItemContentProvider adapter = (ITreeItemContentProvider) wrapper
								.getAdapterFactory().adapt(object,
										ITreeItemContentProvider.class);
						find_child: for (Iterator iterator = adapter
								.getChildren(object).iterator(); iterator
								.hasNext();) {
							Object child = iterator.next();
							if (element == TngUtil.unwrap(child)) {
								object = child;
								break find_child;
							}
						}
					}
					if (object instanceof BreakdownElementWrapperItemProvider) {
						Suppression suppression = getSuppression(immediateBaseProc);
						BreakdownElement element = suppression.getSuppressed(
								(BreakdownElementWrapperItemProvider) object,
								false, true, inheritSuppressionState,
								checkParent, TngUtil.unwrap(object));
						if (element != null) {
							return element;
						}
					}
				}
			}
		}

		// check if the any inherited parent is suppressed
		//
		if (checkParent) {
			if (parent == null) {
				parent = wrapper.getParent(wrapper);
			}
			if (parent instanceof BreakdownElementWrapperItemProvider
					&& TngUtil.unwrap(parent) != top) {
				return getSuppressed(
						(BreakdownElementWrapperItemProvider) parent,
						checkBase, true, inheritSuppressionState, checkParent,
						top);
			}
		}

		return null;
	}

	/**
	 * Gets the cached suppression for the given process if one exists or
	 * creates new one
	 * 
	 * @param immediateBaseProc
	 * @return
	 */
	public static Suppression getSuppression(Process proc) {
		Suppression suppression = (Suppression) procToSuppressionMap.get(proc);
		if (suppression == null) {
			synchronized (procToSuppressionMap) {
				suppression = (Suppression) procToSuppressionMap.get(proc);
				if (suppression == null) {
					suppression = new Suppression(proc);
					procToSuppressionMap.put(proc, suppression);
				}
			}
		}
		return suppression;
	}

	private boolean __isSuppressed(BreakdownElementWrapperItemProvider wrapper) {
		return getSuppressed(wrapper) != null;
	}

	public void saveToModel() {
		if (suppressedExternalElementPaths == null) {
			return;
		}

		StringBuffer paths = new StringBuffer();
		for (Iterator iter = suppressedExternalElementPaths.iterator(); iter
				.hasNext();) {
			String path = (String) iter.next();
			if (isValid(path)) {
				paths.append(path).append(' ');
			}
		}

		Constraint rule = ConstraintManager.getConstraint(process,
				ConstraintManager.PROCESS_SUPPRESSION, true);
		// if(process.getOwnedRules().isEmpty()) {
		// rule = UmaFactory.eINSTANCE.createConstraint();
		// process.getOwnedRules().add(rule);
		// }
		// else {
		// rule = (Constraint) process.getOwnedRules().get(0);
		// }
		//		
		rule.setBody(paths.toString());
	}

	/**
	 * Checks if the given path is valid in process
	 * 
	 * @param path
	 * @return
	 */
	private boolean isValid(String path) {
		URI uri = URI.createURI(path);
		String type = uri.scheme();
		ConfigurableComposedAdapterFactory adapterFactory = null;
		if (WBS.equals(type)) {
			adapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
					.getWBS_ComposedAdapterFactory();
		} else if (TBS.equals(type)) {
			adapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
					.getOBS_ComposedAdapterFactory();
		} else if (WPBS.equals(type)) {
			adapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
					.getPBS_ComposedAdapterFactory();
		} else if (CBS.equals(type)) {
			adapterFactory = (ConfigurableComposedAdapterFactory) TngAdapterFactory.INSTANCE
					.getProcessComposedAdapterFactory();
		} else {
			return false;
		}

		// use process's default configuration to validate
		//
		MethodConfiguration currentConfig = null;
		IConfigurator configurator = null;
		IFilter filter = adapterFactory.getFilter();
		if (filter instanceof IConfigurator) {
			configurator = (IConfigurator) adapterFactory.getFilter();
			currentConfig = configurator.getMethodConfiguration();
			configurator.setMethodConfiguration(process.getDefaultContext());
		}
		try {
			String guid = uri.authority();
			if (!process.getGuid().equals(guid)) {
				return false;
			}
			Object object = process;
			ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
					.adapt(object, ITreeItemContentProvider.class);
			for (int i = 0; i < uri.segmentCount(); i++) {
				guid = uri.segment(i);
				Iterator iter = adapter.getChildren(object).iterator();
				adapter = null;
				find_adapter: while (iter.hasNext()) {
					Object child = iter.next();
					object = TngUtil.unwrap(child);
					if (object instanceof MethodElement) {
						if (guid.equals(((MethodElement) object).getGuid())) {
							if (child instanceof ITreeItemContentProvider) {
								adapter = (ITreeItemContentProvider) child;
							} else {
								adapter = (ITreeItemContentProvider) adapterFactory
										.adapt(child,
												ITreeItemContentProvider.class);
							}
							break find_adapter;
						}
					} else {
						// must be an ItemProviderAdapter
						//
						ItemProviderAdapter itemProvider = (ItemProviderAdapter) object;
						MethodElement e = (MethodElement) itemProvider
								.getTarget();
						if (guid.equals(e.getGuid())) {
							adapter = (ITreeItemContentProvider) itemProvider;
							break find_adapter;
						}
					}
				}
				if (adapter == null) {
					return false;
				}
			}
			return true;
		} finally {
			// restore configuration
			//
			if (configurator != null) {
				configurator.setMethodConfiguration(currentConfig);
			}
		}
	}

	// private boolean reveal(List selection, Collection revealedDescriptors) {
	// boolean readOnlyElementAffected = false;
	// for (Iterator iter = selection.iterator(); iter.hasNext();) {
	// Object element = (Object) iter.next();
	// if (element instanceof BreakdownElementWrapperItemProvider) {
	// BreakdownElementWrapperItemProvider wrapper =
	// (BreakdownElementWrapperItemProvider) element;
	// MethodElement e = (MethodElement) TngUtil.unwrap(wrapper);
	// if (!wrapper.isReadOnly()) { // wrapper of local element
	// e.setSuppressed(Boolean.FALSE);
	// if(e instanceof Descriptor) {
	// revealedDescriptors.add(e);
	// }
	// } else { // was suppressed by this process
	//
	// // remove the path of suppressed element from the list
	// //
	// String path = getPath(wrapper);
	// getSuppressedExternalElementPaths().remove(path);
	// readOnlyElementAffected = true;
	// }
	// } else if (element instanceof MethodElement) {
	// ((MethodElement) element).setSuppressed(Boolean.FALSE);
	// if(element instanceof Descriptor) {
	// revealedDescriptors.add(element);
	// }
	// }
	// }
	// modified = true;
	// return readOnlyElementAffected;
	// }

	// /**
	// * @param selection
	// * @return true if this call revealed any read-only element
	// */
	// public boolean reveal(List selection) {
	// ArrayList revealedDescriptors = new ArrayList();
	// boolean ret = reveal(selection, revealedDescriptors);
	// List descriptorsToReveal = getOwnRelatedElements(revealedDescriptors,
	// false);
	// if(descriptorsToReveal != null) {
	// boolean ret2 = reveal(descriptorsToReveal, revealedDescriptors);
	// return ret || ret2;
	// }
	// return ret;
	// }

	/**
	 * @deprecated need to use {@link SuppressionCommand} instead
	 */
	public void reveal(List selection) {
		doSetSuppressed(selection, false);
	}

	private static String getViewType(
			BreakdownElementWrapperItemProvider wrapper) {
		// no need to store separate path for CBS, reuse WBS/TBS/WPBS paths
		//		
		Object e = TngUtil.unwrap(wrapper);
		if (e instanceof WorkBreakdownElement) {
			return WBS;
		} else if (e instanceof TeamProfile || e instanceof RoleDescriptor) {
			return TBS;
		} else if (e instanceof WorkProductDescriptor) {
			return WPBS;
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	/**
	 * Gets the process GUID in the given GUID path
	 * 
	 * @param guidPath
	 * @return
	 * @see #getPath(BreakdownElementWrapperItemProvider)
	 */
	public static String getProcessGUID(String guidPath) {
		int id = guidPath.indexOf("://"); //$NON-NLS-1$
		if (id != -1) {
			int beginIndex = id + 3;
			if (beginIndex < guidPath.length()) {
				int endIndex = guidPath.indexOf('/', beginIndex);
				if (endIndex != -1) {
					return guidPath.substring(beginIndex, endIndex);
				}
			}
		}
		return null;
	}

	/**
	 * @param wrapper
	 * @return
	 */
	public static String getPath(BreakdownElementWrapperItemProvider wrapper) {
		StringBuffer path = new StringBuffer(); //$NON-NLS-1$
		List parentList = ProcessUtil.getParentList(null, wrapper);
		if (!parentList.isEmpty()) {
			for (Iterator iter = parentList.iterator(); iter.hasNext();) {
				MethodElement e = (MethodElement) iter.next();
				// exclude TaskDescriptor and RoleDescriptor from the parent
				// path b/c those descriptors can be
				// parent only in CBS view
				if (!(e instanceof TaskDescriptor || e instanceof RoleDescriptor)) {
					path.append('/').append(e.getGuid());
				}
			}
		}
		MethodElement e = (MethodElement) TngUtil.unwrap(wrapper);
		path.append('/').append(e.getGuid());
		String viewType = getViewType(wrapper);
		path.insert(0, ":/").insert(0, viewType); //$NON-NLS-1$
		return path.toString();
	}

	private static List getOwnRelatedElements(Collection changedDescriptors,
			boolean suppressed) {
		if (!changedDescriptors.isEmpty()) {
			ArrayList descriptorsToChange = new ArrayList();
			for (Iterator iter = new ArrayList(changedDescriptors).iterator(); iter
					.hasNext();) {
				Descriptor desc = (Descriptor) iter.next();
				Object[] relationships = null;
				if (desc instanceof TaskDescriptor) {
					relationships = RemoveUnusedDescriptorsCommand.TASK_DESCRIPTOR__RELATIONSHIPS;
				} else if (desc instanceof RoleDescriptor) {
					relationships = RemoveUnusedDescriptorsCommand.ROLE_DESCRIPTOR__RELATIONSHIPS;
				} else if (desc instanceof WorkProductDescriptor) {
					relationships = RemoveUnusedDescriptorsCommand.WORK_PRODUCT_DESCRIPTOR__RELATIONSHIPS;
				}
				if (relationships != null) {
					for (int i = 0; i < relationships.length; i++) {
						Object feature = relationships[i];
						boolean isMany;
						Object value;
						if (feature instanceof OppositeFeature) {
							OppositeFeature f = (OppositeFeature) feature;
							isMany = f.isMany();
							value = ((MultiResourceEObject) desc)
									.getOppositeFeatureValue(f);
						} else {
							EStructuralFeature f = (EStructuralFeature) feature;
							isMany = f.isMany();
							value = desc.eGet(f);
						}
						if (isMany) {
							for (Iterator iterator = ((Collection) value)
									.iterator(); iterator.hasNext();) {
								Descriptor ref = (Descriptor) iterator.next();
								if (ref.getSuppressed().booleanValue() != suppressed
										&& !ProcessUtil
												.checkDescriptorReferences(
														changedDescriptors, ref)) {
									descriptorsToChange.add(ref);
									changedDescriptors.add(ref);
								}
							}
						} else {
							Descriptor ref = (Descriptor) value;
							if (ref != null) {
								if (ref.getSuppressed().booleanValue() != suppressed
										&& !ProcessUtil.checkDescriptorReferences(
												changedDescriptors, ref)) {
									descriptorsToChange.add(ref);
									changedDescriptors.add(ref);
								}
							}
						}
					}
				}
			}
			return descriptorsToChange;
		}
		return null;
	}

	/**
	 * Suppresses or reveals the given selection
	 * 
	 * @param selection
	 * @param suppressed
	 * @return {@link Result} object that contains the result of this call
	 */
	private Result setSuppressed(List selection, boolean suppressed) {
		Result result = doSetSuppressed(selection, suppressed);

		// if descriptors had been suppressed, related elements that are not
		// used anywhere else also need to be suppressed (just like delete)
		//	
		if (!result.descriptors.isEmpty()) {
			List descriptorsToSuppress = getOwnRelatedElements(
					result.descriptors, suppressed);
			if (descriptorsToSuppress != null) {
				Result result2 = doSetSuppressed(descriptorsToSuppress,
						suppressed);

				// merge results
				//
				result.elements.addAll(result2.elements);
				result.descriptors.addAll(result2.descriptors);
				result.paths.addAll(result2.paths);
			}
		}

		return result;
	}

	/**
	 * @deprecated need to use {@link SuppressionCommand} instead
	 */
	public void suppress(List selection) {
		doSetSuppressed(selection, true);
	}

	// public boolean suppress(List selection) {
	// ArrayList suppressedDescriptors = new ArrayList();
	// boolean ret = suppress(selection, suppressedDescriptors);
	//		
	// // if descriptors had been suppressed, related elements that are not used
	// anywhere else also need to be suppressed (just like delete)
	// //
	// List descriptorsToSuppress = getOwnRelatedElements(suppressedDescriptors,
	// true);
	// if(descriptorsToSuppress != null) {
	// ArrayList out = new ArrayList();
	// boolean ret2 = suppress(descriptorsToSuppress, out);
	// if(out.size() != descriptorsToSuppress.size()) {
	// LibraryEditPlugin.getDefault().getLogger().logError("Suppression.suppress(List)
	// is buggy."); //$NON-NLS-1$
	// }
	// return ret || ret2;
	// }
	// return ret;
	// }

	private static class Result {
		/** Elements that have been suppressed or revealed */
		Collection elements;

		/** Descriptors that have been suppressed or revealed */
		Collection descriptors;

		/**
		 * Paths that have been added to or removed from
		 * <code>suppressedExternalElementPaths</code>
		 */
		Collection paths;

		Result() {
			elements = new ArrayList();
			descriptors = new ArrayList();
			paths = new ArrayList();
		}

		boolean isEmpty() {
			return elements.isEmpty() && paths.isEmpty();
		}

		void clear() {
			elements.clear();
			descriptors.clear();
			paths.clear();
		}
	}

	/**
	 * Suppresses or reveals the given selection depending on the value of
	 * <code>suppressed</code>
	 * 
	 * @param selection
	 * @param suppressed
	 * @return
	 */
	private Result doSetSuppressed(List selection, boolean suppressed) {
		Result result = new Result();
		for (Iterator iter = selection.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if (element instanceof BreakdownElementWrapperItemProvider) {
				BreakdownElementWrapperItemProvider wrapper = (BreakdownElementWrapperItemProvider) element;
				// if (!isSuppressed(wrapper)) {
				BreakdownElement e = (BreakdownElement) TngUtil.unwrap(wrapper);
				if (!wrapper.isReadOnly()) {
					// wrapper of local element
					//
					if (e.getSuppressed().booleanValue() != suppressed) {
						e.setSuppressed(Boolean.valueOf(suppressed));
						result.elements.add(e);
						if (e instanceof Descriptor) {
							result.descriptors.add(e);
						}
					}
				} else {
					// add the paths of suppressed element to the map
					//
					String path = getPath(wrapper);
					boolean b;
					if (suppressed) {
						b = getSuppressedExternalElementPaths().add(path);
					} else {
						b = getSuppressedExternalElementPaths().remove(path);
					}
					if (b) {
						result.paths.add(path);
					}
					// }
				}
			} else if (element instanceof MethodElement) {
				MethodElement e = ((MethodElement) element);
				if (e.getSuppressed().booleanValue() != suppressed) {
					e.setSuppressed(Boolean.valueOf(suppressed));
					result.elements.add(e);
					if (e instanceof Descriptor) {
						result.descriptors.add(e);
					}
				}
			}
		}
		modified = !result.isEmpty();
		return result;
	}

	// private boolean suppress(List selection, Collection
	// suppressedDescriptors) {
	// boolean readOnlyElementSuppressed = false;
	// for (Iterator iter = selection.iterator(); iter.hasNext();) {
	// Object element = (Object) iter.next();
	// if (element instanceof BreakdownElementWrapperItemProvider) {
	// BreakdownElementWrapperItemProvider wrapper =
	// (BreakdownElementWrapperItemProvider) element;
	// if (!isSuppressed(wrapper)) {
	// BreakdownElement e = (BreakdownElement) TngUtil
	// .unwrap(wrapper);
	// if (!wrapper.isReadOnly()) {
	// // wrapper of local element
	// //
	// e.setSuppressed(Boolean.TRUE);
	// if(e instanceof Descriptor) {
	// suppressedDescriptors.add(e);
	// }
	// } else {
	// // add the paths of suppressed element to the map
	// //
	// String path = getPath(wrapper);
	// getSuppressedExternalElementPaths().add(path);
	// readOnlyElementSuppressed = true;
	// }
	// }
	// } else if (element instanceof MethodElement) {
	// ((MethodElement) element).setSuppressed(Boolean.TRUE);
	// if(element instanceof Descriptor) {
	// suppressedDescriptors.add(element);
	// }
	// }
	// }
	// modified = true;
	// return readOnlyElementSuppressed;
	// }

	/**
	 * @param selection
	 * @return
	 */
	public boolean hasUnsuppressed(List selection) {
		for (Iterator iter = selection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof BreakdownElementWrapperItemProvider) {
				if (!isSuppressed((BreakdownElementWrapperItemProvider) element)) {
					return true;
				}
			} else if (element instanceof BreakdownElement) {
				if (!isSuppressed((BreakdownElement) element)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * @return Returns the modified.
	 */
	public boolean isSaveNeeded() {
		return modified;
	}

	public void saveIsDone() {
		modified = false;
	}
	
	private boolean __isSuppressed(ComposedBreakdownElementWrapperItemProvider composedWrapper) {
		for (Iterator iter = composedWrapper.getValues().iterator(); iter.hasNext();) {
			Object element = iter.next();
			if(!isSuppressed(element)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * check if the element, or the item provider or adaptor associated with the
	 * element is suppressed.
	 * 
	 * @param e
	 *            MethodElement or an associated wrapper, adaptor, or item
	 *            provider, etc.
	 * @return boolean
	 */
	public boolean isSuppressed(Object e) {
		// long start = System.currentTimeMillis();

		try {

			if (e == null) {
				return true;
			}
			
			ComposedBreakdownElementWrapperItemProvider composedWrapper = ProcessUtil.getComposedWrapper(e);
			if(composedWrapper != null) {
				return __isSuppressed(composedWrapper);
			}

			if (internalUnsuppressedElements.contains(e)) {
				return false;
			}

			if (e instanceof BreakdownElementWrapperItemProvider) {
				return __isSuppressed((BreakdownElementWrapperItemProvider) e);
			} else if (e instanceof BreakdownElement) {
				return __isSuppressed((BreakdownElement) e);
			} else {
				Object targetObj = null;
				if (e instanceof WrapperItemProvider) {
					targetObj = ((WrapperItemProvider) e).getValue();
				} else if (e instanceof ItemProviderAdapter) {
					targetObj = ((ItemProviderAdapter) e).getTarget();
				}

				if (targetObj != null && targetObj != e) {
					return isSuppressed(targetObj);
				}
			}

			return false;

		} finally {
			// long time = (System.currentTimeMillis() - start);
			// if(time > 1000) {
			// BreakdownElement be = (BreakdownElement)TngUtil.unwrap(e);
			// String msg = "Suppression.isSuppressed(): time taken (ms) " +
			// time +
			// "\n process: " + (e instanceof
			// BreakdownElementWrapperItemProvider ?
			// ((BreakdownElementWrapperItemProvider)e).getTopItem() :
			// TngUtil.getOwningProcess(be)) +
			// "\n element: " + ProcessUtil.getLabelWithPath(be);
			//				
			// System.out.println(msg);
			// LibraryEditPlugin.getDefault().getLogger().logInfo(msg);
			// }
		}
	}

	/**
	 * Updates the suppression state of the given <code>wrapper</code> from
	 * its base.
	 * 
	 * @param wrapper
	 * @return <code>true</code> if this call modified the suppression state
	 *         of the given wrapper, <code>false</code> otherwise
	 */
	public boolean updateSuppressionFromBase(
			BreakdownElementWrapperItemProvider wrapper) {
		String path = getPath(wrapper);
		boolean ret;
		BreakdownElement e = getSuppressed(wrapper, true, false, true, false,
				null);
		if (e != null) {
			ret = getSuppressedExternalElementPaths().add(path);
		} else {
			ret = getSuppressedExternalElementPaths().remove(path);
		}
		if (ret) {
			modified = true;
		}
		return ret;
	}

	/**
	 * Excludes the descriptors with the same linked element from the check
	 * 
	 * @param selectionToReveal
	 * @return
	 */
	public String checkDuplicateNameAfterReveal(
			Collection selectionToRevealOrSuppress,
			AdapterFactory adapterFactory) {
		Collection elementsToReveal = getApplicableItems(
				selectionToRevealOrSuppress, false);
		for (Iterator iter = elementsToReveal.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof BreakdownElement) {
				BreakdownElement be = (BreakdownElement) element;
				String msg = ProcessUtil.checkBreakdownElementName(
						adapterFactory, be, be.getName(), this);
				if (msg != null) {
					return LibraryEditResources.Suppression_nameDuplication; //$NON-NLS-1$
				}
				msg = ProcessUtil.checkBreakdownElementPresentationName(
						adapterFactory, be, be.getPresentationName(), this);
				if (msg != null) {
					return LibraryEditResources.Suppression_presentationNameDuplication; //$NON-NLS-1$
				}
			} else {
				Object unwrapped = TngUtil.unwrap(element);
				if (unwrapped instanceof BreakdownElement) {
					ITreeItemContentProvider itemProvider = (ITreeItemContentProvider) adapterFactory
							.adapt(element, ITreeItemContentProvider.class);
					Object parent = itemProvider.getParent(element);
					if (parent instanceof BreakdownElement) {
						itemProvider = (ITreeItemContentProvider) adapterFactory
								.adapt(parent, ITreeItemContentProvider.class);
						Collection siblings = itemProvider.getChildren(parent);
						Object linkedElement = null;
						if (element instanceof Descriptor) {
							linkedElement = ProcessUtil
									.getAssociatedElement((Descriptor) element);
						}
						try {
							internalUnsuppressedElements.add(element);
							nameCheckLoop: for (Iterator iterator = siblings
									.iterator(); iterator.hasNext();) {
								Object sibling = iterator.next();
								if (sibling instanceof BreakdownElement) {
									BreakdownElement be = (BreakdownElement) sibling;
									// skip checking on suppressed element
									//
									if (be.getSuppressed().booleanValue()) {
										continue nameCheckLoop;
									}
									if (linkedElement != null
											&& sibling instanceof Descriptor) {
										// skip checking on descriptors with the
										// same linked element
										//
										Object otherLinkedElement = ProcessUtil
												.getAssociatedElement((Descriptor) element);
										if (otherLinkedElement == linkedElement) {
											continue nameCheckLoop;
										}
									}
									String msg = ProcessUtil
											.checkBreakdownElementName(
													adapterFactory, be, be
															.getName(), this);
									if (msg != null) {
										return LibraryEditResources.Suppression_nameDuplication; //$NON-NLS-1$
									}
									msg = ProcessUtil
											.checkBreakdownElementPresentationName(
													adapterFactory, be,
													be.getPresentationName(),
													this);
									if (msg != null) {
										return LibraryEditResources.Suppression_presentationNameDuplication; //$NON-NLS-1$
									}
								}
							}
						} finally {
							internalUnsuppressedElements.remove(element);
						}
					}
				}
			}
		}
		return null;
	}

	public Object getObjectByPath(String[] guidPath,
			AdapterFactory adapterFactory) {
		if (guidPath.length == 0 || adapterFactory == null
				|| !guidPath[0].equals(process.getGuid())) {
			return null;
		}

		Object object = process;
		int len = guidPath.length;
		for (int i = 1; i < len; i++) {
			ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
					.adapt(object, ITreeItemContentProvider.class);
			boolean found = false;

			// if current object is an activity, make sure it is rolled down
			// before looking into its children
			//
			IBSItemProvider rolledUpAdapter = null;
			Iterator iter = null;
			try {
				if (TngUtil.unwrap(object) instanceof Activity) {
					if (adapter instanceof BSActivityItemProvider) {
						BSActivityItemProvider activityItemProvider = (BSActivityItemProvider) adapter;
						if (activityItemProvider.isRolledUp()) {
							activityItemProvider.basicSetRolledUp(false);
							rolledUpAdapter = activityItemProvider;
						}
					} else if (adapter instanceof IBSItemProvider) {
						IBSItemProvider itemProvider = (IBSItemProvider) adapter;
						if (itemProvider.isRolledUp()) {
							itemProvider.setRolledUp(false);
							rolledUpAdapter = itemProvider;
						}
					}
				}
				iter = adapter.getChildren(object).iterator();
			} finally {
				if (rolledUpAdapter != null) {
					rolledUpAdapter.setRolledUp(true);
				}
			}

			find_child: while (iter.hasNext()) {
				Object child = iter.next();
				Object e = TngUtil.unwrap(child);
				if (e instanceof MethodElement
						&& ((MethodElement) e).getGuid().equals(guidPath[i])) {
					found = true;
					object = child;
					break find_child;
				}
			}

			if (!found) {
				return null;
			}
		}
		return object;
	}

	/**
	 * Checks if the breakdown element identified by the given
	 * <code>guidPath</code> is suppressed in the process of this Suppression
	 * object
	 * 
	 * @param guidPath
	 * @return
	 * @exception IllegalArgumentException
	 *                if the object with the given path could not be found using
	 *                the given adapter factory
	 */
	public boolean isSuppressed(String[] guidPath, AdapterFactory adapterFactory)
			throws IllegalArgumentException {
		Object object = getObjectByPath(guidPath, adapterFactory);
		if (object == null) {
			throw new IllegalArgumentException(
					"Could not find object with path '" + guidPath + "'"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return isSuppressed(object);
	}

	/**
	 * Gets the set of suppressed item of the given processes.
	 * 
	 * @param proc
	 * @param adapterFactories
	 *            the adapter factories for WBS, TBS, WPBS, and CBS views
	 * @return
	 */
	public static Set getSuppressedItems(Process proc,
			AdapterFactory[] adapterFactories) {
		Set suppressedItems = new HashSet();
		Suppression suppression = new Suppression(proc);
		for (int i = 0; i < adapterFactories.length; i++) {
			for (Iterator iter = new AdapterFactoryTreeIterator(
					adapterFactories[i], proc); iter.hasNext();) {
				Object item = iter.next();
				if (suppression.isSuppressed(item)) {
					suppressedItems.add(item);
				}
			}
		}
		return suppressedItems;
	}

	public static class SuppressionCommand extends AbstractCommand implements
			IResourceAwareCommand {
		private Collection modifiedResources;

		private List collection;

		private Result result;

		private boolean suppressed;

		private Suppression suppression;

		public SuppressionCommand(Suppression suppression, List selection,
				boolean suppressed) {
			this.suppression = suppression;
			collection = selection;
			this.suppressed = suppressed;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.epf.library.edit.command.IResourceAwareCommand#getModifiedResources()
		 */
		public Collection getModifiedResources() {
			if (modifiedResources == null) {
				modifiedResources = Collections.singletonList(suppression
						.getProcess().eResource());
			}
			return modifiedResources;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.Command#execute()
		 */
		public void execute() {
			result = suppression.setSuppressed(collection, suppressed);
			didExecute();
		}

		/**
		 * 
		 */
		protected void didExecute() {

		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.Command#redo()
		 */
		public void redo() {
			execute();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.AbstractCommand#undo()
		 */
		public void undo() {
			if (result != null && !result.isEmpty()) {
				if (!result.elements.isEmpty()) {
					for (Iterator iter = result.elements.iterator(); iter
							.hasNext();) {
						MethodElement e = (MethodElement) iter.next();
						e.setSuppressed(Boolean.valueOf(!suppressed));
					}
				}
				if (!result.paths.isEmpty()) {
					for (Iterator iter = result.paths.iterator(); iter
							.hasNext();) {
						Object path = iter.next();
						if (suppressed) {
							suppression.getSuppressedExternalElementPaths()
									.remove(path);
						} else {
							suppression.getSuppressedExternalElementPaths()
									.add(path);
						}
					}
				}
				didUndo();
				result.clear();
			}
		}

		/**
		 * 
		 */
		protected void didUndo() {

		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.AbstractCommand#prepare()
		 */
		protected boolean prepare() {
			return true;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.AbstractCommand#getResult()
		 */
		public Collection getResult() {
			if (!result.isEmpty()) {
				return collection;
			}
			return Collections.EMPTY_LIST;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.AbstractCommand#getAffectedObjects()
		 */
		public Collection getAffectedObjects() {
			return collection;
		}

		public boolean isReadOnlyElementAffected() {
			return !result.paths.isEmpty();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.emf.common.command.AbstractCommand#dispose()
		 */
		public void dispose() {
			if (result != null) {
				result.clear();
			}

			super.dispose();
		}
	}

}
