//------------------------------------------------------------------------------
// 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.configuration.closure;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.epf.library.IConfigurationClosure;
import org.eclipse.epf.library.IConfigurationManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.command.IActionManager;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.VariabilityElement;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;

/**
 * A method configuration closure.
 * 
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class ConfigurationClosure implements IConfigurationClosure {

	// If true, generate debug traces.
	protected static boolean debug = LibraryPlugin.getDefault().isDebugging();

	protected MethodConfiguration config = null;

	protected MethodLibrary library = null;

	protected IConfigurationManager configManager = null;

	protected DependencyManager dependencyManager = null;
	
	protected IActionManager actionMgr;

	// Node change information. The object are the model objects
	// check the linked objects in needed
	protected List selectedNotes = new ArrayList();
	
	private List<ElementError> errors = new ArrayList<ElementError>();
	
	// A map of invalid nodes to ElementDependencyError objects.
	protected Map<Object, ElementDependencyError> invalidNodesMap =
		new HashMap<Object, ElementDependencyError>();

	//protected List changedNodes = new ArrayList();
	
	private List<ClosureListener> listeners;

	/**
	 * Creates a new instance.
	 * 
	 * @param actionMgr
	 * 			  The IActionManager to use to change the MethodConfiguration.  If null, config will be changed directly.
	 * @param config
	 *            A method configuration.
	 */
	public ConfigurationClosure(IActionManager actionMgr, MethodConfiguration config) {
		this.config = config;
		this.actionMgr = actionMgr;

		configManager = LibraryService.getInstance().getConfigurationManager(
				config);
		if (configManager != null) {
			library = configManager.getMethodLibrary();
			dependencyManager = configManager.getDependencyManager();
		}

		// configuration changed, re-build the analyze the configuration for errors
		checkError();
	}

	/**
	 * Returns the method configuration manager.
	 * 
	 * @return A <code>ConfigurationManager</code>.
	 */
	public IConfigurationManager getConfigurationManager() {
		return configManager;
	}

	/**
	 * Returns the method configuration.
	 * 
	 * @return A <code>MethodConfiguration</code>.
	 */
	public MethodConfiguration getConfiguration() {
		return config;
	}

	/**
	 * Returns the containining method library.
	 * 
	 * @return A <code>MethodConfiguration</code>.
	 */
	public MethodLibrary getLibrary() {
		return library;
	}

//	/**
//	 * Sets the method plug-ins and packages selection.
//	 * 
//	 * @param elements
//	 *            an array of method plug-ins and packages
//	 */
//	public void setSelections(Object[] elements) {
//		
//		if ( elements == null ) {
//			return;
//		}
//		
//		// clear the old selections
//		selectedNotes.clear();
//		for (int i = 0; i < elements.length; i++ ) {
//			selectedNotes.add(elements[i]);
//		}
//	}

	
	/**
	 * Builds the selection list based on the method configuration.
	 * 
	 */
	public void checkError() {
		
		// Bug 206724 - SCM: Always prompt check out elements for a opened configuration when refresh source control status
		// don't need to validate the configuration, rely on the caller to validate it before call this method.
		// Validate the method configuration with the action manager.
		//LibraryUtil.validateMethodConfiguration(actionMgr, config);

		// initial fill the selections
		selectedNotes.clear();
		selectedNotes.addAll(config.getMethodPluginSelection());
		selectedNotes.addAll(config.getMethodPackageSelection());

		// Re-build the selections to auto add the process packages.
		clearErrorMarks();
		
		// Cleanup the old status and rebuild the list.
		invalidNodesMap.clear();

		processChangedNodes(getSelection());

	}

	private void clearErrorMarks() {
		// Re-build the selections to auto add the process packages.

		for (Iterator<ElementError> it = errors.iterator(); it.hasNext(); ) {
			ElementError error = it.next();
			notifyError(error, ClosureListener.ERROR_REMOVED);
		}	
	}
	
//	private void selectProcessPackages(Activity a) {
//		if (a == null) {
//			return;
//		}
//
//		for (Iterator it = a.getBreakdownElements().iterator(); it.hasNext();) {
//			BreakdownElement e = (BreakdownElement) it.next();
//			Object pkg = e.eContainer();
//			if (!selectedNotes.contains(pkg)) {
//				selectedNotes.add(pkg);
//				changedNodes.add(pkg);
//			}
//
//			if (e instanceof Activity) {
//				selectProcessPackages((Activity) e);
//			}
//		}
//	}

//	/**
//	 * Adds a method plug-in or package to the closure.
//	 * 
//	 * @param element
//	 *            A method element.
//	 * @param addChildren
//	 *            if <code>true</code>, add all child method elements.
//	 */
//	private void add(EObject element, boolean addChildren) {
//		if (!LibraryUtil.selectable(element)) {
//			return;
//		}
//
//		if (!selectedNotes.contains(element)) {
//			selectedNotes.add(element);
//
//			// Save the changed nodes so that we can update the status later.
//			addChanged(element);
//
//			if (element instanceof MethodPlugin) {
//				selectSystemPackages((MethodPlugin) element);
//			}
//		}
//
//		// Add the parent method element as well.
//		EObject parent = element.eContainer();
//		if ((parent != null) && !selectedNotes.contains(parent)) {
//			add(parent, false);
//		}
//
//		// Add children as needed.
//		if (addChildren) {
//			EList elements = element.eContents();
//			if (elements != null) {
//				for (Iterator it = elements.iterator(); it.hasNext();) {
//					EObject child = (EObject) it.next();
//					add(child, true);
//				}
//			}
//		}
//	}
//
//	private void addChanged(Object element) {
//		if (!changedNodes.contains(element)) {
//			changedNodes.add(element);
//		}
//	}

//	private void selectSystemPackages(MethodPlugin plugin) {
//		List pkgs = TngUtil.getAllSystemPackages(plugin);
//		for (Iterator it = pkgs.iterator(); it.hasNext();) {
//			EObject pkg = (EObject) it.next();
//			add(pkg, false);
//		}
//	}

	/**
	 * Checks whether a method plug-in or package is selected.
	 * 
	 * @return <code>true</code> if the given element is selected.
	 */
	public boolean isSelected(Object input) {
		if ((input instanceof MethodLibrary) || input == config
				|| selectedNotes.contains(input)) {
			return true;
		}
		return false;
	}

	/**
	 * Gets the element dependency error for a method element.
	 * 
	 * @element A method element.
	 * 
	 * @return An <code>ElementDependencyError</code>.
	 */
	public ElementDependencyError getError(Object element) {
		return getError(element, false);
	}

	private ElementDependencyError getError(Object element, boolean create) {
		ElementDependencyError error = (ElementDependencyError) invalidNodesMap
				.get(element);
		if (error == null && create) {
			error = new ElementDependencyError(element);
			invalidNodesMap.put(element, error);
		}
		return error;
	}

	/**
	 * check if there is error in this configuration closure
	 * 
	 * @return boolean
	 */
	public boolean hasError() {
		for (Iterator it = invalidNodesMap.values().iterator(); it.hasNext();) {
			ElementDependencyError error = (ElementDependencyError) it.next();
			if (error.isError()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * check if there is any problem (error/warning) with this configuration closure.
	 * @return boolean
	 */
	public boolean hasProblem() {
		return invalidNodesMap.size() > 0;
	}

	/**
	 * Returns all the errors.
	 * 
	 * @return A a list of <code>PackageError</code>.
	 */
	public List<PackageError> getAllErrors() {
		List<PackageError> errors = new ArrayList<PackageError>();
		for (Iterator it = invalidNodesMap.values().iterator(); it.hasNext();) {
			ElementDependencyError error = (ElementDependencyError) it.next();
			errors.addAll(error.getAll());
		}
		return errors;
	}

	/**
	 * Returns all the dependency errors.
	 * 
	 * @return An array of <code>ElementDependencyError</code>
	 */
	public Object[] getDependencyErrors() {
		return invalidNodesMap.values().toArray();
	}

	/**
	 * Returns all the invalid elements.
	 * 
	 * @return A list of invalid elements.
	 */
	public List getInvalidElements() {
		return new ArrayList(invalidNodesMap.keySet());
	}

	private void removeError(Object element) {
		if (invalidNodesMap.containsKey(element)) {
			invalidNodesMap.remove(element);

//			// Error status changed, add it to the changed list.
//			if (!changedNodes.contains(element)) {
//				changedNodes.add(element);
//			}
		}
	}

//	/**
//	 * Returns all the changed elements. These are elements whose check states
//	 * have changed or whose image have changed due to error.
//	 * 
//	 * @return A list of changed method elements.
//	 */
//	public List getChangedElements() {
//		List items = new ArrayList(changedNodes);
//		for (Iterator it = invalidNodesMap.keySet().iterator(); it.hasNext();) {
//			Object item = it.next();
//			if (!items.contains(item)) {
//				items.add(item);
//			}
//		}
//		return items;
//	}

	/**
	 * Returns the method plug-ins and packages selection.
	 * 
	 * @return An array of method plug-ins and packages.
	 */
	public Object[] getSelection() {
		return selectedNotes.toArray();
	}

	private void processChangedNodes(Object[] changedNodes) {
		
		// for all the changed notes,
		// all all contained elements and check if the elements are in config or not
		// if the elements are in config, the referenced elements should also be in config
		
		for (int i = 0; i <changedNodes.length; i++) {
			
			// the elements are either plugin or package
			Object changedElement = changedNodes[i];
			PackageDependency dependency = dependencyManager
					.getDependency((MethodElement) changedElement);
			if (dependency == null) {
				continue;
			}

			List refs = dependency.getAllElementReferences();
			if ( refs == null || refs.size() == 0 ) {
				continue;
			}
			
			for (Iterator itr = refs.iterator(); itr.hasNext(); ) {
				ElementReference ref = (ElementReference)itr.next();
				checkReference(ref);
			}
		}
		
		// for all the elements in the added category, check their references as well
		for ( Iterator<MethodElement> it = configManager.getConfigurationData()
				.getAddedElements().iterator(); it.hasNext(); ) {
			MethodElement e = it.next();
			
			PackageDependency dependency = 
				dependencyManager.getDependency((MethodElement)e.eContainer());
			if (dependency == null) {
				continue;
			}
		
			List refs = dependency.getAllElementReferences();
			if ( refs == null || refs.size() == 0 ) {
				continue;
			}
			
			for (Iterator itr = refs.iterator(); itr.hasNext(); ) {
				ElementReference ref = (ElementReference)itr.next();
				if ( ref.getElement() == e ) {
					checkReference(ref);
				}
			}
	
		}
		
	}
	
	private void checkReference(ElementReference ref) {
		MethodElement e = ref.getElement();
		MethodElement e_ref = ref.getRefElement();
		
		if ( e instanceof MethodPackage || e instanceof MethodConfiguration ) {
			return;
		}
		
		// Bug 207609 - Replaced elements are not considered for configuration error "missing mandatory input"
		// if the element is replaced, ignore the reference
		if ( e instanceof VariabilityElement ) {
			VariabilityElement replacer = ConfigurationHelper.getReplacer((VariabilityElement)e, config);
			if ( replacer != null ) {
				return;
			}
		}
		
		// the element might be subtracted, so ignore it
		if ( !ConfigurationHelper.inConfig(e, config, true, false)) {
			return;
		}
				
		// if the referenced element is not in  config, log error
		if ( !ConfigurationHelper.inConfig(e_ref, config)) {
			
			/*
			String message = LibraryResources.bind(LibraryResources.ElementError_missing_element, 
					(new String[] {LibraryUtil.getTypeName(e), 
							LibraryUtil.getTypeName(e_ref) }));
			
			ElementError error = new ElementError(
					this, ErrorInfo.WARNING,
					message, e, e_ref, ErrorInfo.REFERENCE_TO); //$NON-NLS-1$
			*/
			ElementError error = ConfigurationErrorMatrix.getError(config, ref);
			if ( error == null ) {
				return;
			}
			
			errors.add(error);
			notifyError(error, ClosureListener.ERROR_ADDED);
			
			// process package error
			processPackageError(LibraryUtil.getSelectable(e), LibraryUtil.getSelectable(e_ref), error.getErrorLevel() );
		}	
	}
	
	private void processPackageError(Object pkg, Object pkg_ref, int errorLevel ) {
		if ( errorLevel > 0 ) {
			ElementDependencyError error = getError(pkg, true);
			
			PackageError pkgerror = error.getError(pkg_ref);
			if ( pkgerror == null ) {
				String message = LibraryResources.configClosureWarning_msg1;
	
				pkgerror =  new PackageError(errorLevel, message, 
						pkg, pkg_ref, ErrorInfo.REFERENCE_TO);				
				error.addError(pkgerror);
				
			} else {
				pkgerror.setErrorLevel(errorLevel);
				
				// need to recalc the error bits
				error.calculateErrorBits();
			}
		} else {
			// remove the error
			removeError(pkg);
		}
		
		updateParentsForErrors((EObject)pkg);

	}
	
	private void notifyError(ElementError error, int type ) {
		
		if ( error == null || listeners == null || listeners.size() == 0 ) {
			return;
		}
		
		try {
							
			for (Iterator<ClosureListener> iter = listeners.iterator();iter.hasNext();) {
				ClosureListener listener = iter.next();
				
				listener.fireEvent(type, config, error);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	
//	/**
//	 * Validates the element dependency when the element is selected. When the
//	 * element is selected, we need to do the following: 1. Check error for
//	 * references 2. Remove error for dependents associated with element 3.
//	 * Update parents: if the selection is valid, remove all errors from parents
//	 * associated with this element if the selection is invalid, set error to
//	 * all parents.
//	 * 
//	 * @param dependency
//	 *            ElementDependency
//	 */
//	private void validateSelected(PackageDependency dependency) {
//		Object changedElement = dependency.getElement();
//
//		// Since this element is selected, remove all previous errors.
//		removeError(changedElement);
//
//		if (changedElement instanceof MethodLibrary) {
//			return;
//		}
//
//		// Since this element is selected, check all dependency errors in the
//		// dependent elements.
//		List dependents = dependency.getDependents();
//		if (dependents != null && dependents.size() > 0) {
//			Object element;
//			for (Iterator itr = dependents.iterator(); itr.hasNext();) {
//				element = itr.next();
//
//				ElementDependencyError error = getError(element, false);
//				if (error != null) {
//					PackageError pkgerror = error.removeError(changedElement);
//					if (error.size() == 0) {
//						removeError(element);
//
//						// Clear the parent error introduced by this element.
//						updateParentsForErrors((EObject) element);
//					}
//					
//					// notify the error listener about the error removed
//					notifyErrorRemoved(pkgerror);
//
//				}
//			}
//		}
//
//		// If an element is checked, check the element it depends on,
//		// which should be checked as well.
//		List refs = dependency.getReferences();
//		if (refs != null && refs.size() > 0) {
//			PackageReference ref;
//			Object element;
//			for (Iterator itr = refs.iterator(); itr.hasNext();) {
//				ref = (PackageReference) itr.next();
//				element = ref.getRefElement();
//
//				if (element instanceof MethodLibrary) {
//					continue;
//				}
//
//				// Don't warn on optional inputs not being
//				// present, so added the canIgnore() method
//				if (!isSelected(element) && !canIgnore(ref)) {
//					String message;
//					int errorType = 0;
//					if (ref.hasBaseReference()) {
//						errorType = ErrorInfo.ERROR;
//						message = LibraryResources.configClosureWarning_msg2;
//					} else {
//						errorType = ErrorInfo.WARNING;
//						message = LibraryResources.configClosureWarning_msg3;
//					}
//
//					ElementDependencyError error = getError(changedElement,
//							true);
//					
//					PackageError pkgerror =  new PackageError(this, errorType, message,
//							changedElement, element, ErrorInfo.REFERENCE_TO);				
//					error.addError(pkgerror);
//
//					// notify the error listener about the error added
//					notifyErrorAdded(pkgerror);
//
//				} else {
//					ElementDependencyError error = getError(changedElement,
//							false);
//					if (error != null) {
//						PackageError pkgerror = error.removeError(element);
//						
//						// notify the error listener about the error removed
//						notifyErrorRemoved(pkgerror);
//
//					}
//				}
//			}
//		}
//
//		// Finally, update the parents.
//		updateParentsForErrors((EObject) changedElement);
//	}
//
//	/**
//	 * Validates the ElementDependency when the element is unselected. When the
//	 * element is unselected, we need to do the following: 1. check error for
//	 * dependencts 2. remove error for references associated with element, in
//	 * case of any added when the element was check 3. update parents: if the
//	 * selection is valid, remove all errors from parents associated with this
//	 * element if the selection is invalid, set error to all parents.
//	 * 
//	 * @param dependency
//	 *            A <code>ElementDependency</code> object.
//	 */
//	private void validateUnSelected(PackageDependency dependency) {
//		Object changedElement = dependency.getElement();
//
//		// Since this element is un-selected, remove all previous errors.
//		removeError(changedElement);
//
//		if (changedElement instanceof MethodLibrary) {
//			return;
//		}
//
//		// Since this element is un-selected, remove all errors in the
//		// referenced elements.
//		List refs = dependency.getReferences();
//		if (refs != null && refs.size() > 0) {
//			ElementReference ref;
//			Object element;
//			for (Iterator itr = refs.iterator(); itr.hasNext();) {
//				ref = (ElementReference) itr.next();
//				element = ref.getRefElement();
//
//				ElementDependencyError error = getError(element, false);
//				if (error != null) {
//					PackageError pkgerror = error.removeError(changedElement);
//					if (error.size() == 0) {
//						removeError(element);
//
//						// Clear the parent error introduced by this element.
//						updateParentsForErrors((EObject) element);
//
//					}
//					
//					// notify the error listener about the error removed
//					notifyErrorRemoved(pkgerror);
//
//				}
//			}
//		}
//
//		// If an element is unchecked, check the dependent elements.
//		// If there are check elements depending on it, the element can't be
//		// unchecked.
//		List dependents = dependency.getDependents();
//		if (dependents != null && dependents.size() > 0) {
//			Object element;
//			for (Iterator itr = dependents.iterator(); itr.hasNext();) {
//				element = itr.next();
//
//				if (element instanceof MethodLibrary) {
//					continue;
//				}
//
//				if (isSelected(element)) {
//					// Determine the type of dependency.
//					PackageDependency childDep = dependencyManager
//							.getDependency((MethodElement) element);
//
//					validateSelected(childDep);
//				} else {
//					removeError(changedElement);
//				}
//			}
//		}
//
//		// finally, update the parents
//		updateParentsForErrors((EObject) changedElement);
//	}
//
	private void updateParentError(EObject parent, EObject element,
			int errorType) {
		if (parent == null || (parent instanceof MethodLibrary)) {
			return;
		}

//		if ((parent instanceof MethodPackage)
//				&& ConfigurationHelper.isGlobalPackage((MethodPackage) parent)) {
//			updateParentError(parent.eContainer(), element, errorType);
//			return;
//		}

		// Remove the error associated with this element from all parents.
		ElementDependencyError error = getError(parent, false);
		if (error != null && error.size() > 0) {
			error.removeError(element);
		}

		if (errorType != ErrorInfo.NONE) {
			// Propegate the error to all parents.
			error = getError(parent, true);
			String message = LibraryResources.configClosureWarning_msg1;
			PackageError pkgerr = new PackageError(errorType, message, parent, element,
					ErrorInfo.NONE);
			error.addError(pkgerr);
		} else if ((error != null) && (error.size() == 0)) {
			removeError(parent);
		}

		updateParentError(parent.eContainer(), element, errorType);
	}

	private void updateParentsForErrors(EObject element) {
		int errorType = ErrorInfo.NONE;

		ElementDependencyError error = getError(element);
		if (error != null && error.size() > 0) {
			if (error.isError() || error.isChildError()) {
				errorType = PackageError.CHILD_ERROR;
			} else if (error.isWarning() || error.isChildWarning()) {
				errorType = PackageError.CHILD_WARNING;
			}
		}

		updateParentError(element.eContainer(), element, errorType);
	}

	/**
	 * accept the cutrrent selection, fix the errors and ignore any warning message.
	 * 
	 */
	public void fixErrors() {
		boolean changed = true;
		boolean forceCheck = true;
		while (changed) {
			changed = fixProblems(true, forceCheck);
			forceCheck = false;
		}
	}

	/**
	 * fix all error(s) and warnign(s)
	 * 
	 */
	public void fixProblems() {
		boolean changed = true;
		boolean forceCheck = true;
		while (changed) {
			changed = fixProblems(false, forceCheck);
			forceCheck = false;
		}
	}

	private boolean fixProblems(boolean errorOnly, boolean forceCheck) {
		// Note: make closure will select elements as needed.
		// so we need to make a copy of the current selcted ones
		// in order to trace the status
		//List currentSelected = new ArrayList(selectedNotes);

		// if force check is set, run check anyway
		boolean changed = forceCheck;

		// list of errorInfo objects
		List errors = getAllErrors();
		if (errors.size() > 0) {			
			invalidNodesMap.clear();
			PackageError error;
			EObject causeElement;
			//boolean ownerSelected, causeSelected;
			for (Iterator it = errors.iterator(); it.hasNext();) {
				error = (PackageError) it.next();

				//ownerElement = (EObject) error.getOwnerElement();
				causeElement = (EObject) error.getCauseElement();
				//addChanged(ownerElement);
				//addChanged(causeElement);
//				if (error.isChildError() || error.isChildWarning()) {
//					continue;
//				}

				boolean isError = error.isError();
				boolean isWarning = error.isWarning();
				if (!isError && !isWarning || !isError && errorOnly) {
					continue;
				}
			
				if ( !isSelected(causeElement) && selectErrorElement(causeElement) ) {
					changed = true;
				}
			}
		}

		if ( changed ) {
			checkError();
		}
		
		return changed;
	}

	private boolean selectErrorElement(EObject element) {

		boolean selected = true;
		if (element instanceof MethodPlugin 
				&& !config.getMethodPluginSelection().contains(element)) {
			config.getMethodPluginSelection().add(element);
		} else if ( element instanceof MethodPackage 
				&& !config.getMethodPackageSelection().contains(element)){
			config.getMethodPackageSelection().add(element);
		} else {
			selected = false;
		}
		
		return selected;
	}

//	/**
//	 * update the method configuration in the library with the current selections
//	 */
//	public void saveMethodConfiguration() {
//		List plugins = config.getMethodPluginSelection();
//		List packages = config.getMethodPackageSelection();
//
//		plugins.clear();
//		packages.clear();
//
//		EObject element;
//		for (Iterator it = selectedNotes.iterator(); it.hasNext();) {
//			element = (EObject) it.next();
//			if (element instanceof MethodPlugin) {
//				if (!plugins.contains(element)) {
//					plugins.add(element);
//				}
//			} else if ((element instanceof MethodPackage)
//					&& !ConfigurationHelper
//							.isGlobalPackage((MethodPackage) element)) {
//				if (!packages.contains(element)) {
//					packages.add(element);
//				}
//			}
//		}
//	}

	/**
	 * Packages the library based on the selection.
	 * <p>
	 * Note: This will change the current library. Before calling this method, a
	 * copy of the current library should be created with the following steps:
	 * 1. Create a new <code>ConfigurationManager</code> with a copy of the
	 * original library, 2. Rebuild the dependency, 3. Create a
	 * <code>ConfigurationClosure</code> with the current configuration.
	 * 
	 * @return A <code>MethodLibrary</code>.
	 */
	public MethodLibrary packageLibrary(boolean removeBrokenReferences) {
		processSelection(library, removeBrokenReferences);

		// Remove the configurations except for the current one.
		List configs = library.getPredefinedConfigurations();
		configs.clear();
		configs.add(config);

		return library;
	}

	/**
	 * process the selected package by removeing all unselected elements and any
	 * missing references
	 * 
	 * @param element
	 */
	private void processSelection(EObject element,
			boolean removeBrokenReferences) {
		if (removeBrokenReferences) {
			// Iterator the references and remove broken references.
			EList references = element.eCrossReferences();
			if (references != null) {
				for (Iterator it = new ArrayList(references).iterator(); it
						.hasNext();) {
					EObject ref = (EObject) it.next();
					EObject pkgRef = LibraryUtil.getSelectable(ref);
					if (pkgRef != null && !isSelected(pkgRef)) {
						removeReference(element, ref);
					}
				}
			}
		}

		EList elements = element.eContents();
		if (elements != null) {
			for (Iterator it = new ArrayList(elements).iterator(); it.hasNext();) {
				EObject child = (EObject) it.next();

				// If the child element is selectable but it is not in the
				// configuration, remove it.
				if (LibraryUtil.selectable(child) && !isSelected(child)) {
					EcoreUtil.remove(child);
				} else {
					processSelection(child, removeBrokenReferences);
				}
			}
		}
	}

	private void removeReference(EObject ownerElement, EObject refElement) {
		AdapterFactoryContentProvider provider = configManager
				.getContentProvider();
		IPropertySource ps = provider.getPropertySource(ownerElement);
		IPropertyDescriptor[] pds = ps.getPropertyDescriptors();
		if (pds != null && pds.length > 0) {
			for (int i = 0; i < pds.length; i++) {
				IPropertyDescriptor descriptor = (IPropertyDescriptor) pds[i];
				Object id = descriptor.getId();
				Object value = ps.getPropertyValue(id);

				// Check whether the value needs to be converted to an editable
				// value.
				IPropertySource source = provider.getPropertySource(value);
				if (source != null) {
					value = source.getEditableValue();
				}
				if (value instanceof EList) {
					EList refList = (EList) value;
					if (refList.contains(refElement)) {
						if (debug) {
							System.out
									.println("Reference [" + LibraryUtil.getName(refElement) //$NON-NLS-1$
											+ "] removed from [" //$NON-NLS-1$
											+ LibraryUtil.getName(ownerElement)
											+ "]'s reference list"); //$NON-NLS-1$
						}
						refList.remove(refElement);
						ps.setPropertyValue(id, refList);
					}
				} else if (value instanceof MethodElement) {
					if (debug) {
						System.out
								.println("Reference [" + LibraryUtil.getName(refElement) //$NON-NLS-1$
										+ "] removed from [" //$NON-NLS-1$
										+ LibraryUtil.getName(ownerElement)
										+ "]"); //$NON-NLS-1$
					}
					ps.setPropertyValue(id, null);
				}

			}
		}
	}

	/**
	 * Disposes resources allocated by this closure.
	 */
	public void dispose() {
		
		clearErrorMarks();
		
		configManager = null;
		config = null;
		library = null;
		dependencyManager = null;
		actionMgr = null;
		//selectedNotes.clear();
		//changedNodes.clear();
		if (invalidNodesMap != null) {
			invalidNodesMap.clear();
		}
		if (listeners != null) {
			listeners.clear();
		}
	}

//	private boolean canIgnore(PackageReference pkgRef) {
//		return pkgRef.canIgnore();
//	}

	public void addListener(ClosureListener listener) {
		if (listeners == null) {
			listeners = new ArrayList<ClosureListener>();
		}
		if (!listeners.contains(listener)) {
			listeners.add(listener);
		}
		
		notifyListener(listener, this.errors);
	}
	
	public void removeListener(ClosureListener listener) {
		if (listeners != null) {
			if (listeners.contains(listener)) {
				listeners.remove(listener);
			}
		}
	}
	
//	private void notifyErrorAdded(PackageError pkgerror) {
//			//notifyListeners(ClosureListener.ERROR_ADDED, pkgerror);
//	}
//	
//	private void notifyErrorRemoved(PackageError pkgerror) {
//		//notifyListeners(ClosureListener.ERROR_REMOVED, pkgerror);	
//	}
	
	private void notifyListener(ClosureListener listener, List errors) {
									
		for ( Iterator it = errors.iterator(); it.hasNext(); ) {
			ElementError error = (ElementError)it.next();
			listener.fireEvent(ClosureListener.ERROR_ADDED, config, error);
		}
	}
	
//	/**
//	 * add this element into the configuration
//	 * this is for quick fix action
//	 * our default implementation is to select the owning package
//	 * @param element
//	 * @return IStatus
//	 */
//	public IStatus selectElement(MethodElement element) {
//		
//		//if the element is subtracted, we can't select the element
//		// return an error
//		if ( configManager.getConfigurationData().isElementInSubtractedCategory(element)) {
//			String message = LibraryResources.bind(LibraryResources.QuickfixError_reason1, 
//					(new String[] {LibraryUtil.getTypeName(element)}));
//			return new Status(IStatus.ERROR,
//					LibraryPlugin.getDefault().getId(), IStatus.OK, message, null);
//		}
//		
//		// for quick fix, we just select the package of the element 
//		// and the child packages
//		Object owner = LibraryUtil.getSelectable(element);
//		if ( owner != null && owner instanceof MethodPackage) {
//			config.getMethodPackageSelection().add(owner);
//		}	
//		
//		return Status.OK_STATUS;
//	}
}
