//------------------------------------------------------------------------------
// 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_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;
	}

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

}
