//------------------------------------------------------------------------------
// 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.persistence;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
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.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMLInfoImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLMapImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.library.persistence.ILibraryResourceSet;
import org.eclipse.epf.library.persistence.LibraryResourceException;
import org.eclipse.epf.persistence.refresh.IRefreshEvent;
import org.eclipse.epf.persistence.refresh.IRefreshListener;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.refresh.internal.RefreshEvent;
import org.eclipse.epf.persistence.util.PersistenceResources;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.persistence.util.UnresolvedProxyMarkerManager;
import org.eclipse.epf.resourcemanager.ResourceDescriptor;
import org.eclipse.epf.resourcemanager.ResourceManager;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.services.Services;
import org.eclipse.epf.uma.Activity;
import org.eclipse.epf.uma.BreakdownElement;
import org.eclipse.epf.uma.Descriptor;
import org.eclipse.epf.uma.Diagram;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.ProcessElement;
import org.eclipse.epf.uma.ProcessPackage;
import org.eclipse.epf.uma.RoleDescriptor;
import org.eclipse.epf.uma.SemanticModelBridge;
import org.eclipse.epf.uma.TeamProfile;
import org.eclipse.epf.uma.UMASemanticModelBridge;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.WorkOrder;
import org.eclipse.epf.uma.WorkProductDescriptor;
import org.eclipse.epf.uma.ecore.IProxyResolutionListener;
import org.eclipse.epf.uma.ecore.IUmaResourceSet;
import org.eclipse.epf.uma.ecore.ResolveException;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.EventTypes;
import org.eclipse.epf.uma.ecore.util.OppositeFeature;
import org.eclipse.epf.uma.util.AssociationHelper;
import org.eclipse.epf.uma.util.ContentDescriptionFactory;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.Calendar;

/**
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class MultiFileResourceSetImpl extends ResourceSetImpl implements
		IProxyResolutionListener, IUmaResourceSet, ILibraryResourceSet {

	private static final String[] DEFAULT_DELIVERY_PROCESS_PATH = { "DeliveryProcesses" }; //$NON-NLS-1$

	private static final String[] DEFAULT_CAPABILITY_PATTERN_PATH = {
			"Content", "CapabilityPatterns" }; //$NON-NLS-1$ //$NON-NLS-2$

	private static final String[] DEFAULT_PROCESS_CONTRIBUTION_PATH = { "ProcessContributions" }; //$NON-NLS-1$		

	public static final String[][] PROCESS_PACKAGE_PATHS = {
			DEFAULT_DELIVERY_PROCESS_PATH, DEFAULT_CAPABILITY_PATTERN_PATH,
			DEFAULT_PROCESS_CONTRIBUTION_PATH };

	public static boolean REPORT_ERROR = true;

	static final Map DEFAULT_SAVE_OPTIONS = new HashMap();

	static final Set DEFAULT_SAVE_SEPARATELY_CLASS_SET = new HashSet();

	static {
		DEFAULT_SAVE_SEPARATELY_CLASS_SET.add(UmaPackage.eINSTANCE
				.getMethodPlugin());
		DEFAULT_SAVE_SEPARATELY_CLASS_SET.add(UmaPackage.eINSTANCE
				.getProcessComponent());
		DEFAULT_SAVE_SEPARATELY_CLASS_SET.add(UmaPackage.eINSTANCE
				.getContentDescription());
		// eClasses.add(ResourcemanagerPackage.eINSTANCE.getResourceManager());
		DEFAULT_SAVE_SEPARATELY_CLASS_SET.add(UmaPackage.eINSTANCE
				.getMethodConfiguration());

		XMLResource.XMLMap xmlMap = createSaveXMLMap();

		HashSet saveTogether = new HashSet();
		saveTogether.add(UmaPackage.eINSTANCE.getBreakdownElementDescription());

		DEFAULT_SAVE_OPTIONS.put(
				MultiFileXMISaveImpl.SAVE_SEPARATELY_CLASS_SET,
				DEFAULT_SAVE_SEPARATELY_CLASS_SET);
		DEFAULT_SAVE_OPTIONS.put(MultiFileXMISaveImpl.SAVE_ALL, "false"); //$NON-NLS-1$
		DEFAULT_SAVE_OPTIONS.put(MultiFileXMISaveImpl.SAVE_TOGETHER_CLASS_SET,
				saveTogether);
		DEFAULT_SAVE_OPTIONS.put(MultiFileXMISaveImpl.REFRESH_NEW_RESOURCE,
				"true"); //$NON-NLS-1$
		DEFAULT_SAVE_OPTIONS.put(MultiFileXMISaveImpl.CHECK_MODIFY, "true"); //$NON-NLS-1$
		DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
		DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_PROCESS_DANGLING_HREF,
				XMLResource.OPTION_PROCESS_DANGLING_HREF_DISCARD);
		DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_XML_MAP, xmlMap);
		DEFAULT_SAVE_OPTIONS.put(XMLResource.OPTION_CONFIGURATION_CACHE, Boolean.TRUE);

		AssociationHelper.init();
	}

	public static final String RESMGR_XMI = "resmgr.xmi"; //$NON-NLS-1$

	private HashMap defaultSaveOptions;

	private HashMap guidToMethodElementMap;

	private boolean loading;

	private boolean loadingResourceManagerTree;

	private Map URIToTempURIMap;

	private UnresolvedProxyMarkerManager markerMananger;

	private UniqueEList<IRefreshListener> refreshListeners;

	protected IURIProvider uriProvider;

	private Path configFolderPath;

	private Path libFolderPath;

	private static XMLResource.XMLMap createLoadXMLMap() {
		XMLResource.XMLMap xmlMap = new XMLMapImpl();
		Set excludedAttributes = new HashSet();
		excludedAttributes.add(UmaPackage.eINSTANCE.getMethodElement_Guid());
		excludedAttributes.add(UmaPackage.eINSTANCE.getNamedElement_Name());

		for (Iterator iter = UmaPackage.eINSTANCE.getEClassifiers().iterator(); iter
				.hasNext();) {
			EClassifier eClassifier = (EClassifier) iter.next();
			if (eClassifier instanceof EClass) {
				EClass eClass = (EClass) eClassifier;

				for (Iterator iterator = eClass.getEAttributes().iterator(); iterator
						.hasNext();) {
					EAttribute attrib = (EAttribute) iterator.next();
					if (!excludedAttributes.contains(attrib)) {
						XMLResource.XMLInfo xmlInfo = new XMLInfoImpl();
						xmlInfo.setName(attrib.getName());
						xmlInfo
								.setXMLRepresentation(XMLResource.XMLInfo.ELEMENT);
						xmlMap.add(attrib, xmlInfo);
					}
				}
			}
		}

		return xmlMap;
	}

	private static boolean saveAttributeAsElement(EClass eClass,
			Collection selectedEClasses) {
		for (Iterator iter = selectedEClasses.iterator(); iter.hasNext();) {
			EClass base = (EClass) iter.next();
			if (base.isSuperTypeOf(eClass)) {
				return true;
			}
		}
		return false;
	}

	private static XMLResource.XMLMap createSaveXMLMap() {
		XMLResource.XMLMap xmlMap = new XMLMapImpl();
		Set excludedAttributes = new HashSet();
		excludedAttributes.add(UmaPackage.eINSTANCE.getMethodElement_Guid());
		excludedAttributes.add(UmaPackage.eINSTANCE.getNamedElement_Name());

		// select only ContentDescription and Section
		Set selectedEClasses = new HashSet();
		selectedEClasses.add(UmaPackage.eINSTANCE.getContentDescription());
		selectedEClasses.add(UmaPackage.eINSTANCE.getSection());

		for (Iterator iter = UmaPackage.eINSTANCE.getEClassifiers().iterator(); iter
				.hasNext();) {
			EClassifier eClassifier = (EClassifier) iter.next();
			if (eClassifier instanceof EClass) {
				EClass eClass = (EClass) eClassifier;

				if (saveAttributeAsElement(eClass, selectedEClasses)) {
					for (Iterator iterator = eClass.getEAttributes().iterator(); iterator
							.hasNext();) {
						EAttribute attrib = (EAttribute) iterator.next();
						if (!excludedAttributes.contains(attrib)) {
							XMLResource.XMLInfo xmlInfo = new XMLInfoImpl();
							xmlInfo.setName(attrib.getName());
							xmlInfo
									.setXMLRepresentation(XMLResource.XMLInfo.ELEMENT);
							xmlMap.add(attrib, xmlInfo);
						}
					}
				}
			}
		}

		return xmlMap;
	}

	public MultiFileResourceSetImpl() {
		super();
		markerMananger = new UnresolvedProxyMarkerManager(this);
	}

	public MultiFileResourceSetImpl(boolean reportError) {
		this();
		markerMananger.setEnabled(reportError);
	}

	public UnresolvedProxyMarkerManager getUnresolvedProxyMarkerManager() {
		return markerMananger;		
	}
	
	protected IURIProvider getURIProvider() {
		if(uriProvider == null) {
			uriProvider = new FilePathProvider();
		}
		return uriProvider;
	}
	
	private void handleResourceChange(IResource wsRes) {
		System.out
				.println("MultiFileResourceSetImpl.handleResourceChange(): " + wsRes.toString()); //$NON-NLS-1$

		MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) getResource(
				URI.createFileURI(wsRes.getLocation().toString()), false);
		if (resource != null) {
			try {
				ArrayList proxies = new ArrayList();
				resource.reload(proxies);

				// notify MAKE_PROXY event for all proxies
				//
				Notification msg = new NotificationImpl(EventTypes.MAKE_PROXY,
						false, true);
				for (Iterator iter = proxies.iterator(); iter.hasNext();) {
					EObject o = (EObject) iter.next();
					o.eNotify(msg);
				}

			} catch (IOException e) {
				CommonPlugin.INSTANCE.log(e);
			}
		}

	}

	public Map getLoadOptions() {
		Map options = super.getLoadOptions();
		options.put(XMLResource.OPTION_ENCODING, "UTF-8"); //$NON-NLS-1$
		options.put(XMLResource.OPTION_XML_MAP, createLoadXMLMap());
		return options;
	}

	public Map getDefaultSaveOptions() {
		if (defaultSaveOptions == null) {
			defaultSaveOptions = new HashMap();
			defaultSaveOptions.putAll(DEFAULT_SAVE_OPTIONS);
		}

		return defaultSaveOptions;
	}

	private Resource getMethodLibraryResource() {
		if (getResources().isEmpty())
			return null;
		return (Resource) getResources().get(0);
	}

	public MethodLibrary getMethodLibrary() {
		Resource resource = getMethodLibraryResource();
		return resource == null ? null : (MethodLibrary) PersistenceUtil
				.getMethodElement(resource);
	}

	protected ResourceManager getRootResourceManager() {
		Resource resource = getMethodLibraryResource();
		return resource == null ? null : MultiFileSaveUtil
				.getResourceManager(resource);
	}

	/**
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getURIConverter()
	 */
	public URIConverter getURIConverter() {
		if (uriConverter == null) {
			uriConverter = new MultiFileURIConverter(this);
		}
		return uriConverter;
	}

	/**
	 * @param uri
	 * @return null if the resource with the given URI could not be found
	 */
	public Resource getResource(URI uri) {
		if (getURIConverter().normalize(uri) == null)
			return null;
		Resource res = null;
		try {
			res = super.getResource(uri, false);
			if (res == null) {
				Map map = getURIResourceMap();
				res = createResource(uri);

				try {
					demandLoadHelper(res);
				} catch (RuntimeException e) {
					// remove the resource from resource set if it could not be
					// loaded
					//
					getResources().remove(res);
					throw e;
				}

				if (map != null) {
					map.put(uri, res);
				}
			}
		} catch (WrappedException e) {
			if (e.exception() instanceof FileNotFoundException) {
				return null;
			}
			throw e;
		}
		return res;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#demandLoad(org.eclipse.emf.ecore.resource.Resource)
	 */
	protected void demandLoad(Resource resource) throws IOException {
		super.demandLoad(resource);

		// refresh workspace resource of this resource to make them synchronized
		//
		boolean ret = FileManager.getInstance().refresh(resource);
		if(MultiFileSaveUtil.DEBUG) {
			if(!ret) {
				System.err.println("MultiFileResourceSetImpl.demandLoad(): could not refresh resource " + resource); //$NON-NLS-1$
			}
		}
	}
	
	/**
	 * Resolves container of the MethodElement in the given resource.
	 * 
	 * @param res
	 */
	public void resolveContainer(Resource res) {
		MethodLibrary lib = getMethodLibrary();
		if(loading && lib == null) {
			return;
		}
		for (Iterator iterator = res.getContents().iterator(); iterator.hasNext();) {
			Object element = (Object) iterator.next();
			if(element instanceof MethodElement) {
				MethodElement e = (MethodElement) element;
				if(e != lib && e.eContainer() == null) {
					// the method element might have been loaded before its container accessed it
					//
					ResourceDescriptor resDesc = MultiFileSaveUtil.getResourceDescriptor(res);
					if(resDesc != null) {
						Resource containerResource = resDesc.eResource();
						if(containerResource instanceof XMLResourceImpl) {
							Object proxy = ((XMLResourceImpl)containerResource).getIDToEObjectMap().get(e.getGuid());
							if(proxy instanceof EObject) {
								EObject proxyEObject = ((EObject)proxy); 
								EReference ref = proxyEObject.eContainmentFeature();
								EObject container = proxyEObject.eContainer();
								if(container != null) {
									if (ref.isMany()) {
										List values = (List) container.eGet(ref);
										for (Iterator iter = values.iterator(); iter.hasNext(); iter
										.next())
											;
									} else {
										container.eGet(ref);
									}
									resolveContainer(containerResource);
								}
							}
						}
					}
				}
			}			
		}
	}

	/**
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResource(org.eclipse.emf.common.util.URI,
	 *      boolean)
	 */
	public Resource getResource(URI uri, boolean loadOnDemand) {
		if (getURIConverter().normalize(uri) == null)
			return null;
		Resource res = null;
		try {
			res = super.getResource(uri, loadOnDemand);
		} catch (RuntimeException e) {
			String msg = null;
			if (e.getMessage() != null)
				msg = NLS.bind(
						PersistenceResources.loadResourceErrorWithReason_msg,
						(new Object[] { uri, e.getMessage() }));
			else
				msg = NLS.bind(PersistenceResources.loadResourceError_msg, uri);
			handleException(msg);
			throw e;
		}
		return res;
	}

	public void addRefreshListener(IRefreshListener listener) {
		if (refreshListeners == null) {
			refreshListeners = new UniqueEList<IRefreshListener>();
		}
		refreshListeners.add(listener);
	}

	public void removeRefreshListenter(IRefreshListener listener) {
		if (refreshListeners != null) {
			refreshListeners.remove(listener);
		}
	}
	
	public void notifyRefreshListeners(IRefreshEvent event) {
		if(refreshListeners != null && !refreshListeners.isEmpty()) {
			for (IRefreshListener listener : refreshListeners) {
				try {
					listener.notifyRefreshed(event);
				} catch (Exception e) {
					PersistencePlugin.getDefault().getLogger().logError(e);
				}
			}
		}
	}

	/**
	 * Reloads the given resources
	 * 
	 * @param resources
	 * @return resources that had been reloaded
	 */
	public synchronized Collection reloadResources(Collection resources) {		
		// save the ResourceDescriptor for the resources to create URI for their
		// proxies after unload
		//
		for (Iterator iter = resources.iterator(); iter.hasNext();) {
			MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) iter
					.next();
			
			if(MultiFileSaveUtil.DEBUG) {
				System.out
						.println("MultiFileResourceSetImpl.reloadResources(): resource=" + resource + ", element=" + PersistenceUtil.getMethodElement(resource)); //$NON-NLS-1$ //$NON-NLS-2$
			}
			
			ResourceDescriptor resDesc = MultiFileSaveUtil
					.getResourceDescriptor(resource);
			if (resDesc != null) {
				resource.setResourceDescriptor(resDesc);
			}
		}

		ArrayList reloadedResources = new ArrayList();
		HashSet proxies = new HashSet();
		ArrayList resourceList = new ArrayList(resources);

		Resource libResource = getMethodLibraryResource();
		boolean reloadAllConfigs = false;
		if (resourceList.remove(libResource)) {
			// MethodLibrary resource is to reload, it must be reloaded first
			//			
			MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) libResource;

			// clear markers for this resource
			//
			markerMananger.clearMarkers(resource);

			try {
				if (resource.reload(proxies)) {
					reloadedResources.add(resource);

					// reset the resource manager reference in URIConverter of
					// this resource set
					// since the resource manager is reloaded
					//
					MultiFileURIConverter uriConverter = (MultiFileURIConverter) getURIConverter();
					uriConverter.resMgr = null;
					
					reloadAllConfigs = true;
				}
			} catch (IOException e) {
				CommonPlugin.INSTANCE.log(e);
			}

		}
		// reload the resources
		//
		for (Iterator iter = resourceList.iterator(); iter.hasNext();) {
			MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) iter
					.next();

			// clear markers for this resource
			//
			markerMananger.clearMarkers(resource);

			try {
				if (resource.reload(proxies)) {
					reloadedResources.add(resource);
				}
			} catch (IOException e) {
				CommonPlugin.INSTANCE.log(e);
			}
		}

		if (!reloadedResources.isEmpty()) {
			// reinitialize the resource set
			//
			initialize(reloadAllConfigs);

			// notify the listeners
			//
			if (refreshListeners != null) {
				IRefreshEvent event = new RefreshEvent(reloadedResources,
						proxies);
				for (Iterator iter = new ArrayList(refreshListeners).iterator(); iter
						.hasNext();) {
					IRefreshListener listener = (IRefreshListener) iter.next();
					listener.notifyRefreshed(event);
				}
			}
		}

		return reloadedResources;
	}

	public void initialize(boolean loadConfigurations) {
		// load the ResourceManager tree and opposite features
		//
		loadResourceManagerTree();

		setContainersOfLoadedElements();
		
		if(loadConfigurations) {
			loadConfigurations();
		}

		loadOppositeFeatures();

		// reset the resource manager reference in URIConverter of this resource
		// set
		//
		MultiFileURIConverter uriConverter = (MultiFileURIConverter) getURIConverter();
		uriConverter.resMgr = null;
	}
	
	private void setContainersOfLoadedElements() {
		ResourceManager resMgr = getRootResourceManager();
		Iterator iterator = new AbstractTreeIterator(resMgr, false) {

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

			protected Iterator getChildren(Object object) {
				ResourceManager resMgr = (ResourceManager) object;
				Collection GUIDs = new HashSet();
				List subMgrs = new ArrayList(resMgr.getSubManagers());
				for (Iterator iter = subMgrs.iterator(); iter.hasNext();) {
					try {
						InternalEObject subMgr = (InternalEObject) iter
								.next();
						if (subMgr != null && !subMgr.eIsProxy()) {
							MethodElement e = PersistenceUtil
									.getMethodElement(subMgr.eResource());
							GUIDs.add(e.getGuid());
						}
					} catch (RuntimeException e) {
						throw e;
					}
				}
				Resource resource = resMgr.eResource();
				if(resource != null) {
					MethodElement parent = PersistenceUtil
							.getMethodElement(resource);

					// resolve the proxy of this element in the parent
					//
					MultiFileSaveUtil.resolveProxies(GUIDs, parent);
				}

				return resMgr.getSubManagers().iterator();
			}

		};
		for (; iterator.hasNext(); iterator.next())
			;
	}

	/**
	 * Checks if the given workspace resource represents a library resource
	 * 
	 * @param wsResource
	 * @return
	 */
	public boolean isLibraryResource(IResource wsResource) {
		return libFolderPath != null && libFolderPath.isPrefixOf(wsResource.getLocation());
	}
	
	/**
	 * Checks if the given workspace resource is a new resource that can be loaded 
	 * using {@link #loadNewResources(Collection)}
	 *  
	 * @return
	 */
	public boolean isNewResourceToLoad(IResource wsResource) {
		IPath loc = wsResource.getLocation();
		return (loc != null && configFolderPath != null 
				&& MultiFileSaveUtil.DEFAULT_FILE_EXTENSION.equalsIgnoreCase("." + loc.getFileExtension()) //$NON-NLS-1$
				&& configFolderPath.isPrefixOf(loc)
				&& !FileManager.getInstance().isTeamPrivate(loc.toString()));

	}
	
	/**
	 * Loads new resources specified by the given collection of {@link IResource work space resources}
	 * into this resource set
	 * TODO: merge this code to {@link #getResource(URI, boolean)}
	 * @param wsResources collection of {@link IResource} objects
	 */
	public void loadNewResources(Collection<IResource> wsResources) {
		ArrayList newConfigFiles = new ArrayList();
		for (Iterator iter = wsResources.iterator(); iter.hasNext();) {
			Object wsResource = (Object) iter.next();
			if(wsResource instanceof IResource) {
				IResource wsRes = (IResource) wsResource;
				IPath loc = wsRes.getLocation();
				String configFile;
				if(loc != null && configFolderPath != null 
						&& MultiFileSaveUtil.DEFAULT_FILE_EXTENSION.equalsIgnoreCase("." + loc.getFileExtension()) //$NON-NLS-1$
						&& configFolderPath.isPrefixOf(loc)
						&& !FileManager.getInstance().isTeamPrivate(configFile = loc.toString())) {
					newConfigFiles.add(configFile);
				}
			}
		}
		
		// load new configurations
		//
		for (Iterator iter = newConfigFiles.iterator(); iter.hasNext();) {
			String configFile = (String) iter.next();
			loadConfiguration(new File(configFile));
		}
	}

	/**
	 * Special handling for MethodConfiguration since MethodLibrary will no
	 * longer keeps the references to MethodConfigurations and their files. Any
	 * XMI file under folder ./configurations and its subfolders will be treated
	 * as a configuration file. They will be loaded and added to MethodLibrary
	 * as its configurations.
	 * @return TODO
	 */
	protected Collection<Resource> loadConfigurations() {
		MethodLibrary lib = getMethodLibrary();
		File configDir = new File(new File(lib.eResource().getURI()
				.toFileString()).getParent(),
				MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME);
		return loadConfigurations(configDir);
	}
	
	/**
	 * Loads method configurations from the specified directory.
	 * 
	 * @param configDir
	 * @return TODO
	 */
	protected Collection<Resource> loadConfigurations(File configDir) {
		ArrayList<Resource> resources = new ArrayList<Resource>();
		Iterator dirIter = MultiFileSaveUtil.listConfigFiles(configDir);
		HashSet<File> configFiles = new HashSet<File>();
		while (dirIter.hasNext()) {
			File configFile = (File) dirIter.next();
			if(configFile.isFile()) {
				configFiles.add(configFile);
			}
		}
		MethodLibrary lib = getMethodLibrary();
		for (Iterator iter = lib.getPredefinedConfigurations().iterator(); iter
				.hasNext();) {
			MethodConfiguration config = (MethodConfiguration) iter.next();
			File file = new File(config.eResource().getURI().toFileString());
			if (configFiles.contains(file)) {
				configFiles.remove(file);
			}
		}

		for (Iterator iter = configFiles.iterator(); iter.hasNext();) {
			File file = (File) iter.next();
			Resource resource = loadConfiguration(file);
			if(resource != null) {
				resources.add(resource);
			}
		}
		return resources;
	}

	protected Resource loadConfiguration(File configFile) {
		try {
			MethodLibrary lib = getMethodLibrary();
			URI uri = URI.createFileURI(configFile.getCanonicalPath());
			Resource resource = super.getResource(uri, true);
			if (resource != null) {
				MethodElement e = PersistenceUtil
						.getMethodElement(resource);
				if (e instanceof MethodConfiguration) {
					if(PersistenceUtil.hasDuplicateGUID(e, lib.getPredefinedConfigurations())) {
						PersistencePlugin.getDefault().getLogger().logError(
								NLS.bind(PersistenceResources.loadConfiguration_couldNotLoad_logMsg, configFile));
					}
					else {
						lib.getPredefinedConfigurations().add(e);
						return resource;
					}
				} else {
					PersistencePlugin.getDefault().getLogger().logError(
							NLS.bind(PersistenceResources.loadConfiguration_notConfigFile_logMsg, configFile)
							);
				}
				resource.unload();
				getResources().remove(resource);
			}
		} catch (Exception e) {
			PersistencePlugin.getDefault().getLogger().logError(e);
		}
		return null;
	}

	/**
	 * @param string
	 */
	protected void handleException(Object err) {
		if (err instanceof Throwable) {
			PersistencePlugin.getDefault().getLogger().logError((Exception)err);
		} else {
			PersistencePlugin.getDefault().getLogger().logError(err.toString());
		}
		if(MultiFileSaveUtil.DEBUG) {
			if (err instanceof Throwable) {
				((Exception) err).printStackTrace();
			} else {
				System.err.println(err.toString());
			}
		}
	}

	public void reset() {
		if (uriConverter instanceof MultiFileURIConverter) {
			((MultiFileURIConverter) uriConverter).dispose();
		}
		uriConverter = null;
		boolean notify = eDeliver();
		boolean reportError = REPORT_ERROR;
		boolean refresh = RefreshJob.getInstance().isEnabled();
		try {
			if(RefreshJob.getInstance().getResourceSet() == this) {
				RefreshJob.getInstance().setEnabled(false);
				RefreshJob.getInstance().reset();
			}
			eSetDeliver(false);
			REPORT_ERROR = false;
			markerMananger.setEnabled(false);
			markerMananger.clearAll();

			for (Iterator iter = new ArrayList(getResources()).iterator(); iter
					.hasNext();) {
				Resource resource = (Resource) iter.next();
				try {
					resource.unload();
				} catch (Exception e) {
					// System.err.println("Error unloading resource: " +
					// resource.getURI());
					// e.printStackTrace();
				}
			}

			clearErrors();
		} finally {
			eSetDeliver(notify);
			REPORT_ERROR = reportError;
			markerMananger.setEnabled(true);
			if(RefreshJob.getInstance().getResourceSet() == this) {
				RefreshJob.getInstance().setEnabled(refresh);
			}
		}

		if (guidToMethodElementMap != null) {
			guidToMethodElementMap.clear();
		}

		getResources().clear();

		if (URIToTempURIMap != null) {
			URIToTempURIMap.clear();
		}

		MultiFileXMIResourceImpl.clearDetachedEObjectToIDMap();
	}

	private void clearErrors() {
		// clear all markers
		markerMananger.clearAll();
	}

	public MethodLibrary loadLibrary(String path) throws Exception {
		long begin = System.currentTimeMillis();

		reset();

		long afterReset = System.currentTimeMillis();
		
		if (MultiFileSaveUtil.DEBUG) {
			System.out.println("Reset time: " + (afterReset - begin)); //$NON-NLS-1$
		}

		MethodLibrary lib = loadLibraryWithoutReset(path);

		if (MultiFileSaveUtil.DEBUG) {
			System.out
					.println("Load time: " + (System.currentTimeMillis() - begin)); //$NON-NLS-1$
		}

		if (MultiFileSaveUtil.DEBUG) {
			// check if any resource is marked as modified after loading
			//
			System.err.println("Modified resources after loading:"); //$NON-NLS-1$
			for (Iterator iter = getResources().iterator(); iter.hasNext();) {
				Resource resource = (Resource) iter.next();
				if (resource.isModified()) {
					System.err.println("  " + resource.getURI()); //$NON-NLS-1$
				}
			}
		}

		return lib;
	}
	
	protected Resource loadLibraryResource(String path) {
		URI uri = URI.createFileURI(path);
		Resource res = super.getResource(uri, true);
		if (!res.getErrors().isEmpty()) {
			StringBuffer strBuf = new StringBuffer();
			strBuf.append(PersistenceResources.loadLibraryError_msg);
			for (Iterator iter = res.getErrors().iterator(); iter.hasNext();) {
				Resource.Diagnostic error = (Resource.Diagnostic) iter
						.next();
				strBuf.append(NLS.bind(
						PersistenceResources.loadLibraryError_details,
						(new Object[] { String.valueOf(error.getLine()),
								String.valueOf(error.getColumn()),
								error.getMessage() })));
			}
			String msg = strBuf.toString();
			CommonPlugin.INSTANCE.log(msg);
			if(MultiFileSaveUtil.DEBUG) {
				System.err.println(msg);
			}
		}
		return res;
	}

	public MethodLibrary loadLibraryWithoutReset(String path) throws Exception {
		loading = true;

		// no refresh during load
		//
		boolean b = RefreshJob.getInstance().isEnabled();
		if(RefreshJob.getInstance().getResourceSet() == this) {
			RefreshJob.getInstance().setEnabled(false);
			RefreshJob.getInstance().reset();
		}
		
		// defer adding markers during load
		//
		boolean autoScheduled = markerMananger.isAutoScheduled();
		markerMananger.setAutoScheduled(false);
		try {		
			File libFile = new File(path);
			configFolderPath = new Path(new File(libFile.getParentFile(),
					MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME).getCanonicalPath());
			libFolderPath = new Path(libFile.getParentFile().getCanonicalPath());
			Resource res = loadLibraryResource(libFile.getCanonicalPath()); 
			try {
				initialize(true);
				
				// Set modified flag of library resource to false in case it had been modified during initialization
				//
				if(res != null) {
					res.setModified(false);
				}
				
				return getMethodLibrary();
			} catch (Exception e) {
				PersistencePlugin.getDefault().getLogger().logError(e);
				throw new Exception(NLS.bind(
						PersistenceResources.invalidLibraryFileError_msg, path));
			}
		} finally {
			if(RefreshJob.getInstance().getResourceSet() == this) {
				RefreshJob.getInstance().setEnabled(b);
			}
					
			markerMananger.setAutoScheduled(autoScheduled);
			markerMananger.start();
			
			loading = false;
		}
	}

	/**
	 * Loads opposite features for all loaded objects
	 */
	private void loadOppositeFeatures() {
		ArrayList oppositeFeatures = new ArrayList();
		for (Iterator iter = AssociationHelper.getPredefinedOppositeFeatures()
				.iterator(); iter.hasNext();) {
			OppositeFeature oppositeFeature = (OppositeFeature) iter.next();
			if (oppositeFeature.resolveOwner()) {
				oppositeFeatures.add(oppositeFeature);
			}
		}
		loadOppositeFeatures(oppositeFeatures);
	}

	/**
	 * Loads ResourceManager tree of the open library and connect any loaded
	 * MethodUnit to the library tree as well.
	 */
	private void loadResourceManagerTree() {
		long begin = 0;
		
		if(MultiFileSaveUtil.DEBUG) {
			begin = System.currentTimeMillis();
		}

		// disable logging unresolved proxies during loading resource manager
		// tree
		//
		markerMananger.setEnabled(false);

		MultiFileURIConverter uriConverter = (MultiFileURIConverter) getURIConverter();
		try {
			// this prevents uriConverter from loading resources while
			// normalizing URI
			//
			uriConverter.setResolveProxy(false);

			ResourceManager resMgr = getRootResourceManager();
			Iterator iterator = new AbstractTreeIterator(resMgr, false) {

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

				protected Iterator getChildren(Object object) {
					ResourceManager resMgr = (ResourceManager) object;
					return resMgr.getSubManagers().iterator();
				}

			};
			loadingResourceManagerTree = true;
			for (; iterator.hasNext(); iterator.next())
				;
		} finally {
			markerMananger.setEnabled(true);
			uriConverter.setResolveProxy(true);
			loadingResourceManagerTree = false;

			// Reporting of unnormalized URIs was disabled while loading
			// resource manager tree. Now we need
			// to go thru all the loaded objects to find proxies with
			// unnormalized URIs and report them
			//
			try {
				for (Iterator iter = new ArrayList(getGuidToMethodElementMap().values())
						.iterator(); iter.hasNext();) {
					InternalEObject o = (InternalEObject) iter.next();
					if (o.eIsProxy() && o.eContainer() != null) {
						URI uri = o.eProxyURI();
						URI normalizedURI = getURIConverter().normalize(uri);
						if (normalizedURI == null) {
							// this call will log error about unresolved proxy
							//
							((InternalEObject) o.eContainer()).eResolveProxy(o);
						}
					}
				}
			}
			catch(Exception e) {
				PersistencePlugin.getDefault().getLogger().logError(e);
			}
			
			if(MultiFileSaveUtil.DEBUG) {
				System.out
						.println("MultiFileResourceSetImpl.loadResourceManagerTree(): " + (System.currentTimeMillis() - begin)); //$NON-NLS-1$
			}
		}
	}

	protected ResourceManager getResourceManager() {
		return ((MultiFileURIConverter) getURIConverter()).getResourceManager();
	}

	protected EObject findEObjectInUnloadedResources(String id) {
		return findEObjectInUnloadedResources(getResourceManager(), id);
	}

	private EObject findEObjectInUnloadedResources(ResourceManager resMgr,
			String id) {
		for (Iterator iter = resMgr.getResourceDescriptors().iterator(); iter
				.hasNext();) {
			ResourceDescriptor desc = (ResourceDescriptor) iter.next();
			Resource resource = super.getResource(desc.getResolvedURI(), false);
			if (resource == null || !resource.isLoaded()) {
				try {
					resource = super.getResource(desc.getResolvedURI(), true);
				} catch (Exception e) {
					//
				}
				if (resource != null) {
					EObject eObject = resource.getEObject(id);
					if (eObject != null) {
						return eObject;
					}
				}
			}
		}
		for (Iterator iter = resMgr.getSubManagers().iterator(); iter.hasNext();) {
			EObject eObject = findEObjectInUnloadedResources(
					(ResourceManager) iter.next(), id);
			if (eObject != null)
				return eObject;
		}
		return null;
	}

	/**
	 * Gets object with the given id
	 */
	public EObject getEObject(String id) {
		// first, try to get the object from the cache guidToMethodElement
		//
		EObject eObject = (EObject) getGuidToMethodElementMap().get(id);
		if (eObject != null)
			return eObject;

		URI uri = MultiFileURIConverter.createURI(id).appendFragment(id);
		URI normalized = getURIConverter().normalize(uri);
		if (normalized == null) {
			// the object with the given id might not have direct resource,
			// hence, it does not have
			// its own ResourceDescriptor in ResourceManager tree.
			// go thru all unloaded resources, load them, and try to find the
			// object with the given id.
			//
			eObject = findEObjectInUnloadedResources(id);
			if (eObject == null && REPORT_ERROR) {
				handleException(NLS.bind(
						PersistenceResources.objNotFoundError_msg, id));
			}
			return eObject;
		}

		try {
			return getEObject(uri, true);
		} catch (RuntimeException e) {
			return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.ResourceSet#getEObject(org.eclipse.emf.common.util.URI,
	 *      boolean)
	 */
	public EObject getEObject(URI uri, boolean loadOnDemand) {
		return getEObject(null, uri, loadOnDemand);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.ResourceSet#createResource(org.eclipse.emf.common.util.URI)
	 */
	public Resource createResource(URI uri) {
		Resource result = doCreateResource(uri);
		result.setTrackingModification(true);
		getResources().add(result);
		return result;
	}
	
	protected Resource doCreateResource(URI uri) {
		return new MultiFileXMIResourceImpl(uri);
	}

	private static boolean backupRequired(Map options) {
		Boolean backup = (Boolean) options
				.get(MultiFileXMISaveImpl.BACK_UP_BEFORE_SAVE);
		return backup != null && backup.booleanValue();
	}

	private void backup(Resource res) {
		try {
			if (res.getContents().isEmpty())
				return;
			Object object = res.getContents().get(0);
			if (!(object instanceof MethodLibrary
					|| object instanceof ResourceManager || object instanceof MethodPlugin))
				return;

			MethodLibrary library = getMethodLibrary();
			String backupDir = new File(library.eResource().getURI()
					.toFileString()).getParent()
					+ File.separator + ".bak"; //$NON-NLS-1$
			SimpleDateFormat dateFormatter = new SimpleDateFormat(
					"yyMMddHHmmss.S"); //$NON-NLS-1$
			if (res == library.eResource()) {
				DateFormat.getInstance().format(
						Calendar.getInstance().getTime());
				File backupFile = new File(backupDir,
						MultiFileSaveUtil.DEFAULT_LIBRARY_MODEL_FILENAME
								+ '_'
								+ dateFormatter.format(Calendar.getInstance()
										.getTime()));
				if (!backupFile.getParentFile().exists()) {
					backupFile.getParentFile().mkdirs();
				}
				FileUtil.moveFile(new File(res.getURI().toFileString()), backupFile);
			} else {
				String relativePath = res.getURI().deresolve(
						library.eResource().getURI()).toFileString();
				File backupFile = new File(backupDir, relativePath
						+ '_'
						+ dateFormatter
								.format(Calendar.getInstance().getTime()));
				if (!backupFile.getParentFile().exists()) {
					backupFile.getParentFile().mkdirs();
				}
				FileUtil.moveFile(new File(res.getURI().toFileString()), backupFile);
			}
		} catch (Exception e) {
			handleException(e);
			handleException(NLS.bind(PersistenceResources.backupError_msg, res));
		}
	}

	void removeURIMappings(EObject eObj, Set modifiedResources) {
		ResourceManager resMgr = MultiFileSaveUtil.getResourceManager(eObj
				.eResource());
		if (resMgr != null && resMgr.eContainer() != null) {
			EcoreUtil.remove(resMgr);
		}
		resMgr = getRootResourceManager();
		if(resMgr != null) {
			ResourceDescriptor desc = MultiFileSaveUtil.findResourceDescriptor(
					resMgr, MultiFileSaveUtil.getGuid(eObj),
					null, true);
			if (desc != null) {
				if (modifiedResources != null && desc.eResource() != null) {
					modifiedResources.add(desc.eResource());
				}
				EcoreUtil.remove(desc);
			}
		}
	}

	protected void cleanUp(Resource removedResource) throws IOException {
		cleanUp(removedResource, null);
	}

	// protected void cleanUp(EObject obj, Set modifiedResources) {
	// try {
	// // remove all the URI mappings
	// //
	// removeURIMappings(obj, modifiedResources);
	// }
	// finally {
	// Resource resource = obj.eResource();
	// if(resource != null && resource.getContents().contains(obj)) {
	// resource.unload();
	// getResources().remove(resource);
	// }
	// }
	// }

	void cleanUp(Resource removedResource, Set modifiedResources)
			throws IOException {
		try {
			//
			if (removedResource.getContents().isEmpty()) {
				removedResource.unload();
				try {
					removedResource.load(null);
				} catch (FileNotFoundException e) {
					// the file might already be deleted, moved or never
					// creared.
					//
					return;
				}
			}

			EObject obj = PersistenceUtil.getMethodElement(removedResource);

			// if(obj == null) return;
			// boolean cleanFolder;
			// if(obj instanceof MethodPlugin) {
			// cleanFolder = true;
			// }
			// else {
			// cleanFolder = false;
			// }

			// MultiFileURIConverter umaUriConverter =
			// ((MultiFileURIConverter)getURIConverter());
			// umaUriConverter.getResourceManager().removeResourceDescriptor(removedResource.getURI(),
			// cleanFolder);

			// remove all the URI mappings
			//
			removeURIMappings(obj, modifiedResources);

			// if(obj instanceof ProcessPackage) {
			// cleanUpResourceDescriptors((ProcessPackage)obj);
			// }

			removedResource.unload();
		} finally {
			getResources().remove(removedResource);
			URI oldURI = ((MultiFileXMIResourceImpl) removedResource)
					.getOldURI();
			if (oldURI != null) {
				getURIToTempURIMap().remove(oldURI);
			}
		}
	}

	private void cleanUp(ProcessPackage procPkg) {
		// remove ContentDescription of all ProcessElements in this
		// ProcessPackage
		//
		removeContentDescriptions(procPkg);

		EcoreUtil.remove(procPkg);
	}

	/**
	 * @param procPkg
	 */
	private void removeContentDescriptions(ProcessPackage procPkg) {
		for (Iterator iter = procPkg.getProcessElements().iterator(); iter
				.hasNext();) {
			ProcessElement element = (ProcessElement) iter.next();
			if (ContentDescriptionFactory.hasPresentation(element)
					&& element.getPresentation().eResource() != null) {
				removePresentation(element);
			}
		}

		for (Iterator iter = procPkg.getChildPackages().iterator(); iter
				.hasNext();) {
			Object pkg = iter.next();
			if (pkg instanceof ProcessPackage) {
				removeContentDescriptions((ProcessPackage) pkg);
			}
		}
	}

	/**
	 * @param element
	 */
	private void removePresentation(ProcessElement element) {
		Resource resource = element.getPresentation().eResource();
		resource.getContents().remove(element.getPresentation());
	}

	private boolean save(Collection resources, Map options, boolean prepareSave)
			throws Exception {
		if (options == null) {
			options = getDefaultSaveOptions();
		}

		Set modifiedResources = new HashSet();
		options.put(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET,
				modifiedResources);
		try {
			for (Iterator iter = resources.iterator(); iter.hasNext();) {
				Resource res = (Resource) iter.next();
				save(res, options, prepareSave);
			}
			saveModifiedResources(options);
			return true;
		} finally {
			options.remove(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET);
		}
	}

	boolean save(Resource res, Map options, boolean prepareSave)
			throws Exception {
		Set modifiedResources = (Set) options
				.get(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET);
		TxRecord txRecord = (TxRecord) options
				.get(MultiFileXMISaveImpl.TX_RECORD);
		List resourcesToCommit = txRecord != null ? txRecord
				.getResourcesToCommit() : null;

		try {
			MethodElement eObj = PersistenceUtil.getMethodElement(res);
			if (eObj != null) {
				if (prepareSave) {
					if (eObj instanceof ProcessComponent) {
						ProcessComponent procComp = (ProcessComponent) eObj;
						Resource content = procComp.getProcess() != null
								&& ContentDescriptionFactory
										.hasPresentation(procComp.getProcess()) ? procComp
								.getProcess().getPresentation().eResource()
								: null;
						boolean alreadyModified = content != null
								&& content.isModified();
						prepareSave(procComp);
						if (content != null && content.isModified()
								&& !alreadyModified) {
							// content is modified as result of prepareSave(),
							// it needs to be saved after model is saved
							//
							modifiedResources.add(content);
						}
					}
					else if (eObj instanceof MethodPlugin) {
						MultiFileSaveUtil.addResourceManager(res);
					}
				}
				if (res.isModified()) {
					// System.out.println("----> Start saving " + res);
					boolean backupRequired = backupRequired(options);
					if (backupRequired) {
						// back up resource before saving
						//
						backup(res);
					}

					if (resourcesToCommit != null) {
						((MultiFileXMIResourceImpl) res).setTempURI(txRecord
								.getTxID());
						resourcesToCommit.add(res);
					}

					MultiFileSaveUtil.save(res, options);

					// System.out.println("<---- Saved resource: " + res);

					return true;
				}
			}
		} catch (Exception exception) {
			handleException(exception);
			throw exception;
		}

		return false;
	}

	/**
	 * Save a resource of this resource set with the given save options
	 * 
	 * @param res
	 * @param options
	 * @return <code>true</code> if there is at least a resource has been saved in this call
	 * @throws Exception
	 */
	public boolean save(Resource res, Map options) throws Exception {
//		// clear all error markers for this resource
//		//
//		markerMananger.clearMarkers(res);

		if (res == null || res.getContents().isEmpty())
			return false;

		if (options == null) {
			options = getDefaultSaveOptions();
		}

		Set modifiedResources = new HashSet();
		options.put(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET,
				modifiedResources);
		boolean notFailSafe = options.get(MultiFileXMISaveImpl.TX_RECORD) == null;
		try {
			Collection savedResources = null;
			if(notFailSafe) {
				savedResources = new ArrayList();
			}
			boolean ret = save(res, options, true);
			if(ret && notFailSafe) {
				savedResources.add(res);
			}
			Collection collection = saveModifiedResources(options);
			if(!collection.isEmpty()) {
				ret = true;
				if(notFailSafe) {
					savedResources.addAll(collection);
				}
			}
			
			if(notFailSafe && ret) {
				// update resource cached timestamps
				//
				for (Iterator iter = savedResources.iterator(); iter.hasNext();) {
					Object resource = iter.next();
					if(resource instanceof MultiFileXMIResourceImpl) {
						((MultiFileXMIResourceImpl)resource).updateTimeStamps();
					}
				}								
			}
			
			return ret;
		} finally {
			options.remove(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET);
		}
	}

	/**
	 * Saves only the modified resources in this resource set.
	 * 
	 * @param options
	 */
	public void save(Map options) throws LibraryResourceException {
		try {
			save(options, false, true);
		} catch (Exception e) {
			if(e instanceof RuntimeException) {
				throw (RuntimeException)e;
			}
			throw new LibraryResourceException(e);
		}
	}

	/**
	 * 
	 * @param options
	 * @return resources that had been saved by this call
	 * @throws LibraryResourceException 
	 */
	Collection saveModifiedResources(Map options) throws LibraryResourceException {
		Set modifiedResources = (Set) options
				.get(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET);
		TxRecord txRecord = (TxRecord) options
				.get(MultiFileXMISaveImpl.TX_RECORD);
		List resourcesToCommit = txRecord != null ? txRecord
				.getResourcesToCommit() : null;
		if (modifiedResources == null)
			return Collections.EMPTY_LIST;
		boolean backupRequired = backupRequired(options);
		boolean checkModify = MultiFileXMISaveImpl.checkModifyRequired(options);
		Collection savedResources = new ArrayList();
		while (!modifiedResources.isEmpty()) {
			List<Resource> resourcesToSave = new ArrayList<Resource>(modifiedResources);
			
			modifiedResources.clear();
			if (checkModify) {
				checkModify(resourcesToSave);
				if(resourcesToCommit != null) {
					// check for out-of-synch only in fail-safe saving for now
					//
					MultiFileSaveUtil.checkOutOfSynch(resourcesToSave, options);
				}
			}
			for(Iterator iter = resourcesToSave.iterator(); iter.hasNext();) {
				Resource resource = (Resource) iter.next();
				// if(resource.isModified()) {
				if (backupRequired) {
					// back up resource before saving
					//
					backup(resource);
				}

				if (resourcesToCommit != null) {
					((MultiFileXMIResourceImpl) resource).setTempURI(txRecord
							.getTxID());
					resourcesToCommit.add(resource);
				}

				if(MultiFileSaveUtil.save(resource, options)) {
					savedResources.add(resource);
				}
				// }
			}
		}
		return savedResources;
	}

	/**
	 * 
	 * @param options
	 * @param saveAll
	 *            if true, force saving all the resources even if they are not
	 *            modified.
	 * @throws Exception
	 */
	public void save(Map options, boolean saveAll) throws Exception {
		save(options, saveAll, false);
	}
	
	protected void save(Map options, boolean saveAll, boolean failSafe)
			throws Exception {
		if (options == null) {
			options = new HashMap(getDefaultSaveOptions());
		}

		MethodLibrary library = getMethodLibrary();
		MultiFileSaveUtil.setGuid(library);

		prepareSave(library);

		// do clean-up this resource set before saving
		//
		cleanUp();

		MultiFileURIConverter umaUriConverter = ((MultiFileURIConverter) getURIConverter());
		umaUriConverter.setLibraryURIs(library);

		Set modifiedResources = new HashSet();
		options.put(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET,
				modifiedResources);
		MethodLibraryPersister.FailSafePersister persister = null;
		if (failSafe) {
			persister = MethodLibraryPersister.INSTANCE
					.getFailSafePersister(options);
			options = persister.getSaveOptions();
		}
		try {
			List list = getResources();
			int size = list.size();
			// System.out.println("Start saving " + size + " loaded resources: "
			// + list);
			// System.out.println();
			boolean backupRequired = backupRequired(options);
			List saveResources = new ArrayList();
			List moveResources = new ArrayList();
			for (int i = 0; i < size; i++) {
				Resource res = (Resource) list.get(i);

				 if (res.isModified() && 
						 MultiFileSaveUtil.adjustLocationRequired((MultiFileXMIResourceImpl) res)) {
					 moveResources.add(res);
				 }

				MethodElement eObj = PersistenceUtil.getMethodElement(res);
				if (eObj != null && eObj instanceof MethodElement) {
					if (saveAll || res.isModified()) {
//						// System.out.println("----> Start saving " + res);
//						if (failSafe) {
//							saveResources.add(res);
//						} else {
//							if (backupRequired) {
//								// back up resource before saving
//								//
//								backup(res);
//							}
//
//							if(MultiFileSaveUtil.save(res, options)) {
//								savedResources.add(res);
//								if(res instanceof MultiFileXMIResourceImpl) {
//									((MultiFileXMIResourceImpl)res).updateTimeStamps();
//								}
//							}
//						}
//						// System.out.println("<---- Saved resource: " + res);
						
						saveResources.add(res);
					}
				}
			}

			if(!saveResources.isEmpty()) {
				Resource libResource = getMethodLibraryResource();
				if(!saveResources.contains(libResource) && PersistenceUtil.checkToolVersion(libResource) != 0) {
					saveResources.add(libResource);
				}
				if(MultiFileXMISaveImpl.checkModifyRequired(options)) {
					checkModify(saveResources);
				}
				if (failSafe) {
					try {
						save(saveResources, options, false);
						persister.commit();
						persister.adjustLocation(moveResources);
					} catch (Exception e) {
						persister.rollback();
						throw e;
					}
				} else {
					for (Iterator iter = saveResources.iterator(); iter
							.hasNext();) {
						Resource resource = (Resource) iter.next();
						if(MultiFileSaveUtil.save(resource, options)) {
							if(resource instanceof MultiFileXMIResourceImpl) {
								((MultiFileXMIResourceImpl)resource).updateTimeStamps();
							}
						}
					}
					for (Iterator iter = moveResources.iterator(); iter.hasNext();) {
						Resource resource = (Resource) iter.next();
						MultiFileSaveUtil.adjustLocation(resource,
								modifiedResources);
					}
					Collection saved = saveModifiedResources(options);
					if (saved != null) {
						for (Iterator iter = saved.iterator(); iter.hasNext();) {
							Resource resource = (Resource) iter.next();
							if(resource instanceof MultiFileXMIResourceImpl) {
								((MultiFileXMIResourceImpl)resource).updateTimeStamps();
							}
						}
					}
				}
			}
		} catch (Exception exception) {
			handleException(exception);
			throw exception;
		} finally {
			options.remove(MultiFileXMISaveImpl.MODIFIED_RESOURCE_SET);
		}
	}

	/**
	 * Saves the open library under a new location
	 * 
	 * @param newLocation
	 *            directory to save the open library to
	 * @param if
	 *            true, regenerateGUID regenerate GUID for all MethodElements in
	 *            the open library
	 */
	public void saveAs(String newLocation, boolean regenerateGUID,
			IProgressMonitor monitor) throws Exception {
		MethodLibrary lib = getMethodLibrary();
		if (lib == null)
			return;

		// load all the resources in memory
		//
		if (monitor != null)
			monitor.setTaskName(PersistenceResources.loadResourcesTask_name);
		for (Iterator iter = lib.eAllContents(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			if (regenerateGUID && element instanceof MethodElement) {
				((MethodElement) element).setGuid(UmaUtil.generateGUID());
			}
			for (Iterator iterator = element.eCrossReferences().iterator(); iterator
					.hasNext();) {
				iterator.next();
			}
		}

		// change URI of all loaded resources for new location
		//
		URI oldDir = URI.createFileURI(new File(lib.eResource().getURI()
				.toFileString()).getParent()
				+ File.separator);
		URI newDir = URI.createFileURI(newLocation + File.separator);
		for (Iterator iter = getResources().iterator(); iter.hasNext();) {
			Resource resource = (Resource) iter.next();
			resource.setURI(resource.getURI().replacePrefix(oldDir, newDir));
		}

		// clear the ResourceManager
		//
		ResourceManager resMgr = ((MultiFileURIConverter) getURIConverter())
				.getResourceManager();
		if (resMgr != null) {
			resMgr.getResourceDescriptors().clear();
		}

		if (monitor != null)
			monitor.setTaskName(PersistenceResources.saveLibraryTask_name);
		save(null, true);
	}
	
	protected boolean unloadWithoutRemove(MultiFileXMIResourceImpl resource) {
		MethodElement e = PersistenceUtil.getMethodElement(resource);
		resource.unloadWithoutRemove();
		if(e instanceof MethodConfiguration) {
			MethodLibrary lib = getMethodLibrary();
			if(lib != null) {
				lib.getPredefinedConfigurations().remove(e);
			}
		}
		return true;
	}

	/**
	 * @throws IOException
	 * 
	 */
	private void cleanUp() throws IOException {
		MethodLibrary library = getMethodLibrary();
		List removedResources = new ArrayList();

		List list = getResources();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			Resource res = (Resource) list.get(i);
			boolean remove = false;
			if (res.getContents().isEmpty()) {
				System.out
						.println("MultiFileResourceSetImpl.cleanUp(): empty resource: " + res); //$NON-NLS-1$
				remove = true;
			} else {
				MethodElement eObj = PersistenceUtil.getMethodElement(res);
				if (eObj == null
						|| (eObj != library && eObj.eContainer() == null)) {
					if (eObj == null) {
						System.out
								.println("MultiFileResourceSetImpl.cleanUp(): resource without any MethodElement: " + res); //$NON-NLS-1$
						remove = true;
					}
					// some resources might be loaded directly, not thru its
					// container. Therefore, we cannot assume
					// that a object without a container in a loaded resource is
					// a removed object.
					//
					else if (eObj != library && eObj.eContainer() == null) {
						System.out
								.println("MultiFileResourceSetImpl.cleanUp(): resource without a container: " + res); //$NON-NLS-1$
					}
				}
			}
			if (remove) {
				// This is a removed object. Add its path to the list for
				// removing its files later.
				//
				removedResources.add(res);
			}
		}

		// do clean-up
		//
		System.out
				.println("MultiFileResourceSetImpl.cleanUp(): removed resources: " + removedResources); //$NON-NLS-1$

		for (Iterator iter = removedResources.iterator(); iter.hasNext();) {
			Resource res = (Resource) iter.next();

			try {
				// remove ResourceDescriptor of the removed resource
				//
				cleanUp(res);
			} catch (Exception e) {
				handleException(e);
			}
		}

		// getResources().removeAll(removedResources);
	}
	
	/**
	 * Prepares the library for saving
	 */
	private void prepareSave(MethodLibrary library) {
		// check if the library already has a ResourceManager
		// if not, create ResourceManager for it
		//
		MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) library
				.eResource();
		ResourceManager libResMgr = MultiFileSaveUtil.addResourceManager(resource);
		if(libResMgr != null) {
			MultiFileSaveUtil.registerWithResourceManager(libResMgr, library,
					resource.getFinalURI());
		}

		List models = library.getMethodPlugins();
		int size = models.size();
		for (int i = 0; i < size; i++) {
			prepareSave((MethodPlugin) models.get(i));
		}

		for (int i = 0; i < size; i++) {
			cleanUp((MethodPlugin) models.get(i));
		}
	}

	private static void cleanUp(MethodPlugin plugin) {
		for (int i = 0; i < PROCESS_PACKAGE_PATHS.length; i++) {
			ProcessPackage pkg = (ProcessPackage) UmaUtil.findMethodPackage(
					plugin, PROCESS_PACKAGE_PATHS[i]);
			if (pkg != null) {
				cleanUpProcesses(pkg);
			}
		}
	}

	private void prepareSave(MethodPlugin model) {
		for (int i = 0; i < PROCESS_PACKAGE_PATHS.length; i++) {
			ProcessPackage pkg = (ProcessPackage) UmaUtil.findMethodPackage(
					model, PROCESS_PACKAGE_PATHS[i]);
			if (pkg != null) {
				prepareSave(pkg);
			}
		}
	}

	/**
	 * Removes process packages of unused activities.
	 * 
	 * @param pkg
	 */
	private static void cleanUpProcesses(ProcessPackage pkg) {
		List list = pkg.getChildPackages();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			Object obj = list.get(i);
			if (obj instanceof ProcessComponent) {
				ProcessComponent procComp = (ProcessComponent) obj;
				List packages = new ArrayList();
				for (Iterator iter = procComp.getChildPackages().iterator(); iter
						.hasNext();) {
					Object element = (Object) iter.next();
					if (element instanceof ProcessPackage) {
						getRemovedPackages((ProcessPackage) element, packages);
					}
				}
				for (Iterator iterator = packages.iterator(); iterator
						.hasNext();) {
					EcoreUtil.remove((EObject) iterator.next());
				}
			}
		}
	}

	private static void getRemovedPackages(ProcessPackage pkg,
			List removedPackages) {
		// find activity
		//
		Activity act = getActivity(pkg);

		if (act == null || getParent(act) == null) {
			// Invalid process package. It does not contain any activity.
			// Add it to the list of packages to be removed.
			//
			removedPackages.add(pkg);
		} else {
			for (Iterator iter = pkg.getChildPackages().iterator(); iter
					.hasNext();) {
				Object element = (Object) iter.next();
				if (element instanceof ProcessPackage) {
					getRemovedPackages((ProcessPackage) element,
							removedPackages);
				}
			}
		}
	}

	private static Activity getActivity(ProcessPackage pkg) {
		// find activity
		//
		Activity act = null;
		for (Iterator iter = pkg.getProcessElements().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof Activity) {
				act = (Activity) element;
				break;
			}
		}
		return act;
	}

	private static Object getParent(BreakdownElement e) {
		// ItemProviderAdapter adapter = (ItemProviderAdapter)
		// TngUtil.getAdapter(e, IBSItemProvider.class);
		// return adapter == null ? null : adapter.getParent(e);

		return UmaUtil.getParentActivity(e);
	}

	/**
	 * Creates process package for those activities that still don't belong to
	 * any process package.
	 */
	private void prepareSave(ProcessPackage pkg) {
		List list = pkg.getChildPackages();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			Object obj = list.get(i);
			if (obj instanceof ProcessComponent) {
				prepareSave((ProcessComponent) obj);
			}
		}
	}

	private void prepareSave(ProcessComponent procComp) {
		Process proc = procComp.getProcess();
		if (proc != null) {
			// associateAllAdapters(proc);
			prepareSave(proc);

			cleanUpDanglingDescriptors(procComp);

			List danglingPkgs = new ArrayList();
			for (Iterator iter = new ArrayList(procComp.getChildPackages())
					.iterator(); iter.hasNext();) {
				Object element = (Object) iter.next();
				if (element instanceof ProcessPackage) {
					ProcessPackage pkg = (ProcessPackage) element;
					reorganize(pkg, danglingPkgs);
				}
			}

			// clean up dangling ProcessPackages
			//
			for (Iterator iter = danglingPkgs.iterator(); iter.hasNext();) {
				cleanUp((ProcessPackage) iter.next());
			}

		}
	}

	// /**
	// * @param activity
	// */
	// private static void associateAllAdapters(Activity activity) {
	// AdapterFactory adapterFactory =
	// TngAdapterFactory.INSTANCE.getWBS_ComposedAdapterFactory();
	// ItemProviderAdapter adapter = (ItemProviderAdapter)
	// adapterFactory.adapt(activity, ITreeItemContentProvider.class);
	// for (Iterator iter = adapter.getChildren(activity).iterator();
	// iter.hasNext();) {
	// Object element = iter.next();
	// if(element instanceof Activity) {
	// associateAllAdapters((Activity) element);
	// }
	// }
	// }

	/**
	 * @param activity
	 */
	private static void prepareSave(Activity activity) {
		ProcessPackage parentPkg = (ProcessPackage) activity.eContainer();
		List elements = activity.getBreakdownElements();

		// add new descriptors and other non-activity breakdown elements of the
		// activity to its process package
		//
		for (Iterator iter = elements.iterator(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			if (!(element instanceof Activity) && element.eContainer() == null) {
				parentPkg.getProcessElements().add(element);
			}
		}

		// add new WorkOrder objects or remove unused WorkOrder objects of this
		// activity
		//
		for (Iterator iter = activity.getLinkToPredecessor().iterator(); iter
				.hasNext();) {
			WorkOrder workOrder = (WorkOrder) iter.next();
			if (workOrder.eContainer() == null) {
				if (workOrder.getPred() != null
						&& getParent(workOrder.getPred()) != null) {
					parentPkg.getProcessElements().add(workOrder);
				}
			} else {
				if (workOrder.getPred() == null
						|| getParent(workOrder.getPred()) == null) {
					if (MultiFileSaveUtil.DEBUG) {
						System.err.println("Invalid WorkOrder: " + workOrder); //$NON-NLS-1$
					}
					parentPkg.getProcessElements().remove(workOrder);
				}
			}
		}

		// removed unused diagrams
		//
		for (Iterator iter = parentPkg.getDiagrams().iterator(); iter.hasNext();) {
			Diagram diagram = (Diagram) iter.next();
			SemanticModelBridge bridge = diagram.getSemanticModel();
			if (bridge instanceof UMASemanticModelBridge) {
				MethodElement element = ((UMASemanticModelBridge) bridge)
						.getElement();
				if (element instanceof Activity
						&& (!(element instanceof Process) && getParent((Activity) element) == null)) {
					iter.remove();
				}
			}
		}

		int size = elements.size();
		for (int i = 0; i < size; i++) {
			Object e = elements.get(i);
			if (e instanceof Activity) {
				Activity act = (Activity) e;
				if (act.eContainer() == null) {
					ProcessPackage pkg = UmaFactory.eINSTANCE
							.createProcessPackage();
					pkg.setName(act.getName());
					pkg.getProcessElements().add(act);
					List descriptors = new ArrayList();
					for (int j = 0; j < act.getBreakdownElements().size(); j++) {
						Object obj = act.getBreakdownElements().get(j);
						if (obj instanceof Descriptor) {
							descriptors.add(obj);
						}
					}
					pkg.getProcessElements().addAll(descriptors);

					parentPkg.getChildPackages().add(pkg);
					// System.out.println("Process package created for activity:
					// '" + act.getName() + "'");
				}
				prepareSave(act);
			}
		}
	}

	private static void cleanUpDanglingDescriptors(ProcessPackage pkg) {
		for (Iterator iter = pkg.getProcessElements().iterator(); iter
				.hasNext();) {
			Object element = iter.next();
			if (element instanceof BreakdownElement
					&& ((BreakdownElement) element).getSuperActivities() == null) {
				boolean remove = false;
				if (element instanceof RoleDescriptor) {
					if (AssociationHelper.getTeamProfiles(
							(RoleDescriptor) element).isEmpty()) {
						remove = true;
					}
				} else if (element instanceof WorkProductDescriptor) {
					if (AssociationHelper.getDeliverableDescriptors(
							(WorkProductDescriptor) element).isEmpty()) {
						remove = true;
					}
				} else if (element instanceof TeamProfile) {
					if (((TeamProfile) element).getSuperTeam() == null) {
						remove = true;
					}
				} else {
					remove = true;
				}

				if (remove) {
					iter.remove();
				}
			}
		}
	}

	/**
	 * Moves the process packages to the right location in the tree if needed.
	 * 
	 * @param pkg
	 * @param danglingPkgs
	 */
	private void reorganize(ProcessPackage pkg, List danglingPkgs) {
		Activity act = getActivity(pkg);
		if (act == null)
			return;

		// make sure the package has the same name as the activity's name
		//
		if (!pkg.getName().equals(act.getName())) {
			pkg.setName(act.getName());
		}

		// check if the container of pkg is actually holding the parent activity
		// of act
		//
		EObject parentAct = (EObject) getParent(act);

		if (parentAct == null) {
			// cleanUpResourceDescriptors(pkg);
			// cleanUp(pkg);
			// return;
			danglingPkgs.add(pkg);
		} else if (parentAct != getActivity((ProcessPackage) pkg.eContainer())) {
			// move the package to the right location, under the process package
			// of parentAct
			//
			ProcessPackage parentPkg = (ProcessPackage) parentAct.eContainer();
			parentPkg.getChildPackages().add(pkg);
		}

		if (parentAct != null) {
			cleanUpDanglingDescriptors(pkg);
		}

		for (Iterator iter = pkg.getChildPackages().iterator(); iter.hasNext();) {
			Object element = (Object) iter.next();
			if (element instanceof ProcessPackage) {
				reorganize((ProcessPackage) element, danglingPkgs);
			}
		}
	}

	public Map getGuidToMethodElementMap() {
		if (guidToMethodElementMap == null) {
			guidToMethodElementMap = new HashMap();
		}
		return guidToMethodElementMap;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.notify.impl.BasicNotifierImpl#eNotify(org.eclipse.emf.common.notify.Notification)
	 */
	public void eNotify(Notification notification) {
		try {
			super.eNotify(notification);
		} catch (RuntimeException e) {
			CommonPlugin.INSTANCE
					.log("ERROR notifying changes: resourceSet=" + this + ", notification=" + notification); //$NON-NLS-1$ //$NON-NLS-2$
			CommonPlugin.INSTANCE.log(e);
			e.printStackTrace();
		}
	}

	public void addMarker(Exception e) {
		try {
			// insert problem marker
			//
			markerMananger.notifyException(e);
		} catch (RuntimeException ex) {
			CommonPlugin.INSTANCE.log(ex);
			if (MultiFileSaveUtil.DEBUG) {
				ex.printStackTrace();
			}
		}
	}

	public void setLoading(boolean b) {
		loading = b;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.ecore.IExceptionCollector#collect(java.lang.Exception)
	 */
	public void notifyException(Exception e) {
		if (loadingResourceManagerTree) {
			if (e instanceof ResolveException) {
				if (((ResolveException) e).exception() instanceof MultiFileIOException) {
					return;
				}
			}
		}
		try {
			addMarker(e);
		} catch (Exception ex) {
			//
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.ecore.IProxyResolutionListener#proxyResolved(java.lang.Object,
	 *      java.lang.Object)
	 */
	public void proxyResolved(Object proxy, Object resolved) {
		if(resolved instanceof MethodElement) {
			String guid = MultiFileSaveUtil.getGuid(resolved);
			if (guid != null) {
				getGuidToMethodElementMap().put(guid, resolved);
			}
		}
		markerMananger.proxyResolved(proxy, resolved);
	}

	private EObject getEObjectByGUID(String guid) {
		return (EObject) getGuidToMethodElementMap().get(guid);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.ecore.IUmaResourceSet#getEObject(org.eclipse.emf.ecore.EObject,
	 *      org.eclipse.emf.common.util.URI, boolean)
	 */
	public EObject getEObject(EObject resolver, URI uri, boolean loadOnDemand) {
		// long start;
		// if(MultiFileSaveUtil.PROFILE) {
		// start = System.currentTimeMillis();
		// }

		URI normalized = ((MultiFileURIConverter) getURIConverter()).normalize(
				uri, resolver);
		if (normalized == null) {
			// work-around to look up for object by its GUID in case it had been
			// moved to other resource
			//
			String guid = uri.fragment();
			EObject eObject = getEObjectByGUID(guid);
			if (eObject != null) {
				return eObject;
			}

			String msg = NLS.bind(PersistenceResources.normalizeURIError_msg,
					uri);
			throw new UnnormalizedURIException(msg);
		}
		Resource resource = getResource(normalized.trimFragment(), loadOnDemand);
		if (resource != null) {
			String fragment = normalized.fragment();
			if (fragment == null || fragment.length() == 0) {
				return PersistenceUtil.getMethodElement(resource);
			}
			EObject eObject = resource.getEObject(fragment);
			if (eObject == null && !fragment.equals(uri.authority())) {
				// work-around to look up for object by its GUID in case it had
				// been moved
				//
				return getEObjectByGUID(fragment);
			}
			return eObject;
		} else {
			return null;
		}

		// if(MultiFileSaveUtil.PROFILE) {
		//			
		// }
	}

	// /**
	// * @return Returns the exceptions.
	// */
	// public List getExceptions() {
	// return exceptions;
	// }

	public void loadOppositeFeatures(List oppositeFeatures) {
		int max = oppositeFeatures.size() - 1;
		if (max < 0) {
			return;
		}
		ArrayList elements = new ArrayList(getGuidToMethodElementMap().values());
		HashSet loadedElements = new HashSet();
		while (!elements.isEmpty()) {
			for (Iterator iter = elements.iterator(); iter.hasNext();) {
				Object obj = iter.next();
				if (obj instanceof MethodElement) {
					MethodElement element = (MethodElement) obj;
					for (int i = max; i > -1; i--) {
						EStructuralFeature eFeature = ((OppositeFeature) oppositeFeatures
								.get(i)).getTargetFeature();
						if (eFeature.getContainerClass().isInstance(element)) {
							if (eFeature.isMany()) {
								InternalEList list = (InternalEList) element
										.eGet(eFeature);
								if (!list.isEmpty()) {
									for (Iterator iterator = list.iterator(); iterator
											.hasNext();) {
										iterator.next();
									}
								}
							} else {
								element.eGet(eFeature);
							}
						}
					}
				}
			}

			// gets the newly loaded elements to load their opposite features
			//
			loadedElements.addAll(elements);
			elements = new ArrayList(getGuidToMethodElementMap().values());
			elements.removeAll(loadedElements);
		}
	}

	public void loadOppositeFeatures(List oppositeFeatures, Set deletedGUIDs) {
		int max = oppositeFeatures.size() - 1;
		if (max < 0) {
			return;
		}
		ArrayList elements = new ArrayList(getGuidToMethodElementMap().values());
		HashSet loadedElements = new HashSet();
		while (!elements.isEmpty()) {
			for (Iterator iter = elements.iterator(); iter.hasNext();) {
				Object obj = iter.next();
				if (obj instanceof MethodElement) {
					MethodElement element = (MethodElement) obj;
					MultiResourceEObject mrEObject = ((MultiResourceEObject) element);
					for (int i = max; i > -1; i--) {
						OppositeFeature oppositeFeature = ((OppositeFeature) oppositeFeatures
								.get(i));
						EStructuralFeature eFeature = oppositeFeature.getTargetFeature();
						if (eFeature.getContainerClass().isInstance(element)) {
							if (eFeature.isMany()) {
								InternalEList list = (InternalEList) element
										.eGet(eFeature);
								if (!list.isEmpty()) {
									boolean resolve = false;
									check_resolve: for (Iterator iterator = list
											.basicIterator(); iterator
											.hasNext();) {
										InternalEObject e = (InternalEObject) iterator
												.next();
										if (e.eIsProxy()) {
											String guid = e.eProxyURI()
													.fragment();
											if (deletedGUIDs.contains(guid)) {
												resolve = true;
												break check_resolve;
											}
										}
									}
									if (resolve) {
										Collection<Object> deletedElements = new HashSet<Object>();
										for (Iterator iterator = list
												.iterator(); iterator.hasNext();) {
											Object o = iterator.next();
											if(o instanceof MethodElement && deletedGUIDs.contains(((MethodElement) o).getGuid())) {
												deletedElements.add(o);
											}
										}
										for (Object e : deletedElements) {
											if(oppositeFeature.isMany()) {
												mrEObject.oppositeAdd(oppositeFeature, e);
											}
											else {
												mrEObject.getOppositeFeatureMap().put(oppositeFeature, e);
											}
										}										
									}
								}
							} else {
								Object value = element.eGet(eFeature, false);
								if (value instanceof InternalEObject) {
									InternalEObject e = (InternalEObject) value;
									if (e.eIsProxy()) {
										String guid = e.eProxyURI().fragment();
										if (deletedGUIDs.contains(guid)) {
											Object o = element.eGet(eFeature);
											if(oppositeFeature.isMany()) {
												mrEObject.oppositeAdd(oppositeFeature, o);
											}
											else {
												mrEObject.getOppositeFeatureMap().put(oppositeFeature, o);
											}
										}
									}
								}
							}
						}
					}
				}
			}
			// gets the newly loaded elements to load their opposite features
			//
			loadedElements.addAll(elements);
			elements = new ArrayList(getGuidToMethodElementMap().values());
			elements.removeAll(loadedElements);
		}
	}

	public boolean hasUnresolvedProxy() {
		return markerMananger.hasUnresolvedProxy();
	}

	protected Map getURIToTempURIMap() {
		if (URIToTempURIMap == null) {
			URIToTempURIMap = new HashMap();
		}

		return URIToTempURIMap;
	}

	public UnresolvedProxyMarkerManager getMarkerMananger() {
		return markerMananger;
	}
	
	private void checkModify(Collection<Resource> resources) throws LibraryResourceException {
		if(!resources.isEmpty()) {
			Resource[] resourceArray = new Resource[resources.size()];
			resources.toArray(resourceArray);
			checkModify(resourceArray, PersistencePlugin.getDefault().getContext()/*MsgBox.getDefaultShell()*/);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#checkModify(org.eclipse.epf.library.persistence.ILibraryResource[], java.lang.Object)
	 */
	public void checkModify(Resource[] resources, Object context) throws LibraryResourceException {		
		MultiFileSaveUtil.doCheckModify(Arrays.asList(resources));
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#checkModify(java.util.Collection<EObject>, java.lang.Object)
	 */
	public IStatus checkModify(Collection<EObject> eObjects, Object context) {
		HashSet pathSet = new HashSet();
		for (Iterator iter = eObjects.iterator(); iter.hasNext();) {
			EObject o = (EObject) iter.next();
			Resource resource = o.eResource();
			if(resource != null && resource.getResourceSet() == this) {
				MultiFileXMIResourceImpl mfResource = (MultiFileXMIResourceImpl) resource;
				if(!mfResource.hasTempURI()) {
					String path = mfResource.getURI().toFileString();
					pathSet.add(path);
				}
			}
		}
		if(pathSet.isEmpty()) {
			return Status.OK_STATUS;
		}
		String[] paths = new String[pathSet.size()];
		pathSet.toArray(paths);
		return FileManager.getInstance().checkModify(paths, context);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#getPersister()
	 */
	public ILibraryPersister getPersister() {
		return MethodLibraryPersister.INSTANCE;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#unload(org.eclipse.emf.ecore.resource.Resource, java.util.Map)
	 */
	public boolean unload(Resource resource, Map options) {
		if(resource instanceof MultiFileXMIResourceImpl) {
			return unloadWithoutRemove((MultiFileXMIResourceImpl) resource);
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#unload()
	 */
	public void unload() {
		reset();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#getFirstMethodLibrary()
	 */
	public MethodLibrary getFirstMethodLibrary() {
		return getMethodLibrary();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#getMethodLibraries()
	 */
	public List getMethodLibraries() {
		MethodLibrary lib = getMethodLibrary();
		if(lib == null) {
			return Collections.EMPTY_LIST;
		}
		return Collections.singletonList(lib);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#loadMethodLibraries(org.eclipse.emf.common.util.URI, java.util.Map)
	 */
	public void loadMethodLibraries(URI uri, Map<?, ?> parameters) throws LibraryResourceException {
		try {
			loadLibrary(uri.toFileString());
		} catch (Exception e) {
			if(e instanceof RuntimeException) {
				throw (RuntimeException)e;
			}
			throw new LibraryResourceException(e);
		}

	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#getPersistenceType()
	 */
	public String getPersistenceType() {
		return Services.XMI_PERSISTENCE_TYPE;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#unload(org.eclipse.emf.ecore.EObject)
	 */
	public boolean unload(EObject object) {
		Resource resource = object.eResource();
		if(resource instanceof MultiFileXMIResourceImpl) {
			((MultiFileXMIResourceImpl)resource).unloaded((InternalEObject) object);
			return true;
		}		
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResourceSet#reloadObjects(java.util.Collection)
	 */
	public Collection reloadObjects(Collection objects) {
		// TODO Auto-generated method stub
		return null;
	}

	public Resource getResource(IResource wsRes) {
		IPath path = wsRes.getLocation();
		return path != null ? PersistenceUtil.getResource(path, this) : null;
	}

//	public Collection<Resource> getContainedResources(IResource wsRes) {
//		return Collections.EMPTY_LIST;		
//	}
	
	public Collection<Resource> loadNewResources() {
		return loadConfigurations();
	}
	
	public void handleLibraryMoved(String newFolder) {
		PersistenceUtil.replaceURIPrefix(new ArrayList<Resource>(getResources()), libFolderPath.toOSString(), newFolder);
		
		// clear cached resolved URI in all ResourceDescriptors
		//
		ResourceManager resMgr = getRootResourceManager();
		Iterator iterator = new AbstractTreeIterator(resMgr, false) {
			private static final long serialVersionUID = 1L;

			protected Iterator getChildren(Object object) {
				ResourceManager resMgr = (ResourceManager) object;
				return resMgr.getSubManagers().iterator();
			}

		};
		while (iterator.hasNext()) {
			ResourceManager mgr = (ResourceManager) iterator.next();
			for(ResourceDescriptor resDesc : mgr.getResourceDescriptors()) {
				resDesc.clearResolvedURI();
			}
		}
	}
}