//------------------------------------------------------------------------------
// 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.ProcessElement;
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
 * @since 1.0
 */
public class Suppression {

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

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

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

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

	private static final Map procToSuppressionMap = new HashMap();

	private static boolean autoInheritIntermediateSuppressionState = true;

	protected 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
					|| variabilityType == VariabilityType.CONTRIBUTES) {
				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;
	}

	public static synchronized void setSuppression(Suppression sup) {
		procToSuppressionMap.put(sup.getProcess(), sup);
	}
	
	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 = getPathWithoutViewType(wrapper);
		String viewType = getViewType(wrapper);
		path.insert(0, ":/").insert(0, viewType); //$NON-NLS-1$
		return path.toString();
	}
	
	public static StringBuffer getPathWithoutViewType(BreakdownElementWrapperItemProvider wrapper) {
		StringBuffer path = new StringBuffer(); 
		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());
		return path;
	}
	
	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;
	}
	
	protected 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; 
				}
				msg = ProcessUtil.checkBreakdownElementPresentationName(
						adapterFactory, be, be.getPresentationName(), this);
				if (msg != null) {
					return LibraryEditResources.Suppression_presentationNameDuplication; 
				}
			} 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; 
									}
									msg = ProcessUtil
											.checkBreakdownElementPresentationName(
													adapterFactory, be,
													be.getPresentationName(),
													this);
									if (msg != null) {
										return LibraryEditResources.Suppression_presentationNameDuplication; 
									}
								}
							}
						} 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 {
		protected Collection modifiedResources;

		protected List collection;

		protected Result result;

		protected boolean suppressed;

		protected 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();
		}
	}

	/**
	 * @param obj
	 * @return physical state of the processElement
	 */
	public boolean isItselfSuppressed(Object obj){
		if(obj instanceof ProcessElement){
			return ((ProcessElement)obj).getSuppressed();
		}
		
		if(obj instanceof BreakdownElementWrapperItemProvider && ProcessUtil.isInherited(obj)){
			return isInSuppressedList((BreakdownElementWrapperItemProvider)obj);
		}
		
		if(obj instanceof BreakdownElementWrapperItemProvider && !ProcessUtil.isInherited(obj)){
			Object object = TngUtil.unwrap(obj);
			return ((MethodElement)object).getSuppressed();
		}
				
		return false;
	}
	
	public boolean isSuppressed(Object obj, EStructuralFeature feature) {
		return isSuppressed(obj);
	}

}
