//------------------------------------------------------------------------------
// 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.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URL;
import java.text.MessageFormat;
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.MissingResourceException;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.FeatureMapUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.MoveCommand;
import org.eclipse.emf.edit.command.PasteFromClipboardCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.provider.AttributeValueWrapperItemProvider;
import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
import org.eclipse.emf.edit.provider.FeatureMapEntryWrapperItemProvider;
import org.eclipse.emf.edit.provider.IChangeNotifier;
import org.eclipse.emf.edit.provider.IDisposable;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
import org.eclipse.emf.edit.provider.IWrapperItemProvider;
import org.eclipse.emf.edit.provider.ItemProviderAdapter;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.epf.common.utils.NetUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.edit.FeatureValueWrapperItemProvider;
import org.eclipse.epf.library.edit.IDefaultNameSetter;
import org.eclipse.epf.library.edit.IFilter;
import org.eclipse.epf.library.edit.IGroupContainer;
import org.eclipse.epf.library.edit.LibraryEditPlugin;
import org.eclipse.epf.library.edit.LibraryEditResources;
import org.eclipse.epf.library.edit.PresentationContext;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.category.CustomCategoryItemProvider;
import org.eclipse.epf.library.edit.category.StandardCategoriesItemProvider;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.edit.command.IResourceAwareCommand;
import org.eclipse.epf.library.edit.element.ContentPackageItemProvider;
import org.eclipse.epf.library.edit.internal.IListenerProvider;
import org.eclipse.epf.library.edit.navigator.ContentItemProvider;
import org.eclipse.epf.library.edit.navigator.MethodPluginItemProvider;
import org.eclipse.epf.library.edit.process.BreakdownElementWrapperItemProvider;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.epf.library.edit.process.command.MoveDownCommand;
import org.eclipse.epf.library.edit.process.command.MoveUpCommand;
import org.eclipse.epf.library.edit.util.model.OrderInfo;
import org.eclipse.epf.library.edit.util.model.OrderInfoCollection;
import org.eclipse.epf.library.edit.util.model.util.StringResource;
import org.eclipse.epf.library.edit.validation.DependencyChecker;
import org.eclipse.epf.library.edit.validation.NameChecker;
import org.eclipse.epf.library.edit.validation.UniqueNameHandler;
import org.eclipse.epf.services.IAccessController;
import org.eclipse.epf.services.IFileBasedLibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
import org.eclipse.epf.uma.Discipline;
import org.eclipse.epf.uma.Domain;
import org.eclipse.epf.uma.Example;
import org.eclipse.epf.uma.Guidance;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodElementProperty;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.NamedElement;
import org.eclipse.epf.uma.Practice;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.ProcessPlanningTemplate;
import org.eclipse.epf.uma.ReusableAsset;
import org.eclipse.epf.uma.Role;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.RoleSet;
import org.eclipse.epf.uma.Task;
import org.eclipse.epf.uma.Template;
import org.eclipse.epf.uma.Tool;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
import org.eclipse.epf.uma.Whitepaper;
import org.eclipse.epf.uma.WorkBreakdownElement;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkProduct;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.WorkProductType;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.provider.MethodElementItemProvider;
import org.eclipse.epf.uma.provider.UmaEditPlugin;
import org.eclipse.epf.uma.provider.UmaItemProviderAdapterFactory;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.MessageException;
import org.eclipse.epf.uma.util.UmaResources;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.epf.uma.util.UserDefinedTypeMeta;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.util.StringTokenizer;


/**
 * Utility class with static methods for method authoring
 * 
 * @author Phong Nguyen Le
 * @author Jinhua Xi
 * @since 1.0
 */
public final class TngUtil {

	public static final UmaItemProviderAdapterFactory umaItemProviderAdapterFactory = new UmaItemProviderAdapterFactory();

	public static final boolean DEBUG = LibraryEditPlugin.getPlugin()
			.isDebugging();

	public static final String GUIDANCE_FILESTRING_SEPARATOR = "|"; //$NON-NLS-1$

	private static final String GUIDANCE_FILESTRING_SEPARATOR_SPLITTER = "\\|"; //$NON-NLS-1$

	public static final String COMMA_SEPARATOR = ","; //$NON-NLS-1$
	private static final String COMMA_SEPARATOR_SPLITTER = "\\,"; //$NON-NLS-1$
	
	public static final String PUBLISH_CATEGORY_PROPERTY = "PUBLISH_CATEGORY"; //$NON-NLS-1$
	
	/**
	 * Removes all adapters that are instance of the given class from the given
	 * EObject.
	 * 
	 * @param eObj
	 * @param cls
	 */
	public static void removeAdapters(EObject eObj, Class cls) {
		for (Iterator adapters = eObj.eAdapters().iterator(); adapters
				.hasNext();) {
			Adapter adapter = (Adapter) adapters.next();
			if (cls.isInstance(adapter)) {
				adapters.remove();
			}
		}
	}

	public static Object getAdapter(EObject eObj, Class cls) {
		for (Iterator adapters = eObj.eAdapters().iterator(); adapters
				.hasNext();) {
			Adapter adapter = (Adapter) adapters.next();
			if (cls.isInstance(adapter)) {
				return adapter;
			}
		}
		return null;
	}

	public static Adapter adapt(AdapterFactory factory, Notifier notifier,
			Object type, Class viewType) {
		for (Iterator adapters = notifier.eAdapters().iterator(); adapters
				.hasNext();) {
			Adapter adapter = (Adapter) adapters.next();
			if (adapter.isAdapterForType(type) && viewType.isInstance(adapter)) {
				return adapter;
			}
		}
		return factory.adaptNew(notifier, type);
	}

	public static boolean isValidFileName(String name) {
		if (StrUtil.isBlank(name))
			return false;
		if (name.indexOf('/') != -1 || name.indexOf('\\') != -1
				|| name.indexOf(':') != -1 || name.indexOf('*') != -1
				|| name.indexOf('?') != -1 || name.indexOf('"') != -1
				|| name.indexOf('<') != -1 || name.indexOf('>') != -1
				|| name.indexOf('|') != -1 || name.indexOf(';') != -1
				|| name.indexOf('[') != -1 || name.indexOf(']') != -1
				|| name.indexOf('#') != -1)
			return false;
		return true;
	}
	
	/**
	 * validate the string for a plugin name
	 * 
	 * @param name String
	 * @return String
	 */
	public static boolean isValidPluginName(String name) {
		if (isValidFileName(name) == false ) {
			return false;
		}
		
		// need to remove these characters since they caused problem with element url encoding, bookmark issue, 
		// and javascript string liternal escaping issue
		// see 156946 - plugin name should not allow %, #, and '
		if (name.indexOf('%') != -1 || name.indexOf('#') != -1
				|| name.indexOf('\'') != -1 )
			return false;
		return true;
	}

	/**
	 * Checks if the given name is valid for the given EObject.
	 * 
	 * @param eObj
	 * @param name
	 * @param eClasses
	 *            collection of EClass objects. The EObject instances of these
	 *            EClass objects will be saved in their own directory.
	 * @return null if successful, error message otherwise.
	 */
	public static String checkName(NamedElement e, String name,
			Collection eClasses) {
		return checkName(((EObject) e).eContainer(), e, name, TngUtil
				.getTypeText(e), eClasses);
	}

	public static String checkName(EObject parent, NamedElement e, String name,
			String elementTypeText, Collection eClasses) {
		String msg = checkElementName(name, elementTypeText);
		if (msg != null)
			return msg;
		if (parent == null)
			return null;
		List children = parent.eContents();
		for (int i = 0; i < children.size(); i++) {
			NamedElement child = (NamedElement) children.get(i);
			if (child != e && isEClassInstanceOf(eClasses, child)
					&& name.equalsIgnoreCase(child.getName())) {
				//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
				return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, name); 
			}
		}
		return null;
	}

	public static String checkName(EObject parent, NamedElement e, String name,
			String elementTypeText, IFilter childFilter) {
		String msg = checkElementName(name, elementTypeText);
		if (msg != null)
			return msg;
		if (parent == null)
			return null;
		List children = parent.eContents();
		for (int i = 0; i < children.size(); i++) {
			NamedElement child = (NamedElement) children.get(i);
			if (child != e && childFilter.accept(child)
					&& name.equalsIgnoreCase(child.getName())) {
				//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
				return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, name); 
			}
		}
		return null;
	}

	/**
	 * Checks if the given name can be used for the given element. The method
	 * assume that the given element will be saved under the given directory
	 * using the given name.
	 * 
	 * @param dir
	 *            Directory where the given element will be saved in a file or a
	 *            directory depending on the value of isDir
	 * @param siblings
	 *            exisiting siblings of the given element <code>e</code>
	 * @param e
	 *            the element its name to be checked.
	 * @param name
	 *            the suggested new name for the given element <code>e</code>
	 * @param typeLabel
	 *            the element type label.
	 * @param isDir
	 *            flag indicating whether the given element will be saved a
	 *            directory
	 * @return null if the given name can be used, an error message if the name
	 *         is already taken.
	 */
	public static String checkName(File dir, Collection siblings,
			NamedElement e, String name, String elementTypeText, boolean isDir) {
		String msg = checkElementName(name, elementTypeText);
		if (msg != null)
			return msg;
		String fileName = name;
		if (!isDir) {
			fileName = fileName + ((IFileBasedLibraryPersister)Services.getDefaultLibraryPersister()).getFileExtension(e);
		}
		File file = new File(dir, fileName);
		File currentFile = null;
		if (e != null && e.eResource() != null) {
			currentFile = new File(e.eResource().getURI().toFileString());
			if (isDir) {
				currentFile = currentFile.getParentFile();
			}
		}
		boolean b = file.exists();
		if (b && !file.equals(currentFile)) {
			msg = NLS.bind(LibraryEditResources.duplicateElementNameError_msg, name);
			/* TODO: is this needed? After calling NLS.bind, there will	not be any placeholders left for params.
			Object[] params = new Object[2];
			if (file.isFile()) {
				params[0] = LibraryEditResources.file_text; 
			} else {
				params[0] = LibraryEditResources.directory_text; 
			}
			params[1] = file;
			return MessageFormat.format(msg, params).toString();
			*/
			return msg;
		}
		for (Iterator iter = siblings.iterator(); iter.hasNext();) {
			NamedElement child = (NamedElement) iter.next();
			if (child != e && name.equalsIgnoreCase(child.getName())) {
				//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
				return NLS.bind(LibraryEditResources.duplicateElementNameError_msg, name); 
			}
		}
		// 
		return null;

	}

	public static String checkElementName(String name, String elementTypeText) {
		if (name == null || name.trim().length() == 0)
			//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
			return NLS.bind(LibraryEditResources.emptyElementNameError_msg, StrUtil.toLower(elementTypeText)); 
		if (name.startsWith(" ")) //$NON-NLS-1$
			//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
			return NLS.bind(LibraryEditResources.invalidElementNameError1_msg, name); 
		if (name.endsWith(".")) //$NON-NLS-1$
			//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
			return NLS.bind(LibraryEditResources.invalidElementNameError2_msg, name); 		
		if (!isValidFileName(name))
			//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
			return NLS.bind(LibraryEditResources.invalidElementNameError3_msg, name); 
		return null;
	}

	public static String checkPluginName(String name) {
	
		String error = checkElementName(name, TngUtil.getTypeText("MethodPlugin") ); //$NON-NLS-1$
		if ( error != null ) {
			return error;
		}
		
		// 156946 - plugin name should not allow %, #, and '
		if (!isValidPluginName(name) ) {
			//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
			return NLS.bind(LibraryEditResources.invalidPluginNameError_msg, name); 
		} else {
			return null;
		}
		
	}
	
	public static String checkActivityName(AdapterFactory adapterFactory,
			Object object, String name, Suppression suppression) {
		if (!(object instanceof Activity))
			return null;
		// if(!isValidFileName(name)) return "Invalid name: '" + name + "'. The
		// name cannot contain following characters: \\ / : * ? \" < > |";
		return NameChecker.checkName(adapterFactory, (BreakdownElement) object, Activity.class,
				UmaPackage.eINSTANCE.getNamedElement_Name(), name, suppression);
	}

//	public static String checkWBSActivityName(Object act, String name) {
//		return checkActivityName(TngAdapterFactory.INSTANCE
//				.getWBS_ComposedAdapterFactory(), act, name);
//	}

	public static String checkWBSActivityPresentationName(Object act,
			String name, Suppression suppression) {
		if (!(act instanceof Activity))
			return null;
		return NameChecker.checkName(TngAdapterFactory.INSTANCE
				.getWBS_ComposedAdapterFactory(), (BreakdownElement) act, Activity.class,
				UmaPackage.eINSTANCE.getMethodElement_PresentationName(),
				name, suppression);
	}

	public static String checkWorkBreakdownElementPresentationName(Object e,
			String name, Suppression suppression) {
		if (!(e instanceof WorkBreakdownElement))
			return null;
		return NameChecker.checkName(TngAdapterFactory.INSTANCE
				.getWBS_ComposedAdapterFactory(), (BreakdownElement) e,
				WorkBreakdownElement.class, UmaPackage.eINSTANCE
						.getMethodElement_PresentationName(), name, suppression);
	}

	public static String checkWorkProductDescriptorPresentationName(Object e,
			String name, Suppression suppression) {
		if (!(e instanceof WorkProductDescriptor))
			return null;
		return NameChecker.checkName(TngAdapterFactory.INSTANCE
				.getPBS_ComposedAdapterFactory(), (BreakdownElement) e,
				WorkProductDescriptor.class, UmaPackage.eINSTANCE
						.getMethodElement_PresentationName(), name, suppression);
	}

	public static String checkRoleDescriptorPresentationName(Object e,
			String name, Suppression suppression) {
		if (!(e instanceof RoleDescriptor))
			return null;
		return NameChecker.checkName(TngAdapterFactory.INSTANCE
				.getOBS_ComposedAdapterFactory(), (BreakdownElement) e, RoleDescriptor.class,
				UmaPackage.eINSTANCE.getMethodElement_PresentationName(),
				name, suppression);
	}

	public static boolean isEClassInstanceOf(Collection eClasses, Object obj) {
		for (Iterator iter = eClasses.iterator(); iter.hasNext();) {
			EClass eClass = (EClass) iter.next();
			if (eClass.isInstance(obj))
				return true;
		}
		return false;
	}

	public static boolean isInstanceOf(Collection classes, Object obj) {
		for (Iterator iter = classes.iterator(); iter.hasNext();) {
			Class clazz = (Class) iter.next();
			if (clazz.isInstance(obj))
				return true;
		}
		return false;
	}

	public static AdapterFactory getBestAdapterFactory(
			AdapterFactory adapterFactory) {
		if (adapterFactory instanceof ComposeableAdapterFactory) {
			return ((ComposeableAdapterFactory) adapterFactory)
					.getRootAdapterFactory();
		}
		return adapterFactory;
	}

	/**
	 * @param object
	 */
	public static String getLabel(Object object) {
		return getLabel(object, ""); //$NON-NLS-1$
	}

	public static String getLabel(Object object, String alternativeLabel) {
		if (object instanceof ContentDescription) {
			return getLabel(((ContentDescription) object).eContainer(), alternativeLabel);
		}
		
		if (object instanceof EObject) {
			EObject eObj = (EObject) object;
			if (eObj.eIsProxy()) {
				String path = null;
				try {
					org.eclipse.emf.common.util.URI uri = eObj.eResource().getResourceSet().getURIConverter()
							.normalize(((InternalEObject) eObj).eProxyURI());
					path = uri.isFile() ? uri.toFileString() : uri.toString();
				} catch (Exception e) {
					//
				}
				if (path != null) {
					path = MessageFormat.format(
							" ''{0}''", new Object[] { path }); //$NON-NLS-1$
				} else {
					path = ""; //$NON-NLS-1$
				}
				//		return I18nUtil.formatString(RESOURCE_BUNDLE, key, data);
				return NLS.bind(LibraryEditResources.unresolved_text, path); 
			}
		}
		String label = null;
		boolean showPresentationNames = PresentationContext.INSTANCE.isShowPresentationNames();
		if (showPresentationNames && object instanceof ProcessComponent)
			label = ((ProcessComponent) object).getProcess()
					.getPresentationName();
		else if (showPresentationNames && object instanceof MethodElement)
			label = ((MethodElement) object).getPresentationName();
		if (label == null || label.trim().length() == 0)
			label = ((NamedElement) object).getName();
		return label == null || label.trim().length() == 0 ? alternativeLabel : label;
	}

	public static String getLabel(VariabilityElement object,
			String alternativeLabel, boolean preferBase) {
		String label = TngUtil.getLabel(object, alternativeLabel);
		if (preferBase && object.getVariabilityBasedOnElement() != null) {
			VariabilityType type = object.getVariabilityType();
			String variabilityTxt = null;
			if (type == VariabilityType.CONTRIBUTES) {
				variabilityTxt = LibraryEditResources.contributesTo_text; 
			} else if (type == VariabilityType.LOCAL_CONTRIBUTION) {
					variabilityTxt = LibraryEditResources.localContributesTo_text; 
			} else if (type == VariabilityType.EXTENDS) {
				variabilityTxt = LibraryEditResources.extends_text; 
			} else if (type == VariabilityType.REPLACES) {
				variabilityTxt = LibraryEditResources.replaces_text; 
			} else if (type == VariabilityType.LOCAL_REPLACEMENT) {
				variabilityTxt = LibraryEditResources.localReplaces_text; 
			} else if (type == VariabilityType.EXTENDS_REPLACES){
				variabilityTxt = LibraryEditResources.extends_replaces_text;
			}
			if (variabilityTxt != null) {
				MethodPlugin basePlugin = UmaUtil.getMethodPlugin(object
						.getVariabilityBasedOnElement());
				if (basePlugin != null) {
					label = NLS.bind(LibraryEditResources.Util_labelpath_variabilitywithplugin_info, (new String[] {
					label,
					variabilityTxt,
					TngUtil
							.getLabel(
									object
											.getVariabilityBasedOnElement(),
									alternativeLabel),
					basePlugin.getName() }));
				} else {
					label = NLS.bind(LibraryEditResources.Util_labelpath_variability_info, (new String[] {
					label,
					variabilityTxt,
					TngUtil.getLabel(object
							.getVariabilityBasedOnElement(),
							alternativeLabel) }));
				}
			}
		}

		return label;
	}

	/**
	 * Initializes a newly created ProcessComponent
	 * 
	 * @param component
	 */
	public static void initializeProcessComponent(ProcessComponent component,
			EClass type) {
		// create new process for the process component
		//
		Process proc = component.getProcess();
		if (proc == null) {
			proc = (Process) UmaFactory.eINSTANCE.create(type);
			component.setProcess(proc);
		}

		// create top activity
		//
		// if(proc.getTopLevelBreakdownElement() == null) {
		// Activity act = UmaFactory.eINSTANCE.createActivity();
		// proc.setTopLevelBreakdownElement(act);
		// component.getBreakdownElements().add(act);
		// }

		// create WBS, OBS, and PBS
		//
		// if(component.getWBS() == null)
		// component.setWBS(UmaFactory.eINSTANCE.createWBS());
		// if(component.getTBS() == null)
		// component.setTBS(UmaFactory.eINSTANCE.createTBS());
		// if(component.getWPBS() == null)
		// component.setWPBS(UmaFactory.eINSTANCE.createWPBS());
	}

	public static BreakdownElement getParent(BreakdownElement be) {
		return null;
	}

	public static String checkNull(String str) {
		return (str == null ? "" : str); //$NON-NLS-1$
	}

	public static boolean descriptorExists(Role role, List roleDescriptorList) {
		for (int i = roleDescriptorList.size() - 1; i > -1; i--) {
			RoleDescriptor roleDesc = (RoleDescriptor) roleDescriptorList
					.get(i);
			if (roleDesc.getRole() == role)
				return true;
		}
		return false;
	}

	public static MethodElement copy(MethodElement element) {
		Copier copier = new Copier() {
			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 3257846576033904691L;

			/**
			 * Called to handle the copying of a cross reference; this adds
			 * values or sets a single value as appropriate for the multiplicity
			 * while omitting any bidirectional reference or single opposite
			 * feature's reference that isn't in the copy map.
			 * 
			 * @param eReference
			 *            the reference to copy.
			 * @param eObject
			 *            the object from which to copy.
			 * @param copyEObject
			 *            the object to copy to.
			 */
			protected void copyReference(EReference eReference,
					EObject eObject, EObject copyEObject) {
				if (eObject.eIsSet(eReference)) {
					OppositeFeature oppositeFeature = OppositeFeature.getOppositeFeature(eReference);
					
					// "many" opposite feature does not require copied target, it is
					// treated as a regular non-containment reference
					// TODO: bidirectional relationships are not automatically copied in
					// EMF implementation
					//
					boolean copiedTargetRequired = eReference.getEOpposite() != null
							|| (oppositeFeature != null && !oppositeFeature.isMany());
										
					if (eReference.isMany()) {
						List source = (List) eObject.eGet(eReference);
						InternalEList target = (InternalEList) copyEObject
								.eGet(getTarget(eReference));
						if (source.isEmpty()) {
							target.clear();
						} else {
							int index = 0;
							for (Iterator k = source.iterator(); k.hasNext();) {
								Object referencedEObject = k.next();
								Object copyReferencedEObject = get(referencedEObject);
								if (copyReferencedEObject == null) {
									if (!copiedTargetRequired) {
										target.addUnique(index,
												referencedEObject);
										++index;
									}
								} else {
									if (copiedTargetRequired) {
										int position = target
												.indexOf(copyReferencedEObject);
										if (position == -1) {
											target.addUnique(index,
													copyReferencedEObject);
										} else if (index != position) {
											target.move(index,
													copyReferencedEObject);
										}
									} else {
										target.addUnique(index,
												copyReferencedEObject);
									}
									++index;
								}
							}
						}
					} else {
						Object referencedEObject = eObject.eGet(eReference);
						if (referencedEObject == null) {
							copyEObject.eSet(getTarget(eReference), null);
						} else {
							Object copyReferencedEObject = get(referencedEObject);
							if (copyReferencedEObject == null) {
								if (!copiedTargetRequired) {
									copyEObject.eSet(getTarget(eReference),
											referencedEObject);
								}
							} else {
								copyEObject.eSet(getTarget(eReference),
										copyReferencedEObject);
							}
						}
					}
				}
			}
		};
		MethodElement copy = (MethodElement) copier.copy(element);
		copier.copyReferences();

		// unset the GUID of the copy and its offstring
		//
		copy.setGuid(null);
		for (Iterator iter = copy.eAllContents(); iter.hasNext();) {
			Object e = iter.next();
			if (e instanceof MethodElement) {
				((MethodElement) e).setGuid(null);
			}
		}
		return copy;
	}

	public static VariabilityElement getBase(VariabilityElement c) {
		for (; c.getVariabilityBasedOnElement() != null; c = (VariabilityElement) c
				.getVariabilityBasedOnElement())
			;
		return c;
	}

	public static ContentCategory findInherited(Collection inheritedList,
			ContentCategory category) {
		for (Iterator iter = inheritedList.iterator(); iter.hasNext();) {
			ContentCategory element = (ContentCategory) iter.next();
			if (element.getVariabilityBasedOnElement() != null
					&& (element.getVariabilityBasedOnElement() == category || element
							.getVariabilityBasedOnElement() == category
							.getVariabilityBasedOnElement()))
				return element;
		}
		return null;
	}

	public static ContentCategory removeInherited(List inheritedList,
			ContentCategory category) {
		for (Iterator iter = inheritedList.iterator(); iter.hasNext();) {
			ContentCategory element = (ContentCategory) iter.next();
			if (element.getVariabilityBasedOnElement() == category) {
				iter.remove();
				return element;
			}
		}
		return null;
	}
	
	public static ContentItemProvider getContentItemProvider(MethodPlugin plugin) {
		MethodPluginItemProvider methodPluginItemProvider = (MethodPluginItemProvider)getAdapter(
				plugin,	MethodPluginItemProvider.class);
		methodPluginItemProvider.getChildren(plugin);
		IGroupContainer groupContainer = (IGroupContainer) TngUtil.getAdapter(
				(EObject) plugin, IGroupContainer.class);
		if (groupContainer != null) {
			return (ContentItemProvider) groupContainer
					.getGroupItemProvider(LibraryEditPlugin.INSTANCE
							.getString("_UI_Content_group")); //$NON-NLS-1$
		}
		return null;
	}
	
	public static StandardCategoriesItemProvider getStandardCategoriesItemProvider(MethodPlugin plugin) {
		ContentItemProvider contentItemProvider = getContentItemProvider(plugin);
		contentItemProvider.getChildren(contentItemProvider);
		if (contentItemProvider != null) {
			return (StandardCategoriesItemProvider)contentItemProvider.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_Standard_Categories_group")); //$NON-NLS-1$
		}
		return null;
	}


	public static Object getDisciplineCategoriesItemProvider(MethodPlugin model) {
		StandardCategoriesItemProvider standardCategoriesItemProvider = getStandardCategoriesItemProvider(model);
		standardCategoriesItemProvider.getChildren(standardCategoriesItemProvider);
		if (standardCategoriesItemProvider != null) {
			return standardCategoriesItemProvider
			.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_Disciplines_group")); //$NON-NLS-1$
		}
		return null;
	}

	public static Object getDomainsItemProvider(MethodPlugin model) {
		StandardCategoriesItemProvider standardCategoriesItemProvider = getStandardCategoriesItemProvider(model);
		standardCategoriesItemProvider.getChildren(standardCategoriesItemProvider);
		if (standardCategoriesItemProvider != null) {
			return standardCategoriesItemProvider
			.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_Domains_group")); //$NON-NLS-1$
		}
		return null;
	}

	public static Object getWorkProductTypesItemProvider(MethodPlugin model) {
		StandardCategoriesItemProvider standardCategoriesItemProvider = getStandardCategoriesItemProvider(model);
		standardCategoriesItemProvider.getChildren(standardCategoriesItemProvider);
		if (standardCategoriesItemProvider != null) {
			return standardCategoriesItemProvider
			.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_WorkProductTypes_group")); //$NON-NLS-1$
		}
		return null;
	}

	public static Object getRoleSetsItemProvider(MethodPlugin model) {
		StandardCategoriesItemProvider standardCategoriesItemProvider = getStandardCategoriesItemProvider(model);
		standardCategoriesItemProvider.getChildren(standardCategoriesItemProvider);
		if (standardCategoriesItemProvider != null) {
			return standardCategoriesItemProvider
			.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_Role_Sets_group")); //$NON-NLS-1$
		}
		return null;
	}

	public static Object getToolsItemProvider(MethodPlugin model) {
		StandardCategoriesItemProvider standardCategoriesItemProvider = getStandardCategoriesItemProvider(model);
		standardCategoriesItemProvider.getChildren(standardCategoriesItemProvider);
		if (standardCategoriesItemProvider != null) {
			return standardCategoriesItemProvider
			.getGroupItemProvider(LibraryEditPlugin.INSTANCE
					.getString("_UI_Tools_group")); //$NON-NLS-1$
		}
		return null;
	}
	
	/**
	 * Gets the next available name that is not already taken by any of the specified elements.
	 * 
	 * @param elements
	 * @param e
	 * @param baseName
	 * @return baseName of baseName_X where is is the number starting from 2
	 */
	public static String getNextAvailableName(List<? extends MethodElement> elements, String baseName) {
		if(isNameTaken(elements, null, baseName)) {
			for (int i = 2; true; i++) {
				String name = baseName + '_' + i;
				if (!isNameTaken(elements, null, name)) {
					return name;
				}
			}
		}
		return baseName;
	}


	public static void setDefaultName(List<? extends MethodElement> siblings, MethodElement e,
			String baseName) {
		if (e.getName() != null && e.getName().trim().length() > 0)
			return;

		if (!isNameTaken(siblings, e, baseName)) {
			e.setName(baseName);
			setPresentationName(e, baseName);
			return;
		}
		for (int i = 2; true; i++) {
			String name = baseName + '_' + i;
			if (!isNameTaken(siblings, e, name)) {
				e.setName(name);
				setPresentationName(e, name);
				return;
			}
		}
	}
		
	public static void setDefaultName(CustomCategory parent, CustomCategory cc, String baseName) {
		MethodPlugin plugin = UmaUtil.getMethodPlugin(parent);
		ContentPackage pkg = plugin == null ? null : UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);
		if (pkg == null) {
			TngUtil.setDefaultName(parent.getCategorizedElements(), cc, baseName);
			return;
		}
		
		UniqueNameHandler handler = new UniqueNameHandler();
		handler.registerNames(pkg.getContentElements());
		String name = handler.getUniqueName(baseName);
		cc.setName(name);
		cc.setPresentationName(name);
	}

	private static void setPresentationName(MethodElement e, String baseName) {
		if (e instanceof DescribableElement) {
			DescribableElement de = (DescribableElement) e;

			StringBuffer presNameBuf = new StringBuffer();
			StringTokenizer st = new StringTokenizer(baseName, "_"); //$NON-NLS-1$
			while (st.hasMoreTokens()) {
				String aWord = st.nextToken();
				presNameBuf.append(aWord.substring(0, 1).toUpperCase()
						+ aWord.substring(1) + " "); //$NON-NLS-1$
			}

			de.setPresentationName(presNameBuf.toString().trim());
		}
	}

	private static boolean isNameTaken(List<? extends MethodElement> siblings, MethodElement e,
			String name) {
		for (int i = siblings.size() - 1; i > -1; i--) {
			MethodElement sibling = (MethodElement) siblings.get(i);
			if (sibling != e && name.equalsIgnoreCase(sibling.getName())) {
				return true;
			}
		}
		return false;
	}

	public static List extract(Collection collection, Class cls) {
		ArrayList list = new ArrayList();
		for (Iterator iter = collection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (cls.isInstance(element)) {
				list.add(element);
			}
		}
		return list;
	}
	
	public static <T> List<T> extractType(Collection<? extends Object> collection, Class<T> cls) {
		ArrayList<T> list = new ArrayList<T>();
		for (Iterator<? extends Object> iter = collection.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (cls.isInstance(element)) {
				list.add((T)element);
			}
		}
		return list;
	}


	public static void setDefaultName(IDefaultNameSetter defaultNameSetter,
			Notification msg) {
		if (defaultNameSetter.getInterestedFeatureOwnerClass() != null) {
			int featureId = msg.getFeatureID(defaultNameSetter
					.getInterestedFeatureOwnerClass());
			if (featureId == defaultNameSetter.getInterestedFeatureID()) {
				switch (msg.getEventType()) {
				case Notification.ADD:
					defaultNameSetter.setDefaultName(msg.getNewValue());
					break;
				case Notification.ADD_MANY:
					for (Iterator iter = ((Collection) msg.getNewValue())
							.iterator(); iter.hasNext();) {
						defaultNameSetter.setDefaultName(iter.next());
					}
					break;
				}
			}
		}
	}

	/**
	 * @param baseCategory
	 * @param methodConf
	 * @param children
	 */
	public static void addExtendedChildren(ContentCategory baseCategory,
			MethodConfiguration methodConf, Collection children,
			String[] categoryPkgPath) {
		Map<String, Boolean> map = new HashMap<String, Boolean>(); 
		MethodPlugin basePlugin = UmaUtil.getMethodPlugin(baseCategory);
		for (Iterator iter = methodConf.getMethodPluginSelection().iterator(); iter
				.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) iter.next();
			if (Misc.isBaseOf(basePlugin, plugin, map)) {
				ContentPackage categoryPkg = UmaUtil.findContentPackage(plugin,
						categoryPkgPath);
				if (categoryPkg != null
						&& methodConf.getMethodPackageSelection().contains(
								categoryPkg)) {
					ContentCategory category = findInherited(categoryPkg
							.getContentElements(), baseCategory);
					if (category != null) {
						ItemProviderAdapter adapter = (ItemProviderAdapter) TngAdapterFactory.INSTANCE
								.getNavigatorView_ComposedAdapterFactory()
								.adapt(category, ITreeItemContentProvider.class);
						if (adapter == null) {
							System.err
									.println("DisciplineGroupingItemProvider.addExtendedChildren(): could not find adapter for " + category); //$NON-NLS-1$
						}
						for (Iterator iterator = adapter.getChildren(category)
								.iterator(); iterator.hasNext();) {
							Object child = (Object) iterator.next();
							ContentElement element = null;
							if (child instanceof ContentElement) {
								element = (ContentElement) child;
							}
							if (element != null
									&& element.getVariabilityBasedOnElement() == null) {
								// this is an own child of an extended category
								// it must be added to the child list of the
								// base category in the configuration.
								//
								children.add(child);
							}
						}

						// collect the own children of the extended categories
						// of this category down the inheritance tree
						//
						addExtendedChildren(category, methodConf, children,
								categoryPkgPath);
					}
				}
			}
		}
	}
	
	public static void addAllTo(List allChildren, List newChildren) {
		int id;
		BreakdownElement child, next, last;
		ArrayList list = new ArrayList();
		while(!newChildren.isEmpty()) {
			child = (BreakdownElement) newChildren.remove(0);
			list.clear();
			list.add(child);
			last = null;
			
			// find the last element of the chain in new children list
			//
			find_last:
			for(next = child.getPresentedAfter(); next != null; next = next.getPresentedAfter()) {
				last = next;
				id = indexOfNextElement(newChildren, next);
				if(id == -1) {
					break find_last;
				}
				else {
					list.add(newChildren.remove(id));
				}
			}
			if(last != null) {
				id = indexOfNextElement(allChildren, last);
				if(id == -1) {
					allChildren.addAll(list);
				}
				else {
					allChildren.addAll(id, list);
				}
			}
			else {
				allChildren.add(child);
			}
		}
	}

	/**
	 * Adds the given child to the allChildren list based on the presentedBefore
	 * of child.
	 * 
	 * @param allChildren
	 * @param child
	 */
	public static void addTo(List allChildren, BreakdownElement child,
			Object owner, AdapterFactory adapterFactory) {
		BreakdownElement next = child.getPresentedAfter();
		int id;
		if (next == null) {
			id = -1;
		} else {
			id = indexOfNextElement(allChildren, next);
			// if(id == -1) {
			// // System.out.println("TngUtil.addTo(): invalid presentedBefore
			// of " + child);
			// BreakdownElement prev = child.getPresentedBefore();
			// if(prev == null) {
			// id = 0;
			// }
			// else {
			// id = indexOf(allChildren, prev);
			// if(id > -1) {
			// if(id < allChildren.size() - 1) {
			// id++;
			// }
			// else {
			// id = -1;
			// }
			// }
			// }
			// }
		}
		if (id == -1) {
			allChildren.add(child);
		} else {
			allChildren.add(id, child);
		}
	}

	/**
	 * Gets the index of next element of the breakdown element whose presented-after element is the given 
	 * break down element
	 * @param mixedList
	 *            mixed list of BreakdownElementWrapperItemProvider and
	 *            BreakdownElement objects
	 * @param presentedAfter
	 * @return
	 */
	private static int indexOfNextElement(List mixedList, BreakdownElement presentedAfter) {
		int size = mixedList.size();
		for (int i = 0; i < size; i++) {
			Object o = unwrap(mixedList.get(i));
			if (o == presentedAfter
					|| (o instanceof VariabilityElement && ((VariabilityElement)o).getVariabilityBasedOnElement() == presentedAfter)) {
				return i;
			}
		}
		return -1;
	}
	
	public static List getAvailableBaseProcesses(MethodPlugin plugin,
			List processClasses) {
		List processes = new ArrayList();
		List allBasePlugins = Misc.getAllBase(plugin);
		allBasePlugins.add(0, plugin);
		for (Iterator iter = allBasePlugins.iterator(); iter.hasNext();) {
			MethodPlugin basePlugin = (MethodPlugin) iter.next();
			Collection packages = getRootProcessPackages(basePlugin,
					processClasses);
			for (Iterator iterator = packages.iterator(); iterator.hasNext();) {
				ProcessPackage pkg = (ProcessPackage) iterator.next();
				for (Iterator iterator1 = pkg.getChildPackages().iterator(); iterator1
						.hasNext();) {
					Object childPkg = (Object) iterator1.next();
					if (childPkg instanceof ProcessComponent) {
						Process proc = ((ProcessComponent) childPkg)
								.getProcess();
						if (isInstanceOf(processClasses, proc)) {
							processes.add(proc);
						}
					}
				}
			}
		}
		return processes;
	}

	private static String[] getRootProcessPackagePath(Class procClass) {
		if (procClass == DeliveryProcess.class) {
			return ModelStructure.DEFAULT.deliveryProcessPath;
		} else if (procClass == CapabilityPattern.class) {
			return ModelStructure.DEFAULT.capabilityPatternPath;
		} else if (procClass == ProcessPlanningTemplate.class) {
			return ModelStructure.DEFAULT.processPlanningTemplatePath;
		}

		return null;
	}

	private static Collection getRootProcessPackages(MethodPlugin plugin,
			Collection procClasses) {
		List packages = new ArrayList();
		for (Iterator iter = procClasses.iterator(); iter.hasNext();) {
			Class clazz = (Class) iter.next();
			String[] path = getRootProcessPackagePath(clazz);
			if (path != null) {
				MethodPackage pkg = UmaUtil.findMethodPackage(plugin, path);
				if (pkg instanceof ProcessPackage) {
					packages.add(pkg);
				}
			}
		}

		return packages;
	}
	
	/**
	 * 
	 * @param plugin
	 * @return true iff the plugin has any ContentCategory objects
	 */
	public static boolean hasCategories(MethodPlugin plugin) {
		List<ContentPackage> conPacks = getContentCategoryPackages(plugin);
		for (Iterator<ContentPackage> conPacksIter = conPacks.iterator();conPacksIter.hasNext();) {
			ContentPackage conPack = conPacksIter.next();
			for (Iterator conPackIter = conPack.getContentElements().iterator();conPackIter.hasNext();) {
				Object o = conPackIter.next();
				if (o instanceof ContentCategory) {
					return true;
				}
			}
		}
		return false;
	}		

	public static List<Process> getAllProcesses(MethodPlugin plugin) {
		List<Process> processes = new ArrayList<Process>();
		for (MethodPackage pkg : plugin.getMethodPackages()) {
			_iteratePackageForProcesses(pkg, processes);
		}

		return processes;
	}

	public static List<Process> getAllProcesses(MethodPackage pkg) {
		List<Process>  processes = new ArrayList<Process> ();
		_iteratePackageForProcesses(pkg, processes);

		return processes;
	}
	
	private static void _iteratePackageForProcesses(MethodPackage pkg,
			List processes) {
		if (pkg instanceof ProcessComponent) {
			Process p = ((ProcessComponent) pkg).getProcess();
			if (p != null && !processes.contains(p)) {
				processes.add(p);
			}
		}

		for (Iterator it = pkg.getChildPackages().iterator(); it.hasNext();) {
			_iteratePackageForProcesses((MethodPackage) it.next(), processes);
		}
	}

	/**
	 * Checks if e is a subelement of parent
	 * 
	 * @param parent
	 * @param e
	 * @param adapterFactory
	 * @return
	 */
	public static boolean isSubelementOf(Object parent, Object e,
			AdapterFactory adapterFactory) {
		if (parent == e)
			return false;
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
				.adapt(parent, ITreeItemContentProvider.class);
		for (Iterator<?> iter = adapter.getChildren(parent).iterator(); iter
				.hasNext();) {
			Object element = (Object) iter.next();
			if (element == e)
				return true;
			if (isSubelementOf(element, e, adapterFactory)) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @param child
	 * @param e
	 * @param adapterFactory
	 * @return
	 */
	public static boolean isSuperElementOf(Object child, Object e,
			AdapterFactory adapterFactory) {
		if (child == e)
			return false;
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
				.adapt(e, ITreeItemContentProvider.class);
		for (Iterator<?> iter = adapter.getChildren(e).iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if (element == child)
				return true;
			if (isSuperElementOf(child, element, adapterFactory)) {
				return true;
			}
		}

		return false;
	}

	public static Object unwrap(Object obj) {
		if (obj instanceof IWrapperItemProvider) {
			do {
				obj = ((IWrapperItemProvider) obj).getValue();
			} while (obj instanceof IWrapperItemProvider);
		} else if (obj instanceof CommandWrapper) {
			do {
				obj = ((CommandWrapper) obj).getCommand();
			} while (obj instanceof CommandWrapper);
		}

		return obj;
	}
	
	/**
	 * Returns boolean value based on whether object is wrapper object or not
	 * @param obj
	 * @return
	 */
	public static boolean isWrapped(Object obj) {
		if (obj instanceof IWrapperItemProvider || obj instanceof CommandWrapper) {
			return true;
		}
		return false;
	}

	public static Command unwrap(Command cmd) {
		while (cmd instanceof CommandWrapper) {
			cmd = ((CommandWrapper) cmd).getCommand();
		}

		return cmd;
	}

	/**
	 * Checks if the given <code>base</code> is the base element of any
	 * element in the given elements
	 * 
	 * @param elements
	 * @param base
	 * @param variabilityTypes variability types to check against, ignored if <code>null</code>
	 * @return
	 */
	public static boolean isBase(List<?> elements, Object base, Set<VariabilityType> variabilityTypes) {
		for (Iterator<?> iter = elements.iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if (element instanceof VariabilityElement) {
				VariabilityElement ve = ((VariabilityElement) element);
				if (base == ve.getVariabilityBasedOnElement()
						&& (variabilityTypes == null || variabilityTypes
								.contains(ve.getVariabilityType()))) {
					return true;
				}
			}
		}
		return false;
	}
	
	

	public static String getPresentationName(Object e) {
		return getPresentationName(e, null);
	}
	
	public static String getPresentationName(Object e, PresentationNameHelper helper) {
		if (e instanceof ContentDescription) {
			e = ((ContentDescription) e).eContainer();
		}

		if (e == null) {
			return ""; //$NON-NLS-1$
		}

		String name = null;
		
		if (e instanceof MethodElement) {
			name = ((MethodElement) e).getPresentationName();
			if (StrUtil.isBlank(name)) 	{
				if (helper != null) {
					name = helper.getPresentationName((MethodElement) e);
				} 
				if (helper == null || StrUtil.isBlank(name)) {
					name = ((MethodElement) e).getName();
				}
			}
		}

		return name;
	}

	public static Process getOwningProcess(BreakdownElement e) {
		EObject container;
		for (container = e.eContainer(); container != null
				&& !(container instanceof ProcessComponent); container = container
				.eContainer())
			;
		if (container != null) {
			return ((ProcessComponent) container).getProcess();
		}
		return null;
	}
	
	public static Process getOwningProcess(BreakdownElementWrapperItemProvider wrapper) {
		Object top = wrapper.getTopItem();
		if(top instanceof Process) {
			Process proc = (Process) top;
			if(proc.eContainer() instanceof ProcessComponent) {
				return proc;
			}
		}
		return null;
	}
	
	public static Process getOwningProcess(Object object) {
		if(object instanceof BreakdownElement) {
			return getOwningProcess((BreakdownElement)object);
		}
		else if(object instanceof BreakdownElementWrapperItemProvider) {
			return getOwningProcess((BreakdownElementWrapperItemProvider)object);
		}
		return null;
	}

	public static boolean canReference(MethodElement source,
			MethodElement target) {
		MethodPlugin targetPlugin = UmaUtil.getMethodPlugin(target);
		MethodPlugin sourcePlugin = UmaUtil.getMethodPlugin(source);
		if (sourcePlugin == targetPlugin)
			return true;
		return Misc.isBaseOf(targetPlugin, sourcePlugin, new HashMap<String, Boolean>());
	}

	public static OrderInfo getOrderInfo(MethodElement e, String orderInfoName) {
		String str = e.getOrderingGuide();
		if (str == null || str.length() == 0)
			return null;
		Resource res = new StringResource(str);
		try {
			res.load(null);
			if (res.getContents().isEmpty())
				return null;
			OrderInfoCollection orderInfos = (OrderInfoCollection) res
					.getContents().get(0);
			for (Iterator iter = orderInfos.getOrderInfos().iterator(); iter
					.hasNext();) {
				OrderInfo orderInfo = (OrderInfo) iter.next();
				if (orderInfoName.equalsIgnoreCase(orderInfo.getName())) {
					return orderInfo;
				}
			}
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return null;
	}

	/**
	 * @param provider
	 * @param notification
	 */
	public static void refreshContributors(IChangeNotifier notifier,
			Notification notification, boolean contentRefresh,
			boolean labelUpdate) {
		for (Iterator iter = getContributors((VariabilityElement) notification
				.getNotifier()); iter.hasNext();) {
			Object element = iter.next();
			notifier.fireNotifyChanged(new ViewerNotification(notification,
					element, contentRefresh, labelUpdate));
		}
	}
	
	/**
	 * Used to refresh plugins that extend another
	 * @param notifier
	 * @param notification
	 * @param contentRefresh
	 * @param labelUpdate
	 */
	public static void refreshPluginExtenders(IChangeNotifier notifier,
			Notification notification, boolean contentRefresh,
			boolean labelUpdate) {
		Object obj = notification.getNotifier();
		if (obj instanceof MethodPlugin) {
			for (Iterator iter = AssociationHelper.getPluginDirectExtensions(
					((MethodPlugin) obj)).iterator(); iter.hasNext();) {
				Object element = iter.next();
				notifier.fireNotifyChanged(new ViewerNotification(notification,
						element, contentRefresh, labelUpdate));
			}
		}
	}

	public static boolean hasContributor(VariabilityElement e) {
		return hasGeneralizer(e, Collections
				.singleton(VariabilityType.CONTRIBUTES));
	}

	public static boolean hasGeneralizer(VariabilityElement e,
			Collection variabilityTypes) {
		for (Iterator iterator = AssociationHelper.getImmediateVarieties(e)
				.iterator(); iterator.hasNext();) {
			VariabilityElement element = (VariabilityElement) iterator.next();
			if (variabilityTypes.contains(element.getVariabilityType())) {
				return true;
			}
		}
		return false;
	}

	public static Iterator getImmediateVarieties(VariabilityElement elem, VariabilityType type) {
		List selectedVes = new ArrayList();
		List allVes = AssociationHelper.getImmediateVarieties(elem);
		for (int i=0; i<allVes.size(); i++) {
			VariabilityElement ve = (VariabilityElement) allVes.get(i);
			if (type == ve.getVariabilityType()) {
				selectedVes.add(ve);
			}			
		}
		return selectedVes.iterator();
	}
		
	public static Iterator getGeneralizers(VariabilityElement e,
			final VariabilityType type) {
		return new AbstractTreeIterator(e, false) {

			/**
			 * Comment for <code>serialVersionUID</code>
			 */
			private static final long serialVersionUID = 3978145439449298483L;

			protected Iterator getChildren(Object object) {
				List children = new ArrayList();
				for (Iterator iterator = AssociationHelper
						.getImmediateVarieties((VariabilityElement) object)
						.iterator(); iterator.hasNext();) {
					VariabilityElement element = (VariabilityElement) iterator
							.next();
					if ((type == null) || element.getVariabilityType() == type) {
						children.add(element);
					}
				}
				return children.iterator();
			}

		};
	}

	/**
	 * get geenralizers of all types, recursively
	 * 
	 * @param e
	 * @return
	 */
	public static Iterator getGeneralizers(VariabilityElement e) {
		return getGeneralizers(e, null);
	}

	public static Iterator getContributors(VariabilityElement e) {
		return getGeneralizers(e, VariabilityType.CONTRIBUTES);
	}

	public static ItemProviderAdapter getAdapter(MethodPlugin plugin,
			String[] path) {
		IGroupContainer groups = (IGroupContainer) TngAdapterFactory.INSTANCE
				.getNavigatorView_ComposedAdapterFactory().adapt(plugin,
						ITreeItemContentProvider.class);
		int i;
		for (i = 0; i < path.length - 1; i++) {
			groups = (IGroupContainer) groups.getGroupItemProvider(path[i]);
			if (groups == null)
				return null;
		}
		return (ItemProviderAdapter) groups.getGroupItemProvider(path[i]);
	}

	private static void refreshAdapter(MethodPlugin plugin, String[] path,
			Notification msg) {
		if (plugin == null) {
			return;
		}
		ItemProviderAdapter adapter = getAdapter(plugin, path);
		if (adapter != null) {
			adapter.fireNotifyChanged(new ViewerNotification(msg, adapter,
					true, false));
		}
	}

	public static void refreshAdapter(String[] path, Notification notification) {
		EObject eObj = null;
		switch (notification.getEventType()) {
		case Notification.ADD:
			eObj = (EObject) notification.getNewValue();
			break;
		case Notification.ADD_MANY:
			eObj = (EObject) new ArrayList((Collection) notification
					.getNewValue()).get(0);
			break;
		case Notification.REMOVE:
			eObj = (EObject) notification.getOldValue();
			break;
		case Notification.REMOVE_MANY:
			eObj = (EObject) new ArrayList((Collection) notification
					.getOldValue()).get(0);
			break;
		}
		if (eObj != null) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(eObj);
			TngUtil.refreshAdapter(plugin, path, notification);
		}
	}

	public static void refreshUncategorizedTasksItemProvider(
			MethodPlugin plugin, Notification msg) {
		// refresh the uncategorized tasks group
		//

		refreshAdapter(plugin, LibraryEditConstants.UNCATEGORIZED_TASKS_PATH,
				msg);
	}

	public static void refreshDomainUncategorizedWorkProductsItemProvider(
			MethodPlugin plugin, Notification msg) {
		refreshAdapter(plugin,
				LibraryEditConstants.UNCATEGORIZED_DOMAIN_WORKPRODUCTS_PATH,
				msg);
	}

	public static void refreshWorkProductTypeUncategorized(MethodPlugin plugin,
			Notification msg) {
		refreshAdapter(
				plugin,
				LibraryEditConstants.UNCATEGORIZED_WORKPRODUCTTYPE_WORKPRODUCTS_PATH,
				msg);
	}

	public static void refreshUncategorizedWorkProductsItemProviders(
			MethodPlugin plugin, Notification msg) {
		refreshDomainUncategorizedWorkProductsItemProvider(plugin, msg);
		refreshWorkProductTypeUncategorized(plugin, msg);
	}

	public static void refreshUncategorizedRolesItemProvider(
			MethodPlugin plugin, Notification msg) {
		refreshAdapter(plugin, LibraryEditConstants.UNCATEGORIZED_ROLES_PATH,
				msg);
	}

	public static void refreshUncategorizedToolMentorsItemProvider(
			MethodPlugin plugin, Notification msg) {
		refreshAdapter(plugin,
				LibraryEditConstants.UNCATEGORIZED_TOOLMENTORS_PATH, msg);

	}

	public static Object createWrapper(AdapterFactory adapterFactory,
			EObject object, EStructuralFeature feature, Object value, int index) {
		if (FeatureMapUtil.isFeatureMap(feature)) {
			value = new FeatureMapEntryWrapperItemProvider(
					(FeatureMap.Entry) value, object, (EAttribute) feature,
					index, adapterFactory, null);
		} else if (feature instanceof EAttribute) {
			value = new AttributeValueWrapperItemProvider(value, object,
					(EAttribute) feature, index, adapterFactory, null);
		} else if (!((EReference) feature).isContainment()) {
			value = new FeatureValueWrapperItemProvider(feature, value, object,
					adapterFactory);
		}

		return value;
	}

	public static Object getNavigatorParentItemProvider(Guidance guidance) {
		EObject container = guidance.eContainer();
		if (!(container instanceof ContentPackage))
			return null;
		ContentPackageItemProvider itemProvider = (ContentPackageItemProvider) TngUtil
				.getAdapter(container, ContentPackageItemProvider.class);
		return itemProvider != null ? itemProvider.getGuidances() : null;
	}

	public static Object getNavigatorParentItemProvider(WorkProduct object) {
		EObject contentPkg = object.eContainer();
		if (contentPkg == null)
			return null;
		ContentPackageItemProvider itemProvider = (ContentPackageItemProvider) TngUtil
				.getAdapter(contentPkg, ContentPackageItemProvider.class);
		return itemProvider != null ? itemProvider.getWorkProducts() : null;
	}
	
	public static Object getImage(Object object) {
		Object image = TngUtil.getCustomNodeIcon(object);
		if(image != null) {
			return image;
		}
		
		//For user defined type
		if ((object instanceof Practice) && (PracticePropUtil.getPracticePropUtil().isUtdType((Practice)object))) {
			return getImageForUdt((Practice)object);
		}		
		
		Object adapter = null;
		try {
			adapter = umaItemProviderAdapterFactory.adapt(object,
					ITreeItemContentProvider.class);
			if (adapter instanceof IItemLabelProvider) {
				return ((IItemLabelProvider) adapter).getImage(object);
			}
		}
		finally {
			if(adapter != object && adapter instanceof IDisposable) {
				((IDisposable)adapter).dispose();
			}
		}
		return null;
	}
	
	public static ImageDescriptor getImageForUdt(Practice prac) {
		try {
			UserDefinedTypeMeta udtMeta = PracticePropUtil.getPracticePropUtil().getUtdData(prac);
			String imageUrl = udtMeta.getRteNameMap().get(UserDefinedTypeMeta._icon);
			if (imageUrl == null || imageUrl.trim().length() == 0) {
				return null;
			}
			return ImageDescriptor.createFromURL(new URL(imageUrl));
		} catch (Exception e) {
			LibraryEditPlugin.getDefault().getLogger().logError(e);
		}
		
		return null;
	}
	
	private static String getTypeNameForUdt(Practice prac) {
		try {
			UserDefinedTypeMeta udtMeta = PracticePropUtil.getPracticePropUtil().getUtdData(prac);
			return udtMeta.getRteNameMap().get(UserDefinedTypeMeta._typeName);
		} catch (Exception e) {
			LibraryEditPlugin.getDefault().getLogger().logError(e);
		}
		
		return null;
	}

	public static Object getColumnImage(Object object, String colName) {
		// if(colName == IBSItemProvider.COL_TYPE)
		// if(colName == IBSItemProvider.COL_NAME)
		if (colName == IBSItemProvider.COL_PRESENTATION_NAME) {
			return getImage(object);
		}
		return null;
	}

	/**
	 * Move element up withing the parent
	 * 
	 * @param activity
	 * @param elementObj
	 * @param eClasses
	 * @param actionMgr
	 */
	public static void moveUp(Activity activity, Object elementObj,
			Collection eClasses, IActionManager actionMgr) {
		MoveUpCommand cmd = new MoveUpCommand(activity, elementObj, eClasses);
		actionMgr.execute(cmd);
	}

	/**
	 * Move element down within the parent
	 * 
	 * @param activity
	 * @param elementObj
	 * @param eClasses
	 * @param actionMgr
	 */
	public static void moveDown(Activity activity, Object elementObj,
			Collection eClasses, IActionManager actionMgr) {
		MoveDownCommand cmd = new MoveDownCommand(activity, elementObj,
				eClasses);
		actionMgr.execute(cmd);
	}

	public static CustomCategory createRootCustomCategory(
			ContentPackage customCategoryPkg) {
		// create root custom category
		//
		CustomCategory rootCustomCategory = UmaFactory.eINSTANCE
				.createCustomCategory();
		rootCustomCategory.setName(LibraryEditPlugin.INSTANCE
				.getString("_UI_Custom_Categories_group")); //$NON-NLS-1$
		ContentPackage hiddenPkg = UmaUtil.findContentPackage(customCategoryPkg
				.getChildPackages(), ModelStructure.HIDDEN_PACKAGE_NAME);
		if (hiddenPkg == null) {
			// create hidden package to store the root custom category
			//
			hiddenPkg = UmaFactory.eINSTANCE.createContentPackage();
			hiddenPkg.setName(ModelStructure.HIDDEN_PACKAGE_NAME);
			customCategoryPkg.getChildPackages().add(hiddenPkg);
		}
		hiddenPkg.getContentElements().add(rootCustomCategory);

		return rootCustomCategory;
	}

	public static Set<CustomCategory> getAllCustomCategories(MethodPlugin plugin) {
		Set<CustomCategory> set = new HashSet<CustomCategory>();
		ContentPackage customCategoryPkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);
		if (customCategoryPkg != null) {
			for (ContentElement element : customCategoryPkg
					.getContentElements()) {
				if (element instanceof CustomCategory) {
					set.add((CustomCategory) element);
				}
			}
		}
		return set;
	}
	
	public static CustomCategory getRootCustomCategory(MethodPlugin plugin) {
		ContentPackage customCategoryPkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);
		if (customCategoryPkg == null)
			return null;
		ContentPackage hiddenPkg = UmaUtil.findContentPackage(customCategoryPkg
				.getChildPackages(), ModelStructure.HIDDEN_PACKAGE_NAME);
		if (hiddenPkg != null && !hiddenPkg.getContentElements().isEmpty()) {
			return (CustomCategory) hiddenPkg.getContentElements().get(0);
		}
		CustomCategory root = createRootCustomCategory(customCategoryPkg);
		// code for backward compatibility: add all the custom categories under
		// customCategoryPkg
		// to the content element reference list of the root custom category so
		// they can be visible
		// in the new UI
		//
		for (Iterator iter = customCategoryPkg.getContentElements().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof CustomCategory) {
				root.getCategorizedElements().add((DescribableElement) element);
			}
		}
		return root;
	}

	public static boolean isRootCustomCategory(CustomCategory category) {
		EObject pkg = category.eContainer();
		if (pkg instanceof ContentPackage
				&& ModelStructure.HIDDEN_PACKAGE_NAME
						.equals(((ContentPackage) pkg).getName())) {
			return true;
		}
		return false;
	}

	public static boolean isRootCutomCategoryPackage(MethodPackage pkg) {
		if ( !(pkg instanceof ContentPackage) ||
				!ModelStructure.HIDDEN_PACKAGE_NAME
						.equals(pkg.getName()) ) {
			return false;
		}
		
		// check the plugin and make sure it's the object, TODO
		
		return true;
	}
	
	/**
	 * Saves resource of the given element's container if this has been modified
	 * 
	 * @param element
	 */
	public static void saveContainerResource(EObject element,
			IFileBasedLibraryPersister persister) {
		// save container's resource
		if (element.eContainer() != null) {
			Resource resource = element.eContainer().eResource();
			if (resource != null && resource.isModified()) {
				try {
					persister.save(resource);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

	}

	public static ContentCategory findContributor(ContentPackage categoryPkg,
			ContentCategory baseCategory) {
		for (Iterator iter = categoryPkg.getContentElements().iterator(); iter
				.hasNext();) {
			ContentCategory cat = (ContentCategory) iter.next();
			if (cat.getVariabilityBasedOnElement() == baseCategory) {
				return cat;
			}
		}
		return null;
	}

	public static boolean isEmpty(ContentCategory category) {
		if (!category.getConceptsAndPapers().isEmpty()
				|| !category.getSupportingMaterials().isEmpty())
			return false;

		if (category instanceof Discipline) {
			return ((Discipline) category).getTasks().isEmpty();
		} else if (category instanceof Domain) {
			return ((Domain) category).getWorkProducts().isEmpty();
		} else if (category instanceof RoleSet) {
			return ((RoleSet) category).getRoles().isEmpty();
		} else if (category instanceof Tool) {
			return ((Tool) category).getToolMentors().isEmpty();
		} else if (category instanceof WorkProductType) {
			return ((WorkProductType) category).getWorkProducts().isEmpty();
		} else if (category instanceof CustomCategory) {
			CustomCategory userDefinedCategory = ((CustomCategory) category);
			return userDefinedCategory.getCategorizedElements().isEmpty()
			// && userDefinedCategory.getSubCategories().isEmpty()
			;
		}

		throw new IllegalArgumentException("Unknown category: " + category); //$NON-NLS-1$
	}

	/**
	 * @param order
	 */
	private static void addToPackage(WorkOrder order, BreakdownElement e) {
		EObject container = e.eContainer();
		if(container != null) {
			((ProcessPackage) container).getProcessElements().add(order);
		}
	}

	/**
	 * @param order
	 */
	private static void removeFromPackage(WorkOrder order, BreakdownElement e) {
		EObject container = e.eContainer();
		if(container instanceof ProcessPackage) {
			((ProcessPackage) container).getProcessElements().remove(order);
		}
	}

	public static boolean handlePredecessorListChange(
			ItemProviderAdapter adapter, Notification notification) {
		if (notification.getNotifier() instanceof WorkBreakdownElement) {
			switch (notification.getFeatureID(WorkBreakdownElement.class)) {
			case UmaPackage.ACTIVITY__LINK_TO_PREDECESSOR:
				switch (notification.getEventType()) {
				case Notification.ADD:
					addToPackage((WorkOrder) notification.getNewValue(),
							(BreakdownElement) notification.getNotifier());
					break;
				case Notification.ADD_MANY:
					for (Iterator iter = ((Collection) notification
							.getNewValue()).iterator(); iter.hasNext();) {
						addToPackage((WorkOrder) iter.next(),
								(BreakdownElement) notification.getNotifier());
					}
					break;
				case Notification.REMOVE:
					removeFromPackage((WorkOrder) notification.getOldValue(),
							(BreakdownElement) notification.getNotifier());
					break;
				case Notification.REMOVE_MANY:
					for (Iterator iter = ((Collection) notification
							.getOldValue()).iterator(); iter.hasNext();) {
						removeFromPackage((WorkOrder) iter.next(),
								(BreakdownElement) notification.getNotifier());
					}
					break;

				}

				adapter.fireNotifyChanged(new ViewerNotification(notification,
						notification.getNotifier(), false, true));
				return true;
			}
		}
		return false;
	}

	/**
	 * return all the global packages for the method plugin
	 * 
	 * @param plugin
	 *            MethodPlugin
	 * @return List a list of global packages
	 */
	public static List<ContentPackage> getGlobalPackages(MethodPlugin plugin) {
		ArrayList<ContentPackage> packages = new ArrayList<ContentPackage>();
		String[][] categoryPaths = ModelStructure.DEFAULT.getCategoryPaths();
		for (int i = 0; i < categoryPaths.length; i++) {
			String[] path = categoryPaths[i];
			ContentPackage categoryPkg = UmaUtil.findContentPackage(plugin,
					path);
			if (categoryPkg != null) {
				packages.add(categoryPkg);
			}
		}

		return packages;
	}

	
	/**
	 * return all the content category packages for the method plugin. 
	 * 
	 * @param plugin
	 *            MethodPlugin
	 * @return List a list of global packages
	 */
	public static List<ContentPackage> getContentCategoryPackages(MethodPlugin plugin) {
		return getGlobalPackages(plugin);
	}
	
	
	/**
	 * return all the system defined packages for the method plugin
	 * 
	 * @param plugin
	 *            MethodPlugin
	 * @return List a list of all system packages
	 */
	public static List getAllSystemPackages(MethodPlugin plugin) {
		ArrayList packages = new ArrayList();
		String[][] paths = ModelStructure.DEFAULT.getAllSystemPaths();
		for (int i = 0; i < paths.length; i++) {
			String[] path = paths[i];
			MethodPackage pkg = UmaUtil.findMethodPackage(plugin, path);
			if (pkg != null && !packages.contains(pkg)) {
				packages.add(pkg);
				EObject o = pkg.eContainer();
				while ((o instanceof MethodPackage) && !packages.contains(o)) {
					packages.add(o);
					o = o.eContainer();
				}
			}
		}

		// also add the hidden costom category package
		ContentPackage customCategoryPkg = UmaUtil.findContentPackage(plugin,
				ModelStructure.DEFAULT.customCategoryPath);
		if (customCategoryPkg != null) {
			ContentPackage hiddenPkg = UmaUtil.findContentPackage(
					customCategoryPkg.getChildPackages(),
					ModelStructure.HIDDEN_PACKAGE_NAME);
			if (hiddenPkg != null) {
				packages.add(hiddenPkg);
			}
		}

		return packages;
	}

	public static boolean isPredefined(MethodElement e) {
		if (e instanceof CustomCategory
				&& isRootCustomCategory((CustomCategory) e))
			return true;
		String path = ModelStructure
				.toFilePath(Misc.getPathRelativeToPlugin(e));
		for (Iterator iter = ModelStructure.ALL_PREDEFINED_PATHS.iterator(); iter
				.hasNext();) {
			String predefinePath = (String) iter.next();
			if (predefinePath.startsWith(path)) {
				return true;
			}
		}
		return false;
	}


	public static MethodPackage getMethodPackage(EObject e) {
		for (; !(e instanceof MethodPackage) && e != null; e = e.eContainer())
			;
		return (MethodPackage) e;
	}
	
	public static MethodPackage getParentMethodPackage(EObject e) {
		EObject eobj = e;
		while(eobj != null) {
			eobj = eobj.eContainer();
			if (eobj == null ) {
				return null;
			} else if (eobj instanceof MethodPackage) {
				return (MethodPackage) eobj;
			}
		}
		return  null;
	}

	/**
	 * validate the configuration by forcing to select the global packages of
	 * the selected method plugins, this is needed for configuration exporting.
	 * If global packages are missing, the exported configuration is not valid
	 * 
	 * @param actionMgr if not null, will use the given IActionManager to change the configuration, otherwise configuration will be changed directly
	 * @param plugin
	 */
	public static void validateMethodConfiguration(IActionManager actionMgr, MethodConfiguration config) {
		List plugins = new ArrayList(config.getMethodPluginSelection());
		List pkgSels = new ArrayList(config.getMethodPackageSelection());
		List<MethodPlugin> pluginsToAdd = new ArrayList<MethodPlugin>();
		List<MethodPackage> packagesToAdd = new ArrayList<MethodPackage>();

		// make sure all required packages are selected.
		// if a package is selected, all the parent packages must be selected.
		for ( Iterator it = new ArrayList(pkgSels).iterator(); it.hasNext(); ) {
			MethodPackage pkg = (MethodPackage)it.next();
			EObject c = pkg.eContainer();
			while ( ((c instanceof MethodPackage) || (c instanceof MethodPlugin)) 
					&& !pkgSels.contains(c) && !plugins.contains(c) ) {
				if (c instanceof MethodPlugin) {
					plugins.add(c);
					pluginsToAdd.add((MethodPlugin)c);
				} else {
					pkgSels.add(c);
					packagesToAdd.add((MethodPackage)c);
				}
				
				c = c.eContainer();
			}	
			
			// if the package is a ProcessComponent, select all the child packages
			if ( pkg instanceof ProcessComponent ) {
				List oldPkgSels = new ArrayList(pkgSels);
				getAllChildPackages(pkg, pkgSels);
				pkgSels.removeAll(oldPkgSels);
				packagesToAdd.addAll(pkgSels);
			}
		}
		ConfigurationUtil.addCollToMethodPluginList(actionMgr, config, pluginsToAdd);
		ConfigurationUtil.addCollToMethodPackageList(actionMgr, config, packagesToAdd);
		pkgSels = new ArrayList(config.getMethodPackageSelection());

		// make sure all system packages are selected
		List<MethodPackage> sysPackagesToAdd = new ArrayList<MethodPackage>();
		for (Iterator itp = plugins.iterator(); itp.hasNext();) {
			MethodPlugin plugin = (MethodPlugin) itp.next();
			List pkgs = TngUtil.getAllSystemPackages(plugin);
			for (Iterator it = pkgs.iterator(); it.hasNext();) {
				Object pkg = it.next();
				if (!pkgSels.contains(pkg) && pkg instanceof MethodPackage) {
					pkgSels.add(pkg);
					sysPackagesToAdd.add((MethodPackage)pkg);
				}
			}
		}
		ConfigurationUtil.addCollToMethodPackageList(actionMgr, config, sysPackagesToAdd);
	}
	
	/**
	 * get all child packages of the given MethodPackage and add to the list
	 * @param pkg MethodPackage
	 * @param result List the packages found
	 */
	private static void getAllChildPackages(MethodPackage pkg, List result) {
		List pkgs = pkg.getChildPackages();
		
		// only add unique items
		for ( Iterator it = pkgs.iterator(); it.hasNext(); ) {
			Object p = it.next();
			if ( !result.contains(p) ) {
				result.add(p);
			}
		}

		for (Iterator it = pkgs.iterator(); it.hasNext();) {
			getAllChildPackages((MethodPackage) it.next(), result);
		}
	}
	
	/**
	 * Adds the given object's method package and plugin to the given
	 * configuration if they are not in the configuration yet.
	 * 
	 * @param config
	 * @param object
	 */
	public static boolean addTo(MethodConfiguration config, EObject object,
			Set addedObjects) {
		MethodPackage pkg = getMethodPackage(object);
		if (pkg != null) {
			if (!config.getMethodPackageSelection().contains(pkg)) {
				config.getMethodPackageSelection().add(pkg);
				addedObjects.add(pkg);
				MethodPlugin plugin = UmaUtil.getMethodPlugin(pkg);
				
				// 150552 - Processes: If configuration is updated by itself due to actions like CP extendiing or deep copy, 
				// there is a refresh issue.
				// missing the "!" here!
				if (!config.getMethodPluginSelection().contains(plugin)) {
					config.getMethodPluginSelection().add(plugin);
					addedObjects.add(plugin);
				
					// need to validate the method configuration to make sure all related system packages are selected.
					// otherwise the configuration explorer will not work
					// 150552 - Processes: If configuration is updated by itself due to actions like CP extendiing or deep copy, there is a refresh issue.		
					validateMethodConfiguration(null, config);
				}
				return true;
			}
		}
		return false;
	}

	public static boolean addToConfiguration(MethodConfiguration config,
			EObject object, Set addedObjects) {
		int size = addedObjects.size();
		addTo(config, object, addedObjects);

		if (object instanceof VariabilityElement) {
			// add all the base elements if there is any
			for (VariabilityElement c = ((VariabilityElement) object)
					.getVariabilityBasedOnElement(); c != null; c = (VariabilityElement) c
					.getVariabilityBasedOnElement()) {
				addTo(config, c, addedObjects);
			}
		}

		return addedObjects.size() > size;
	}

	/**
	 * 
	 * @param eObj
	 * @param context
	 *            the <code>org.eclipse.swt.widgets.Shell</code> that is to be
	 *            used to parent any dialogs with the user, or <code>null</code>
	 *            if there is no UI context (declared as an <code>Object</code>
	 *            to avoid any direct references on the SWT component)
	 * @return
	 */
	public static IStatus checkEdit(EObject eObj, Object context) {
		if (((InternalEObject) eObj).eProxyURI() != null) {
			// this is a unresolved proxy, disallow editing it
			//
			EObject proxy = eObj;
			String uri = ((InternalEObject) proxy).eProxyURI().toString();
			org.eclipse.emf.common.util.URI containerURI = proxy.eContainer() != null ? proxy
					.eContainer().eResource().getURI()
					: null;
			String location;
			if (containerURI != null) {
				location = containerURI != null && containerURI.isFile() ? containerURI.toFileString()
						: ""; //$NON-NLS-1$
				if (location.length() != 0) {
					location = MessageFormat.format(
							" in ''{0}''", new Object[] { location }); //$NON-NLS-1$
				}
			} else {
				location = ""; //$NON-NLS-1$
			}
			String msg = MessageFormat.format(LibraryEditResources.unresolvedObjectError_reason
					, new Object[] { proxy.eClass().getName(), uri, location });
			return new Status(IStatus.ERROR, LibraryEditPlugin.INSTANCE
					.getSymbolicName(), 0, msg, null);
		}				
		
		IAccessController ac = Services.getAccessController();
		if(ac == null) {
			return Status.OK_STATUS;
		}
		return ac.checkModify(Collections.singletonList(eObj), context);
	}
	
	/**
	 * Check the given element for modifiable
	 * 
	 * @param e
	 * @throws MessageException if the element cannot be modified
	 */
	public static void checkModify(EObject e) {
		IAccessController ac = Services.getAccessController();
		if(ac != null) {
			IStatus status = ac.checkModify(Collections.singletonList(e), null);
			if (!status.isOK()) {
				String msg = UmaUtil.getMessage(status);
				if (msg == null) {
					Object obj;
					if(e.eResource().getURI().isFile()) {
						obj = e.eResource().getURI().toFileString();
					}
					else {
						obj = e; 
					}
					msg = MessageFormat.format(UmaResources.err_cannotModify0,
							new Object[] { obj });
				}
				throw new MessageException(msg);
			}
		}
	}

	public static String getMessage(IStatus status) {
		String msg = status.getMessage();
		if (status.isMultiStatus()) {
			StringBuffer strBuf = new StringBuffer(msg);
			IStatus statuses[] = status.getChildren();
			for (int i = 0; i < statuses.length; i++) {
				strBuf.append('\n').append(statuses[i].getMessage());
			}
			msg = strBuf.toString();
		}
		if (msg == null || msg.length() == 0) {
			msg = LibraryEditResources.util_tngutil_cannot_edit_resource; 
		}
		return msg;
	}

	public static boolean isContributor(VariabilityElement e) {
		return e.getVariabilityBasedOnElement() != null
		&& (e.getVariabilityType() == VariabilityType.CONTRIBUTES);
	}
	
	public static boolean isReplacer(VariabilityElement e) {
		return e.getVariabilityBasedOnElement() != null
		&& (e.getVariabilityType() == VariabilityType.REPLACES);
	}
	
	public static boolean isContributorOrReplacer(VariabilityElement e) {
		VariabilityElement base = e.getVariabilityBasedOnElement();
		VariabilityType type = e.getVariabilityType();
		return base != null && (type == VariabilityType.CONTRIBUTES || type == VariabilityType.REPLACES);
	}

	public static boolean isGeneralizer(Object obj, Collection types) {
		if (!(obj instanceof VariabilityElement))
			return false;
		VariabilityElement ve = (VariabilityElement) obj;
		if (ve.getVariabilityBasedOnElement() == null)
			return false;
		if (types == null)
			return true;
		return types.contains(ve.getVariabilityType());
	}

	public static String getTypeText(String typeKey) {
		try {
			return UmaEditPlugin.INSTANCE.getString("_UI_" + typeKey + "_type"); //$NON-NLS-1$ //$NON-NLS-2$
		} catch (MissingResourceException e) {
		}
		return UmaEditPlugin.INSTANCE.getString("_UI_Unknown_type"); //$NON-NLS-1$		
	}

	/**
	 * Looks up the user friendly type name for a Method element.
	 */
	public static String getTypeText(EObject element) {
		//For user defined type
		if ((element instanceof Practice) && (PracticePropUtil.getPracticePropUtil().isUtdType((Practice)element))) {
			return getTypeNameForUdt((Practice)element);
		}		
		
		return getTypeText(element.eClass());
	}
	
	/**
	 * Looks up the user-friendly type name for a given type.
	 * 
	 * @param type
	 * @return
	 */
	public static String getTypeText(EClass type) {
		return getTypeText(type.getName());
	}

	/**
	 * This looks up the name of the specified feature.
	 */
	public static String getFeatureText(Object feature) {
		if (feature instanceof EStructuralFeature) {
			return getFeatureText((EStructuralFeature) feature);
		} else {
			return "Unknown"; //$NON-NLS-1$
		}
	}

	/**
	 * Checks if the given object is locked. An object is considered locked if
	 * its MethodPlugin has the attribute userChangeable set to false. The
	 * 'locked' status of an object is independent from 'read-only' status of
	 * its resource file.
	 * 
	 * @param object
	 * @return
	 */
	public static boolean isLocked(EObject object) {
		MethodPlugin plugin = UmaUtil.getMethodPlugin(object);
		if (plugin == null)
			return false;
		return !plugin.getUserChangeable().booleanValue();
	}

	public static boolean checkExist(Collection wrappers, Object e) {
		for (Iterator iterator = wrappers.iterator(); iterator.hasNext();) {
			Object element = unwrap(iterator.next());
			if (element == e) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Gets the index of element or its wrapper in the given list
	 * @param list a mixed list of element and wrapper
	 * @param e
	 * @return -1 if the element or its wrapper could not be found in the list
	 */
	public static int getIndexOf(List list, Object e) {
		int size = list.size();
		for (int i = 0; i < size; i++) {
			Object element = unwrap(list.get(i));
			if(element == e) {
				return i;
			}
		}
		return -1;
	}

	public static EStructuralFeature getContainingFeature(Object object,
			AdapterFactory adapterFactory) {
		ITreeItemContentProvider adapter = (ITreeItemContentProvider) adapterFactory
				.adapt(object, ITreeItemContentProvider.class);
		if (adapter == null)
			return null;
		Object parent = adapter.getParent(object);
		if (!(parent instanceof EObject))
			return null;
		adapter = (ITreeItemContentProvider) adapterFactory.adapt(parent,
				ITreeItemContentProvider.class);
		if (adapter instanceof MethodElementItemProvider) {
			EObject parentEObj = (EObject) parent;
			for (Iterator iter = ((MethodElementItemProvider) adapter)
					.getChildrenFeatures(parent).iterator(); iter.hasNext();) {
				EStructuralFeature f = (EStructuralFeature) iter.next();
				if (f.isMany()) {
					if (((Collection) parentEObj.eGet(f)).contains(object)) {
						return f;
					}
				} else {
					if (parentEObj.eGet(f) == object) {
						return f;
					}
				}
			}
		}
		return null;
	}
	
	/**
	 * Looks up the user-friendly name for a given feature.
	 * 
	 * @param feature
	 * @return
	 */
	public static String getFeatureText(EStructuralFeature feature) {
		switch (feature.getFeatureID()) {
		// case UmaPackage.TASK_DESCRIPTOR__PERFORMED_PRIMARILY_BY:
		// return "Primary Performer";
		// case UmaPackage.TASK_DESCRIPTOR__ADDITIONALLY_PERFORMED_BY:
		// return "Secondary Performer";
		case UmaPackage.TASK_DESCRIPTOR__ASSISTED_BY:
			return LibraryEditResources.assists_text; 
		}

		String featureKey;
		if (feature instanceof EStructuralFeature) {
			EStructuralFeature eFeature = (EStructuralFeature) feature;
			featureKey = eFeature.getEContainingClass().getName()
					+ "_" + eFeature.getName(); //$NON-NLS-1$
		} else {
			featureKey = LibraryEditResources.unknown_text; 
		}
		return UmaEditPlugin.INSTANCE
				.getString("_UI_" + featureKey + "_feature"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * get the library root path for the given element, assuming the element and
	 * it's parents are loaded
	 * 
	 * @param element
	 * @return File the root path of the library
	 */
	public static File getLibraryRootPath(EObject element) {
		EObject parent = element;
		while ((parent != null) && !(parent instanceof MethodLibrary)) {
			parent = parent.eContainer();
		}

		if (parent != null && parent.eResource() != null) {
			org.eclipse.emf.common.util.URI uri = parent.eResource().getURI();
			String path = uri.toFileString();
			File f = new File(path);
			return f.getParentFile();
		}
		return null;
	}

	/**
	 * get the full path URI by appending the relative path URI to the object's
	 * library path
	 * 
	 * @param o
	 *            EObject the object to find the MethodLibrary, can be any
	 *            object in the library
	 * @param uri
	 *            The uri to be fixed
	 * @return URI the full path uri
	 */
	public static URI getFullPathURI(EObject o, URI uri) {
		if (uri == null) {
			return uri;
		}

		// try if this is a valid URL or not
		try {
			URL url = uri.toURL();
			if (url != null) {
				return uri;
			}
		} catch (Exception ex) {
			; // not a valid url, maybe a relative path
		}

		// need to get the element's resource path
		File f = getLibraryRootPath(o);
		if (f != null) {
			return new File(f, NetUtil.decodedFileUrl(uri.toString())).toURI();
		}

		return uri;
	}
	
	/**
	 * 
	 * @param object
	 * @return custom node icon or null if the given object does not have one
	 */
	public static Object getCustomNodeIcon(Object object) {
		if (object instanceof DescribableElement) {
			if (((DescribableElement) object).getNodeicon() != null) {
				URI imgUri = TngUtil.getFullPathofNodeorShapeIconURI(
						(DescribableElement) object,
						((DescribableElement) object).getNodeicon());
				Object image = LibraryEditPlugin.INSTANCE
						.getSharedImage(imgUri);
				if (image != null)
					return image;
			}
		}
		return null;
	}

	
	/**
	 * To get the node icon/shape icon full path URI by appending the relative path URI to the object's
	 * library path
	 * 
	 * @param o
	 *            EObject the object to find the MethodLibrary, can be any
	 *            object in the library
	 * @param uri
	 *            The uri to be fixed
	 * @return URI the full path uri
	 */
	//FIXME: make storage independent
	public static URI getFullPathofNodeorShapeIconURI(EObject o, URI uri) {
		if (uri == null) {
			return uri;
		}

		// try if this is a valid URL or not
		try {
			URL url = uri.toURL();
			if (url != null) {
				return uri;
			}
		} catch (Exception ex) {
			; // not a valid url, maybe a relative path
		}

		// need to get the element's resource path
		MethodPlugin plugin = UmaUtil.getMethodPlugin(o);
		if (plugin != null && UmaUtil.hasDirectResource(plugin)) {
			File f = getLibraryRootPath(o);
			String path = uri.getPath();
			if (f != null && path.indexOf(plugin.getName() + "/") == 0) { //$NON-NLS-1$
				return new File(f, NetUtil.decodedFileUrl(uri.toString()))
						.toURI();
			}
			else {
				IFileBasedLibraryPersister persister = (IFileBasedLibraryPersister) Services
						.getLibraryPersister(Services.XMI_PERSISTENCE_TYPE);
				File pluginDir = persister.getFile(plugin.eResource())
						.getParentFile();

				return new File(pluginDir, NetUtil.decodedFileUrl(uri
						.toString())).toURI();

			}
		}
		return null;
	}
	/**
	 * @param e
	 * @return
	 */
	public static String toStackTraceString(Throwable e) {
		StringWriter strWriter = new StringWriter();
		e.printStackTrace(new PrintWriter(strWriter));
		return strWriter.toString();
	}
	
	public static String getLabelWithPath(Object object) {
		if (object instanceof BreakdownElement) {
			return ProcessUtil.getLabelWithPath((BreakdownElement) object);
		}

		if (object instanceof ContentDescription) {
			return getLabelWithPath(((ContentDescription) object).eContainer());
		}

		if(object instanceof MethodElement) {
			MethodElement me = (MethodElement) object;
			Collection<NamedElement> itemPath = Misc.getObjectTreeRelativeToPlugin(me);
			StringBuffer path = new StringBuffer(getLabel(object, me.getGuid()));
			if (MethodElementUtil.getMethodModel(object) != null) {
				path
				.append(", ").append(MethodElementUtil.getMethodModel(object).getName()); //$NON-NLS-1$
				for (Iterator<NamedElement> iter = itemPath.iterator();iter.hasNext();) {
					NamedElement e = iter.next();
					String s = String.valueOf(e.getName());

					if (ModelStructure.CORE_CONTENT_PACAKGE_NAME.equals(s) || ModelStructure.CONTENT_PACKAGE_NAME.equalsIgnoreCase(s)
							|| (((NamedElement) object).equals(e))) {
					} else {
						path.append('/').append(s);
					}
				}
			}
			return path.toString();
		}
		return ""; //$NON-NLS-1$
	}

	public static EObject getOwner(Command command) {
		command = TngUtil.unwrap(command);
		EObject owner = null;
		if (command instanceof AddCommand) {
			owner = ((AddCommand) command).getOwner();
		} else if (command instanceof RemoveCommand) {
			owner = ((RemoveCommand) command).getOwner();
		} else if (command instanceof SetCommand) {
			owner = ((SetCommand) command).getOwner();
		} else if (command instanceof MoveCommand) {
			owner = ((MoveCommand) command).getOwner();
		} else if (command instanceof PasteFromClipboardCommand) {
			Object o = ((PasteFromClipboardCommand) command).getOwner();
			if (o instanceof EObject) {
				owner = (EObject) o;
			}
		}
		return owner;
	}
	
	public static Set<Resource> getModifiedResources(Command cmd) {
		Set<Resource> modifiedResources = new HashSet<Resource>();
		collectModifiedResources(cmd, modifiedResources);
		return modifiedResources;
	}
	
	public static void collectModifiedResources(Command command, Set<Resource> modifiedResources) {
		if (command instanceof IResourceAwareCommand) {
			modifiedResources.addAll(((IResourceAwareCommand) command)
					.getModifiedResources());
		} 
		else if(command instanceof CompoundCommand){
			List commandList = ((CompoundCommand)command).getCommandList();
			for (Iterator iter = commandList.iterator(); iter.hasNext();) {
				collectModifiedResources((Command) iter.next(), modifiedResources);				
			}
		}
		else {
			EObject modified = TngUtil.getOwner(command);
			if(modified != null) {
				Resource resource = modified.eResource();
				if(resource != null) {
					modifiedResources.add(resource);
				}
			}
		}
	}

	public static List convertGuidanceAttachmentsToList(String attachmentString) {
		ArrayList attachments = new ArrayList();
		if (attachmentString == null)
			attachmentString = ""; //$NON-NLS-1$
		String files[] = attachmentString
				.split(GUIDANCE_FILESTRING_SEPARATOR_SPLITTER);
		for (int i = 0; i < files.length; i++) {
			if (files[i].trim().length() > 0)
				attachments.add(files[i]);
		}
		return attachments;
	}

	public static String convertGuidanceAttachmentsToString(List attachmentList) {
		String attachmentString = ""; //$NON-NLS-1$
		int i = 0;
		for (Iterator iter = attachmentList.iterator(); iter.hasNext();) {
			String attachment = (String) iter.next();
			if (i++ > 0)
				attachmentString = attachmentString
						.concat(GUIDANCE_FILESTRING_SEPARATOR);
			attachmentString = attachmentString.concat(attachment);
		}
		return attachmentString;
	}
	
	public static List<String> convertStringsToList(String string) {
		ArrayList<String> strList = new ArrayList<String>();
		if (string == null)
			string = ""; //$NON-NLS-1$
		String strings[] = string
				.split(COMMA_SEPARATOR_SPLITTER);
		for (int i = 0; i < strings.length; i++) {
			if (strings[i].trim().length() > 0)
				strList.add(strings[i].trim());
		}
		return strList;
	}
	
	public static List<String> convertStringsToList(String string, String seperator) {
		ArrayList<String> strList = new ArrayList<String>();
		if (string == null)
			string = ""; //$NON-NLS-1$
		String strings[] = string
				.split(seperator);
		for (int i = 0; i < strings.length; i++) {
			if (strings[i].trim().length() > 0)
				strList.add(strings[i].trim());
		}
		return strList;
	}

	public static String convertListToString(List<String> strList) {
		String string = ""; //$NON-NLS-1$
		int i = 0;
		if (strList != null) {
			for (String aString: strList) {
				if (i++ > 0)
					string = string
							.concat(COMMA_SEPARATOR);
				string = string.concat(aString);
			}
		}
		return string;
	}

	
	/**
	 * 
	 * @param e
	 * @return true iff the MethodElement is allowed an attachment.  Currently, only
	 * Example, ResuableAsset, Template,  Whitepaper are allowed attachments
	 */
	public static boolean isAllowedAttachments(MethodElement e) {
		if (e == null) {
			return false;
		}
		if (e instanceof Example)
			return true;
		if (e instanceof ReusableAsset)
			return true;
		if (e instanceof Template)
			return true;
		if (e instanceof Whitepaper)
			return true;

		return false;
	}

	/**
	 * Checks if the given <code>elements</code> contains <code>e</code> or has a wrapper of <code>e</code>
	 * 
	 * @param elements
	 * @param e
	 * @return
	 */
	public static boolean contains(Collection elements, Object e) {
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if(element == e || e == unwrap(element)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Checks if the given CustomCategory is an ancestor of the given DescibableElement
	 * 
	 * @param cc
	 * @param e
	 * @return
	 * @deprecated moved to {@link DependencyChecker#isAncessorOf(CustomCategory, DescribableElement)}
	 */
	public static boolean isAncessorOf(CustomCategory cc, DescribableElement e) {
		return DependencyChecker.isAncessorOf(cc, e);
	}
	
	public static void refreshParentIfNameChanged(Notification notification, ItemProviderAdapter adapter) {
		if(notification.getNotifier() instanceof ContentElement) {
			switch (notification.getFeatureID(DescribableElement.class)) {
			case UmaPackage.DESCRIBABLE_ELEMENT__NAME:
				if(PresentationContext.INSTANCE.isShowPresentationNames()) {
					return;
				}
				break;
			case UmaPackage.DESCRIBABLE_ELEMENT__PRESENTATION_NAME:
				if(!PresentationContext.INSTANCE.isShowPresentationNames()) {
					return;
				}
				break;
			default:
				return;
			}
		}
		else if ( notification.getFeatureID(NamedElement.class) != UmaPackage.NAMED_ELEMENT__NAME ){
			return;
		}
		// name change might change the element's order in the sorted list
		// refresh the parent content to resort the element list
		//
		adapter.fireNotifyChanged(new ViewerNotification(notification, adapter.getParent(notification.getNotifier()), true, false));
	}	
	
	/**
	 * Checks if the given element <code>e</code> is a contributor of the given <code>base</code>
	 * @param base
	 * @param e
	 * @return
	 */
	public static boolean isContributorOf(Object base, VariabilityElement e) {
		for(VariabilityElement ve = (VariabilityElement) e;
		ve != null && ve.getVariabilityType() == VariabilityType.CONTRIBUTES && ve.getVariabilityBasedOnElement() != null;
		ve = ve.getVariabilityBasedOnElement()) {
			if(ve.getVariabilityBasedOnElement() == base) {
				return true;
			}
		}
		return false;
	}

//	/**
//	 * Checks if the given parent contains the given child, either via containment or contribution
//	 * @param parent
//	 * @param child
//	 * @return
//	 */
//	public static boolean isContainedBy(Artifact parent, Artifact child) {
//		EObject container = child.eContainer();
//		if(container instanceof Artifact) {
//			Artifact currentParent = (Artifact)container;
//			if(container == parent || isContributorOf(parent, currentParent)) {
//				return true;
//			}
//			Iterator iter = new AbstractTreeIterator(parent, false) {
//				
//				private static final long serialVersionUID = 1L;
//				
//				protected Iterator getChildren(Object object) {
//					return ((Artifact)object).getContainedArtifacts().iterator();
//				}
//				
//			};
//			while(iter.hasNext()) {
//				Object o = iter.next();
//				if(o == currentParent || isContributorOf(o, currentParent)) {
//					return true;
//				}
//			}
//			return false;
//		}
//		else {
//			return UmaUtil.isContainedBy(child, parent);
//		}
//	}
	
	public static void getConfigurationsToUpdate(MethodPackage parent, MethodPackage pkg, Collection configsToUpdate) {
		Object configs = ((MultiResourceEObject) parent)
		.getOppositeFeatureValue(AssociationHelper.MethodPackage_MethodConfigurations);
		if (configs instanceof List) {
			for (Iterator itconfig = ((List) configs).iterator(); itconfig
			.hasNext();) {
				MethodConfiguration config = (MethodConfiguration) itconfig
				.next();
				List pkgs = config.getMethodPackageSelection();
				if (!pkgs.contains(pkg)) {
					configsToUpdate.add(config);
				}
			}
		}
	}
	
	/**
	 * Checks if the given object can be estimated
	 * 
	 * @param o
	 * @return
	 */
	public static boolean canEstimate(Object o) {
		return o instanceof Task || o instanceof WorkBreakdownElement;
	}
	
	
	public static void debugShowAll() {
		ILibraryInspector inspector = getLibraryInspector();
		if (inspector != null) {
			inspector.showAllContents();
		}
	}
	
	public static void debugShowAll(MethodLibrary lib) {
		ILibraryInspector inspector = getLibraryInspector();
		if (inspector != null) {
			inspector.showAllContents(lib);
		}
	}
	
	//Used for debug only
	public static ILibraryInspector getLibraryInspector() {
		return (ILibraryInspector) ExtensionManager.getExtension("org.eclipse.epf.library.edit", "libraryInspector"); 			//$NON-NLS-1$ //$NON-NLS-2$
	}
	
	public static boolean isInPluginWithLessThanOneSuperCustomCategory(CustomCategory cc, MethodPlugin plugin) {
		if(UmaUtil.getMethodPlugin(cc) != plugin) {
			return false;
		}
		List list = AssociationHelper.getCustomCategories(cc);
		int count = 0;
		for (Iterator iter = list.iterator(); iter.hasNext() && count < 2;) {
			CustomCategory cat = (CustomCategory) iter.next();
			if(UmaUtil.getMethodPlugin(cat) == plugin) {
				count++;
			}						
		}
		return count < 2;
	}

	/**
	 * Check if the given wrapper is under a custom category tree
	 * 
	 * @param item
	 * @return
	 */
	public static boolean isUnderCustomCategoryTree(IWrapperItemProvider wrapper) {
		do {
			Object owner = wrapper.getOwner();
			if(unwrap(owner) instanceof CustomCategory) {
				return true;
			}
			wrapper = owner instanceof IWrapperItemProvider ? (IWrapperItemProvider) owner : null;
		} while(wrapper != null);
		
		return false;
	}
	
	public static Collection getExclusiveSubCustomCategories(CustomCategory cc) {
		ArrayList collection = new ArrayList();
		collectExclusiveSubCustomCategories(collection, cc, UmaUtil.getMethodPlugin(cc));
		return collection;
	}
	
	private static void collectExclusiveSubCustomCategories(Collection collection, CustomCategory cc, MethodPlugin plugin) {
		for (Iterator iter = cc.getCategorizedElements().iterator(); iter.hasNext();) {
			Object e = (Object) iter.next();
			if(e instanceof CustomCategory) {
				CustomCategory sub = (CustomCategory) e;
				if(isInPluginWithLessThanOneSuperCustomCategory(sub, plugin)) {
					collection.add(e);
					collectExclusiveSubCustomCategories(collection, sub, plugin);
				}
			}
		}
	}
	
	public static Object getAdapterByType(Notifier notifier, Object type) {
		for (Iterator iter = notifier.eAdapters().iterator(); iter.hasNext();) {
			Adapter adapter = (Adapter) iter.next();
			if(adapter.isAdapterForType(type)) {
				return adapter;
			}
		}
		return null;
	}

	/**
	 * Removes all references to a method element.
	 * 
	 * @param element
	 *            a method element
	 * @return a map containing the removed references
	 */
	public static Map removeReferences(MethodElement element) {
		return TngUtil.removeReferences(element, false);
	}

	/**
	 * Removes all references to a method element.
	 * 
	 * @param element
	 *            a method element
	 * @return a map of method elements whose references to the given element
	 *         are just removed, and their features that hold the references to
	 *         the given element
	 */
	public static Map removeReferences(MethodElement element,
			boolean checkModify) {
		// List referencers = new ArrayList();
		Map objectFeaturesMap = new HashMap();
		MultiResourceEObject eObj = (MultiResourceEObject) element;
	
		if (eObj.basicGetOppositeFeatureMap() == null)
			return objectFeaturesMap;
	
		for (Iterator iter = eObj.getOppositeFeatureMap().entrySet().iterator(); iter
				.hasNext();) {
			Map.Entry entry = (Map.Entry) iter.next();
			OppositeFeature oppositeFeature = ((OppositeFeature) entry.getKey());
			EStructuralFeature feature = oppositeFeature.getTargetFeature();
			if (feature.isMany()) {
				if (oppositeFeature.isMany()) {
					for (Iterator iterator = new ArrayList((Collection) eObj
							.getOppositeFeatureValue(oppositeFeature))
							.iterator(); iterator.hasNext();) {
						EObject obj = (EObject) iterator.next();
						if (checkModify) {
							checkModify(obj);
						}
						((List) obj.eGet(feature)).remove(element);
						List features = (List) objectFeaturesMap.get(obj);
						if (features == null) {
							features = new ArrayList();
							objectFeaturesMap.put(obj, features);
						}
						features.add(feature);
					}
				} else {
					EObject obj = (EObject) eObj
							.getOppositeFeatureValue(oppositeFeature);
					if (obj != null) {
						if (checkModify) {
							checkModify(obj);
						}
						((List) obj.eGet(feature)).remove(element);
						List features = (List) objectFeaturesMap.get(obj);
						if (features == null) {
							features = new ArrayList();
							objectFeaturesMap.put(obj, features);
						}
						features.add(feature);
					}
				}
			} else {
				if (oppositeFeature.isMany()) {
					for (Iterator iterator = new ArrayList((Collection) eObj
							.getOppositeFeatureValue(oppositeFeature))
							.iterator(); iterator.hasNext();) {
						EObject obj = (EObject) iterator.next();
						if (checkModify) {
							checkModify(obj);
						}
						obj.eSet(feature, null);
						List features = (List) objectFeaturesMap.get(obj);
						if (features == null) {
							features = new ArrayList();
							objectFeaturesMap.put(obj, features);
						}
						features.add(feature);
					}
				} else {
					EObject obj = (EObject) eObj
							.getOppositeFeatureValue(oppositeFeature);
					if (obj != null) {
						if (checkModify) {
							checkModify(obj);
						}
						obj.eSet(feature, null);
						List features = (List) objectFeaturesMap.get(obj);
						if (features == null) {
							features = new ArrayList();
							objectFeaturesMap.put(obj, features);
						}
						features.add(feature);
					}
				}
			}
		}
		// for (Iterator iter = objectFeaturesMap.entrySet().iterator();
		// iter.hasNext();) {
		// Map.Entry entry = (Map.Entry) iter.next();
		// referencers.add(new Referencer((EObject)entry.getKey(),
		// (List)entry.getValue()));
		// }
		// return referencers;
		return objectFeaturesMap;
	}
	
	/**
	 * Return publishing category property for method element
	 * The meaning of this property is used for:
	 * 
	 * CustomCategory: Publish this category with the categorized method elements
	 * Practice: Publish this practice with the referenced method elements
	 * 
	 * @param element
	 * @return
	 * 		 property if found, else null
	 */
	public static MethodElementProperty getPublishCategoryProperty(MethodElement element) {
		List props = element.getMethodElementProperty();
		if (props == null || props.size() == 0) {
			return null;
		}

		for (Iterator it = props.iterator(); it.hasNext();) {
			MethodElementProperty prop = (MethodElementProperty) it.next();
			if (PUBLISH_CATEGORY_PROPERTY.equals(prop.getName())) {
				return prop;
			}
		}

		return null;
	}

	public static List<INotifyChangedListener> getNotifyChangedListeners(AdapterFactory adapterFactory, Object obj) {
		Object adapter = adapterFactory.adapt(obj, ITreeItemContentProvider.class);
		if(adapter instanceof IListenerProvider) {
			return ((IListenerProvider) adapter).getNotifyChangedListeners();
		}
		return Collections.emptyList();
	}
	
	public static Collection<?> getWrappers(AdapterFactory adapterFactory, Object obj) {
		HashSet<Object> wrappers = new HashSet<Object>();
		for (INotifyChangedListener listener : getNotifyChangedListeners(adapterFactory, obj)) {
			if(listener instanceof IWrapperItemProvider && unwrap(listener) == obj) {
				wrappers.add(listener);
			}
		}
		return wrappers;
	}

	/**
	 * Gets the wrapper for the given value in the given wrappers.
	 * 
	 * @param wrappers
	 * @param value
	 * @return
	 */
	public static FeatureValueWrapperItemProvider getWrapper(Collection wrappers, Object value) {
		if (wrappers == null)
			return null;
		for (Iterator iter = wrappers.iterator(); iter.hasNext();) {
			Object listener = (Object) iter.next();
			if(listener instanceof FeatureValueWrapperItemProvider
					&& unwrap(listener) == value) {
				return (FeatureValueWrapperItemProvider) listener;
			}
		}
		return null;
	}

	public static Object getFeatureValueWrapperItemProviderForCC(AdapterFactory adapterFactory, CustomCategory cc) {
		// get ITreeContentProvider adapater
		CustomCategoryItemProvider adapter = (CustomCategoryItemProvider) adapterFactory.adapt(cc, ITreeItemContentProvider.class);
		for (Iterator iter = adapter.getNotifyChangedListeners().iterator(); iter.hasNext();) {
			Object listener = iter.next();
			if (listener instanceof FeatureValueWrapperItemProvider
					&& unwrap(listener) == cc) {
				return (FeatureValueWrapperItemProvider)listener;
			}
		}
		return cc;
	}
	
	public static class PresentationNameHelper {
		//to be overriden by subclass
		public String getPresentationName(MethodElement element) {
			return element.getPresentationName();
		}
	}
	
}