//------------------------------------------------------------------------------
// 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.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.epf.library.persistence.internal.IFailSafeSavable;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.epf.persistence.util.PersistenceResources;
import org.eclipse.epf.persistence.util.PersistenceUtil;
import org.eclipse.epf.services.IFileBasedLibraryPersister;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.ContentDescription;
import org.eclipse.epf.uma.ContentElement;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.DescribableElement;
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.MethodUnit;
import org.eclipse.epf.uma.Process;
import org.eclipse.epf.uma.ProcessComponent;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.osgi.util.NLS;

/**
 * File-based implementation for IMethodLibraryPersister
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class MethodLibraryPersister implements IFileBasedLibraryPersister {

	private static class FolderInfo {

		EClass eClazz;

		boolean shared;

		private String name;

		/**
		 * @param clazz
		 * @param shared
		 */
		public FolderInfo(EClass clazz, boolean shared) {
			super();
			eClazz = clazz;
			this.shared = shared;
			this.name = lowerAndPluralize(clazz.getName());
		}

	}

	public static final MethodLibraryPersister INSTANCE = new MethodLibraryPersister();

	// need to expose this, jxi
	public static final String RESOURCE_FOLDER = "resources"; //$NON-NLS-1$

	private static final List folderInfos = new ArrayList();

	static {
		folderInfos.add(new FolderInfo(UmaPackage.eINSTANCE.getGuidance(),
				false));
		folderInfos.add(new FolderInfo(UmaPackage.eINSTANCE.getWorkProduct(),
				true));
		folderInfos
				.add(new FolderInfo(UmaPackage.eINSTANCE.getActivity(), true));
	}

	protected List warnings;

	public MethodLibraryPersister() {
	}

	/**
	 * Returns the correct path (relative to the plugin) of the file of the
	 * given content description or null if the given content does not be long
	 * to any plugin.
	 * 
	 * @param content
	 * @return
	 */
	public static String getCorrectPath(ContentDescription content) {
		return getCorrectPath((DescribableElement) content.eContainer(),
				content);
	}

	private static String getCorrectPath(DescribableElement e,
			ContentDescription content) {
		if (e == null)
			return null;
		MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
		if (plugin == null) {
			return null;
		}
		Resource resource = plugin.eResource();
		URI uri = MultiFileSaveUtil.getFinalURI(resource);
		File pluginDir = new File(uri.toFileString()).getParentFile();
		String folderPath = staticGetFolderPath(e.eClass());
		String dir = new StringBuffer(pluginDir.getAbsolutePath()).append(
				File.separator).append(folderPath).append(File.separator)
				.toString();

		return getNextAvailableFileName(dir, e, content);
	}

	/**
	 * Gets next available file name for the given {@link MultiResourceEObject} in the given directory <code>dir</code>
	 * 
	 * @param dir the directory path that must have a file separator at the end
	 * @param requestedName
	 * @param e
	 * @return
	 */
	public static String getNextAvailableFileName(String dir, String requestedName,
			MultiResourceEObject e) {
		String currentFilename = null;
		File currentFile = null;
		MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) e
				.eDirectResource();
		if (resource != null) {
			// keep existing file name during move if it is not taken yet. Don't
			// try to match the element's name
			//
			String path = ((MultiFileXMIResourceImpl) e.eResource())
					.getFinalURI().toFileString();
			currentFile = new File(path);
			currentFilename = currentFile.getName();
			File file = new File(dir, currentFilename);
			if (!file.exists()) {
				// the element is being moved
				//
				return file.getAbsolutePath();
			}
		}

		// element without a resource or path is already taken
		//
		String path = new StringBuffer(dir).append(requestedName).append(
				MultiFileSaveUtil.DEFAULT_FILE_EXTENSION).toString();
		File file = new File(path);
		if(file.equals(currentFile)) {
			return path;
		}
		if ((currentFilename != null && currentFilename.equals(requestedName))
				|| file.exists()) {
			for (int i = 2; true; i++) {
				path = new StringBuffer(dir).append(requestedName).append(' ')
						.append(i).append(
								MultiFileSaveUtil.DEFAULT_FILE_EXTENSION)
						.toString();
				if (!new File(path).exists()) {
					return path;
				}
			}
		} else {
			return path;
		}
	}

	static String getNextAvailableFileName(String dir,
			ContentDescription content) {
		return getNextAvailableFileName(dir, (DescribableElement) content
				.eContainer(), content);
	}

	private static String getNextAvailableFileName(String dir,
			DescribableElement e, ContentDescription content) {
		return getNextAvailableFileName(dir, e.getName(),
				(MultiResourceEObject) content);
	}

	private static String staticGetFolderPath(EClass eClazz) {
		int size = folderInfos.size();
		FolderInfo info = null;
		for (int i = 0; i < size; i++) {
			FolderInfo folderInfo = (FolderInfo) folderInfos.get(i);
			if (folderInfo.eClazz.isSuperTypeOf(eClazz)) {
				info = folderInfo;
			}
		}
		if (info != null) {
			if (info.eClazz == eClazz || info.shared) {
				return info.name;
			} else {
				return new StringBuffer(info.name).append(File.separatorChar)
						.append(lowerAndPluralize(eClazz.getName())).toString();
			}
		} else {
			return lowerAndPluralize(eClazz.getName());
		}
	}

	public static String lowerAndPluralize(String name) {
		name = name.toLowerCase();
		if (name.endsWith("children")) { //$NON-NLS-1$
			return name;
		} else if (name.endsWith("child")) { //$NON-NLS-1$
			return name + "ren"; //$NON-NLS-1$
		} else if (name.endsWith("data")) { //$NON-NLS-1$
			return name;
		} else if (name.endsWith("datum")) { //$NON-NLS-1$
			return name.substring(0, name.length() - 2) + "a"; //$NON-NLS-1$
		} else if (name.endsWith("by")) { //$NON-NLS-1$
			return name + "s"; //$NON-NLS-1$
		} else if (name.endsWith("y")) { //$NON-NLS-1$
			return name.substring(0, name.length() - 1) + "ies"; //$NON-NLS-1$
		} else if (name.endsWith("ex")) { //$NON-NLS-1$
			return name.substring(0, name.length() - 2) + "ices"; //$NON-NLS-1$
		} else if (name.endsWith("x")) { //$NON-NLS-1$
			return name + "es"; //$NON-NLS-1$
		} else if (name.endsWith("us")) { //$NON-NLS-1$
			return name.substring(0, name.length() - 2) + "i"; //$NON-NLS-1$
		} else if (name.endsWith("ss")) { //$NON-NLS-1$
			return name + "es"; //$NON-NLS-1$
		} else if (name.endsWith("s")) { //$NON-NLS-1$
			return name;
		} else {
			return name + "s"; //$NON-NLS-1$
		}
	}

	/**
	 * Gets the virtual path to the resource folder of the given MethodElement object.
	 * 
	 * @param e
	 * @return
	 * @see #getElementVirtualPath(MethodElement)
	 */
	public String geResourceVirtualPath(MethodElement e) {
		String folderPath = getElementVirtualPath(e);
		if (folderPath == null || folderPath.length() == 0)
		{
			return RESOURCE_FOLDER;
		} else {
			StringBuffer buffer = new StringBuffer(folderPath);
			if ( !folderPath.endsWith(File.separator) ) {
				buffer.append(File.separator);
			} 
			
			buffer.append(RESOURCE_FOLDER);				
			
			return buffer.toString();
		}
	}

	/**
	 * Gets the virtual path to the folder of the given MethodElement object. This path will have the following format:
	 * <plugin_name>\folder_relative_path\
	 * 
	 * @param e
	 * @return
	 */	
	public String getElementVirtualPath(MethodElement e) {
		MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
		if (plugin == null) {
			if (!(e instanceof MethodConfiguration || e instanceof MethodLibrary)) {
				// error: plugin element without a valid plugin set. This
				// problem needs to be fixed.
				// still see it from time to time,
				// for example, when lick on a capability pattern in
				// Configuration Explorer
				System.err
						.println("error in MethodLibraryPersister.getElementPath(): plugin element without a valid plugin. This problem needs to be fixed."); //$NON-NLS-1$
			}
			return ""; //$NON-NLS-1$
		}
		
		String folderPath = getFolderRelativePath(e);
		String pluginName = plugin.getName();
		return (folderPath.length() == 0 ? pluginName + File.separator : new StringBuffer(
				pluginName).append(File.separatorChar).append(folderPath)
				.append(File.separatorChar).toString());
	}
	
	/**
	 * Gets the path relative to the library root directory to the
	 * folder of the given MethodElement object.
	 * 
	 * @param e
	 * @return
	 */	
	private String getRelativeElementPath(MethodElement e) {
		String folderPath = getFolderRelativePath(e);
		MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
		if (plugin == null) {
			if ((e instanceof MethodConfiguration || e instanceof MethodLibrary)) {
				return folderPath;
			}
			else {
				// error: plugin element without a valid plugin set. This
				// problem needs to be fixed.
				// still see it from time to time,
				// for example, when lick on a capability pattern in
				// Configuration Explorer
				System.err
						.println("error in MethodLibraryPersister.getElementPath(): plugin element without a valid plugin. This problem needs to be fixed."); //$NON-NLS-1$
				return ""; //$NON-NLS-1$
			}
		}

		if (plugin.eContainer() == null) {
			// error: plugin without library set. This problem needs to be
			// fixed.
			// still see it from time to time
			System.err
					.println("error in MethodLibraryPersister.getElementPath(): plugin without library set. This problem needs to be fixed."); //$NON-NLS-1$
			return ""; //$NON-NLS-1$
		}

		String relPluginPath;
		if (plugin.eResource() != null) {
			Resource libRes = UmaUtil.getMethodLibrary(plugin).eResource();
			if (libRes == plugin.eResource()) {
				// the plugin is not saved yet
				relPluginPath = plugin.getName();
			} else {
				URI uri = MultiFileSaveUtil.getFinalURI(plugin.eResource());
				URI libUri = MultiFileSaveUtil.getFinalURI(libRes);
				URI relUri = uri.deresolve(libUri);
				relPluginPath = relUri.trimSegments(1).toFileString();
			}
		} else {
			// the library is not saved yet
			relPluginPath = plugin.getName();
		}

		return (folderPath.length() == 0 ? relPluginPath + File.separator: new StringBuffer(
				relPluginPath).append(File.separatorChar).append(folderPath)
				.append(File.separatorChar).toString());
	}

	public static void main(String[] args) {
		EClass eCls = UmaPackage.eINSTANCE.getTemplate();
		System.out.println(eCls.getName());
	}

	/**
	 * Adjusts the location of the given resource and save all the resources
	 * that have been changed as the result of this adjustment
	 * 
	 * @param resource
	 */
	public void adjustLocation(Resource resource) {
		Set modifiedResources = new HashSet();
		MultiFileSaveUtil.adjustLocation(resource, modifiedResources);

		// save the modified resources
		MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) resource
				.getResourceSet();
		for (Iterator iter = modifiedResources.iterator(); iter.hasNext();) {
			try {
				resourceSet.save((Resource) iter.next(), null);
			} catch (Exception e) {
				CommonPlugin.INSTANCE.log(e);
			}
		}
	}

	public void save(Resource resource) throws Exception {
		MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) resource
				.getResourceSet();
		resourceSet.save(resource, null);
	}

	protected void deleteFiles(MethodElement e, String path,
			ResourceSet resourceSet) {
		if (new File(path).isDirectory() && !e.eIsProxy()) {
			for (Iterator iter = resourceSet.getResources().iterator(); iter
					.hasNext();) {
				Resource res = (Resource) iter.next();
				MethodElement me = PersistenceUtil.getMethodElement(res);
				if (me != null && UmaUtil.isContainedBy(me, e)) {
					res.unload();
					iter.remove();
				}
			}
		}

		try {
			FileManager.getInstance().deleteResource(path, null);
		} catch (CoreException ex) {
			CommonPlugin.INSTANCE.log(ex);
			throw new WrappedException(ex);
		}
	}

	/**
	 * Deletes the files associated with the given MethodElement
	 * 
	 * @param e
	 */
	protected void delete(MethodElement e, Set modifiedResources) {
		if (!UmaUtil.hasDirectResource(e)) {
			return;
		}

		MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) e
				.eResource();
		MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) resource
				.getResourceSet();

		// Don't delete this resource's file if it still contains other
		// MethodElement
		for (Iterator iter = resource.getContents().iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof MethodElement && element != e) {
				resourceSet.removeURIMappings(e, modifiedResources);
				resource.getContents().remove(e);
				modifiedResources.add(resource);
				return;
			}
		}

		String path;
		if (MultiFileSaveUtil.hasOwnFolder(e)) {
			// path is the directory of the MethodPlugin/ProcessComponent
			//
			path = new File(resource.getFinalURI().toFileString()).getParent();

			// unload/remove all resources under the folder
			//
			Collection unloadedResources = new ArrayList();
			do {
				unloadedResources.clear();
				// collect all resources whose root element is contained by the
				// given element
				//
				for (Iterator iter = new ArrayList(resourceSet.getResources())
						.iterator(); iter.hasNext();) {
					Resource res = (Resource) iter.next();
					if (res.isLoaded()) {
						MethodElement me = PersistenceUtil
								.getMethodElement(res);
						if (me != null && UmaUtil.isContainedBy(me, e)) {
							unloadedResources.add(res);
						}
					}
				}
				for (Iterator iter = unloadedResources.iterator(); iter
						.hasNext();) {
					Resource res = (Resource) iter.next();
					res.unload();
				}
				resourceSet.getResources().removeAll(unloadedResources);
			} while (!unloadedResources.isEmpty());
		} else {
			path = resource.getFinalURI().toFileString();
		}

		try {
			resourceSet.cleanUp(resource, modifiedResources);
		} catch (Exception e1) {
			CommonPlugin.INSTANCE.log(e1);
			if (MultiFileSaveUtil.DEBUG) {
				e1.printStackTrace();
			}
		}

		deleteFiles(e, path, resourceSet);
	}

	/**
	 * @param e
	 * @param objectsWithDirectResources
	 */
	private static void getObjectsWithDirectResources(EObject e,
			Collection objectsWithDirectResources) {
		if (UmaUtil.hasDirectResource(e)) {
			objectsWithDirectResources.add(e);
		} else {
			for (Iterator iter = e.eContents().iterator(); iter.hasNext();) {
				getObjectsWithDirectResources((EObject) iter.next(),
						objectsWithDirectResources);
			}
		}
	}

	/**
	 * @see org.eclipse.epf.services.IFileBasedLibraryPersister#delete(org.eclipse.epf.uma.MethodElement)
	 */
	public void delete(MethodElement e) {
		// collect all elements with direct resources that are the given element
		// or its offstring
		ArrayList elements = new ArrayList();
		getObjectsWithDirectResources(e, elements);
		deleteAndSave(elements);
	}

	private void deleteAndSave(ArrayList elements) {
		if (!elements.isEmpty()) {
			Set modifiedResources = new HashSet();
			for (Iterator iter = elements.iterator(); iter.hasNext();) {
				delete((MethodElement) iter.next(), modifiedResources);
			}

			// save modified resources
			//
			for (Iterator iter = modifiedResources.iterator(); iter.hasNext();) {
				Resource resource = (Resource) iter.next();
				try {
					save(resource);
				} catch (Exception ex) {
					throw new WrappedException(ex);
				}
			}
		}
	}

	/**
	 * Gets the relative path of the folder that can store the content of the
	 * given MethodElement. The path is relative to its plugin folder or library
	 * folder if the element cannot be stored in a plugin.
	 */
	private static String staticGetFolderRelativePath(MethodElement e) {
		if (e instanceof MethodPlugin) {
			return ""; //$NON-NLS-1$
		} else if (e instanceof ContentElement) {
			return staticGetFolderPath(e.eClass());
		} else if (e instanceof MethodConfiguration) {
			return MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME;
		}

		MethodUnit unit = UmaUtil.getMethodUnit(e);

		if (unit instanceof ProcessComponent) {
			Process proc = ((ProcessComponent) unit).getProcess();
			if (proc instanceof CapabilityPattern) {
				return MultiFileSaveUtil.CAPABILITY_PATTERN_PATH;
			} else if (proc instanceof DeliveryProcess) {
				return MultiFileSaveUtil.DELIVERY_PROCESS_PATH;
			}
		} else if (unit instanceof ContentDescription) {
			return staticGetFolderRelativePath((MethodElement) unit
					.eContainer());
		}

		return ""; //$NON-NLS-1$
	}

	public String getFolderRelativePath(MethodElement e) {
		return staticGetFolderRelativePath(e);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#getWarnings()
	 */
	public List getWarnings() {
		if (warnings == null) {
			warnings = new ArrayList();
		}
		return warnings;
	}

	static class FailSafePersister extends MethodLibraryPersister implements
			FailSafeMethodLibraryPersister {

		private Map saveOptions;

		private TxRecord txRecord = new TxRecord() {
			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.epf.persistence.TxRecord#clear()
			 */
			public void clear() {
				if (warnings != null && !warnings.isEmpty()) {
					// copy the warning to persister
					//
					FailSafePersister.this.warnings = Collections
							.unmodifiableList(warnings);
				}
				super.clear();
			}
		};

		private Map elementToInfoMapToDeleteFiles;

		public FailSafePersister() {
			saveOptions = new HashMap(
					MultiFileResourceSetImpl.DEFAULT_SAVE_OPTIONS);
			txRecord = new TxRecord();
			saveOptions.put(MultiFileXMISaveImpl.TX_RECORD, txRecord);
			elementToInfoMapToDeleteFiles = new HashMap();
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.epf.persistence.MethodLibraryPersister#getWarnings()
		 */
		public List getWarnings() {
			if (txRecord.getTxID() == null) {
				return super.getWarnings();
			}
			return txRecord.getWarnings();
		}

		public Map getSaveOptions() {
			return saveOptions;
		}

		void checkMove(Resource resource) {
			// disallow new operation on resource which has started operation
			// that is not committed
			MultiFileXMIResourceImpl mfResource = (MultiFileXMIResourceImpl) resource;
			if (mfResource.txStarted()) {
				throw new MultiFileIOException(NLS.bind(
						PersistenceResources.moveResourceError_msg, resource));
			}			
		}				
		
		/**
		 * @see org.eclipse.epf.uma.persistence.MethodLibraryPersister#save(org.eclipse.emf.ecore.resource.Resource)
		 */
		public void save(Resource resource) throws Exception {
			if(resource.getResourceSet() instanceof MultiFileResourceSetImpl &&
					resource instanceof MultiFileXMIResourceImpl) {
				MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) resource
				.getResourceSet();
				if (resourceSet == null) {
					return;
				}

				// update version info in library resource if needed
				//
				Resource libResourceToSave = null;
				MethodElement me = PersistenceUtil.getMethodElement(resource);
				if(me != null) {
					MethodLibrary lib = UmaUtil.getMethodLibrary(me);
					if(lib != null) {
						Resource libResource = lib.eResource();
						if(libResource != null 
								&& libResource != resource
								&& PersistenceUtil.checkToolVersion(libResource) != 0) {
							libResourceToSave = libResource;
						}
					}
				}

				if (MultiFileXMISaveImpl.checkModifyRequired(saveOptions)) {
					Collection<Resource> resources;
					if(libResourceToSave != null) {
						resources = new ArrayList<Resource>();
						resources.add(resource);
						resources.add(libResourceToSave);
					}
					else {
						resources = Collections.singletonList(resource);
					}
					MultiFileSaveUtil.checkModify(resources);
					
					// check out-of-sync
					//
					MultiFileSaveUtil.checkOutOfSynch(resources, saveOptions);
					
					MultiFileSaveUtil.checkFilePathLength(resources);
				}

				resourceSet.save(resource, saveOptions);
				if(libResourceToSave != null) {
					resourceSet.save(libResourceToSave, saveOptions);
				}
			}
			else if(resource instanceof IFailSafeSavable) {
				IFailSafeSavable failSafeSavable = (IFailSafeSavable) resource;
				failSafeSavable.setTxID(txRecord.getTxID());
				resource.save(saveOptions);
				txRecord.getResourcesToCommit().add(resource);
			}
			else {
				throw new IllegalAccessException("Resource must implement org.eclipse.epf.library.persistence.internal.IFailSafeSavable"); //$NON-NLS-1$
			}
		}

		/**
		 * @see org.eclipse.epf.uma.persistence.MethodLibraryPersister#adjustLocation(org.eclipse.emf.ecore.resource.Resource)
		 */
		public void adjustLocation(Resource resource) {
			checkMove(resource);
			Set modifiedResources = new HashSet();
			if (MultiFileSaveUtil.prepareAdjustLocation(
					(MultiFileXMIResourceImpl) resource, modifiedResources)) {
				txRecord.getResourcesToCommit().add(resource);
				
				HashSet resourcesToCheck = new HashSet(modifiedResources);
				resourcesToCheck.addAll(resourcesToCheck);
				MultiFileSaveUtil.checkModify(resourcesToCheck);
				
				if (!modifiedResources.isEmpty()) {		
					
					MultiFileSaveUtil.checkOutOfSynch(modifiedResources, saveOptions);

					// save the modified resources
					for (Iterator iter = modifiedResources.iterator(); iter
							.hasNext();) {
						try {
							save((Resource) iter.next());
						} catch (Exception e) {
							PersistencePlugin.getDefault().getLogger().logError(e);
							throw new MultiFileIOException(e.toString());
						}
					}
				}
			}
			commit();
		}

		public void adjustLocation(Collection resources) {
			if (resources == null || resources.isEmpty()) {
				return;
			}

			for (Iterator iter = resources.iterator(); iter.hasNext();) {
				checkMove((Resource) iter.next());
			}

			Set modifiedResources = new HashSet();
			HashSet resourcesToCheck = new HashSet();
			for (Iterator iter = resources.iterator(); iter.hasNext();) {
				MultiFileXMIResourceImpl resource = (MultiFileXMIResourceImpl) iter
						.next();
				if (MultiFileSaveUtil.prepareAdjustLocation(
						(MultiFileXMIResourceImpl) resource, modifiedResources)) {
					txRecord.getResourcesToCommit().add(resource);
					resourcesToCheck.add(resource);
				}
			}

			resourcesToCheck.addAll(modifiedResources);
			if(!resourcesToCheck.isEmpty()) {
				MultiFileSaveUtil.checkModify(resourcesToCheck);
			}			
			if (!modifiedResources.isEmpty()) {
				MultiFileSaveUtil.checkOutOfSynch(modifiedResources, saveOptions);

				// save the modified resources
				for (Iterator iter = modifiedResources.iterator(); iter
						.hasNext();) {
					try {
						save((Resource) iter.next());
					} catch (Exception e) {
						CommonPlugin.INSTANCE.log(e);
						throw new MultiFileIOException(e.toString());
					}
				}
			}
			commit();
		}

		/**
		 * @see org.eclipse.epf.uma.persistence.MethodLibraryPersister#deleteFiles(org.eclipse.epf.uma.MethodElement,
		 *      java.lang.String, org.eclipse.emf.ecore.resource.ResourceSet)
		 */
		protected void deleteFiles(MethodElement e, String path,
				ResourceSet resourceSet) {
			// keep the info to really delete the files in commit()
			elementToInfoMapToDeleteFiles.put(e, new Object[] { path,
					resourceSet });
		}

		private void superDeleteFiles(MethodElement e, String path,
				ResourceSet resourceSet) {
			super.deleteFiles(e, path, resourceSet);
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#commit()
		 */
		public void commit() {
			// save is done
			// call saveIsDone() on every saved file to rename it to the correct
			// name
			int size = txRecord.getResourcesToCommit().size();
			for (int i = 0; i < size; i++) {
				((IFailSafeSavable) txRecord.getResourcesToCommit()
						.get(i)).commit();
			}

			// notify all commited resources that the transaction is done
			for (int i = 0; i < size; i++) {
				((IFailSafeSavable) txRecord.getResourcesToCommit()
						.get(i)).txFinished(true);
			}

			// delete backup
			for (int i = 0; i < size; i++) {
				((IFailSafeSavable) txRecord.getResourcesToCommit()
						.get(i)).deleteBackup();
			}

			txRecord.clear();

			// delete files of deleted elements
			//
			for (Iterator iter = elementToInfoMapToDeleteFiles.entrySet()
					.iterator(); iter.hasNext();) {
				Map.Entry entry = (Map.Entry) iter.next();
				Object[] info = (Object[]) entry.getValue();
				String path = (String) info[0];
				try {
					superDeleteFiles((MethodElement) entry.getKey(), path,
							(ResourceSet) info[1]);
				} catch (Exception e) {
					if (e instanceof WrappedException) {
						e = ((WrappedException) e).exception();
					}
					String msg = PersistenceResources.ErrMsg_CouldNotDelete;
					String otherMsg = null;
					if (e instanceof CoreException) {
						IStatus status = ((CoreException) e).getStatus();
						if (status != null) {
							otherMsg = UmaUtil.getMessage(status);
						}
					}
					if (otherMsg == null) {
						otherMsg = ""; //$NON-NLS-1$
					}
					msg = MessageFormat.format(msg, new Object[] { path,
							otherMsg });
					e = new Exception(msg, e);
					getWarnings().add(e);
					CommonPlugin.INSTANCE.log(e);
					if (MultiFileSaveUtil.DEBUG) {
						e.printStackTrace();
					}
				}
			}
			elementToInfoMapToDeleteFiles.clear();
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#rollback()
		 */
		public void rollback() {
			if (!txRecord.getResourcesToCommit().isEmpty()) {
				try {
					int max = txRecord.getResourcesToCommit().size() - 1;
					ArrayList restoredResources = new ArrayList();

					// Something went wrong, restore from backup
					for (int i = max; i > -1; i--) {
						IFailSafeSavable resource = (IFailSafeSavable) txRecord
								.getResourcesToCommit().get(i);
						if (resource.restore()) {
							restoredResources.add(resource);
						}
					}

					for (Iterator iter = restoredResources.iterator(); iter
							.hasNext();) {
						Resource resource = (Resource) iter
								.next();
						resource.setModified(true);
					}

					// delete temp files
					for (int i = max; i > -1; i--) {
						Resource resource = (Resource) txRecord
								.getResourcesToCommit().get(i);
						if (((IFailSafeSavable)resource).hasTempURI()) {
							// uri keeps the path to temp file
							try {
								new File(resource.getURI().toFileString())
										.delete();
							} catch (Exception e) {
								CommonPlugin.INSTANCE.log(e);
								if (MultiFileSaveUtil.DEBUG) {
									e.printStackTrace();
								}
							}
						}
					}

					// notify all commited resources that the transaction is
					// done
					for (int i = max; i > -1; i--) {
						((IFailSafeSavable) txRecord
								.getResourcesToCommit().get(i))
								.txFinished(false);
					}

				} catch (RuntimeException e) {
					CommonPlugin.INSTANCE.log(e);
					if (MultiFileSaveUtil.DEBUG) {
						e.printStackTrace();
					}
					throw e;
				}
			}
			txRecord.clear();
		}

		/**
		 * @see org.eclipse.epf.services.IFileBasedLibraryPersister#getFailSafePersister()
		 */
		public FailSafeMethodLibraryPersister getFailSafePersister() {
			return this;
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#getCurrentTxID()
		 */
		public String getCurrentTxID() {
			return txRecord.getTxID();
		}

	}

	FailSafePersister getFailSafePersister(Map options) {
		FailSafePersister persister = new FailSafePersister();
		persister.saveOptions.putAll(options);

		// make sure that TX_RECORD still keeps the correct value
		persister.saveOptions.put(MultiFileXMISaveImpl.TX_RECORD,
				persister.txRecord);

		return persister;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#hasOwnFolder(java.lang.Object)
	 */
	public boolean hasOwnFolder(Object e) {
		return MultiFileSaveUtil.hasOwnFolder(e);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#hasOwnResource(java.lang.Object)
	 */
	public boolean hasOwnResource(Object e) {
		return MultiFileSaveUtil.hasOwnResource(e,
				MultiFileResourceSetImpl.DEFAULT_SAVE_SEPARATELY_CLASS_SET);
	}

	/**
	 * @see org.eclipse.epf.services.IFileBasedLibraryPersister#getFailSafePersister()
	 */
	public FailSafeMethodLibraryPersister getFailSafePersister() {
		return new FailSafePersister();
	}

	public static class NonFailSafePersister extends MethodLibraryPersister
			implements FailSafeMethodLibraryPersister {
		private Map saveOptions = new HashMap();

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#commit()
		 */
		public void commit() {
			// do nothing
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#rollback()
		 */
		public void rollback() {
			// do nothing
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#getCurrentTxID()
		 */
		public String getCurrentTxID() {
			return null;
		}

		/**
		 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister.FailSafeMethodLibraryPersister#adjustLocation(java.util.Collection)
		 */
		public void adjustLocation(Collection resources) {
			for (Iterator iter = resources.iterator(); iter.hasNext();) {
				adjustLocation((Resource) iter.next());
			}
		}

		public Map getSaveOptions() {
			return saveOptions;
		}

	}

	private static final FailSafeMethodLibraryPersister nonFailSafePersister = new NonFailSafePersister();

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#getFileExtension(java.lang.Object)
	 */
	public String getFileExtension(Object e) {
		return MultiFileSaveUtil.DEFAULT_FILE_EXTENSION;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#save(org.eclipse.epf.uma.MethodElement)
	 */
	public void save(MethodElement element) throws Exception {
		if(!hasOwnResourceWithoutReferrer(element)) {
			return;
		}
		MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) UmaUtil.getMethodLibrary(element).eResource().getResourceSet();
		Map options = resourceSet.getDefaultSaveOptions(); 
		Resource res = ((InternalEObject)element).eDirectResource();
		MultiFileXMIResourceImpl resource;
		if(res instanceof MultiFileXMIResourceImpl) {
			resource = (MultiFileXMIResourceImpl) res;
			resourceSet.save(resource, options);
		}
		else {
			URI uri = MultiFileSaveUtil.createURI(element, resourceSet);
			resource = MultiFileSaveUtil.save(resourceSet, element, uri, options, false);
		}
		resource.updateTimeStamps();
		
		String str = (String) options.get(MultiFileXMISaveImpl.REFRESH_NEW_RESOURCE);
		if (str != null && Boolean.valueOf(str).booleanValue()) {
			// notify RefreshJob the this resource is saved so it will not be
			// reloaded after refreshing it
			//
			RefreshJob.getInstance().resourceSaved(resource);

			// refresh the newly created resource so it is in synch with the
			// workspace
			//
			FileManager.getInstance().refresh(resource);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.uma.util.IFileBasedLibraryPersister#hasOwnResourceWithoutReferrer(java.lang.Object)
	 */
	public boolean hasOwnResourceWithoutReferrer(Object e) {
		return e instanceof MethodConfiguration;
	}

	public File createMethodPluginFolder(String pluginName, MethodLibrary library) {
		File libDir = new File(library.eResource().getURI().toFileString()).getParentFile();
		File pluginDir = new File(libDir, pluginName);
		if(!pluginDir.exists()) {
			if(!pluginDir.mkdirs()) {
				throw new MultiFileIOException(NLS.bind(PersistenceResources.cannot_create_dir_msg, pluginDir));				
			}
		}
		return pluginDir;
	}

	public File getDefaultMethodConfigurationFolder(MethodLibrary library) {
		File libDir = new File(library.eResource().getURI().toFileString()).getParentFile();
		File configDir = new File(libDir, MultiFileSaveUtil.METHOD_CONFIGURATION_FOLDER_NAME);
		if(!configDir.exists()) {
			if(!configDir.mkdirs()) {
				throw new MultiFileIOException(NLS.bind(PersistenceResources.cannot_create_dir_msg, configDir));				
			}
		}
		return configDir;
	}

	public void setDefaultMethodConfigurationFolder(MethodLibrary library, File file) {
		// not allowed
	}

	public boolean isContainedBy(Resource resource, Resource containerResource) {
		MethodElement e = PersistenceUtil.getMethodElement(containerResource);
		if(hasOwnFolder(e)) {
			String path = FileManager.toFileString(resource.getURI());
			String containerPath = FileManager.toFileString(containerResource.getURI());		
			if(path == null || containerPath == null) {
				return false;
			}
			return new Path(containerPath).removeLastSegments(1).isPrefixOf(new Path(path));
		}
		return false;
	}

	public String getResourceFolderPath(MethodElement e) {
		String folderPath = getFolderAbsolutePath(e);
		return folderPath != null ? new File(folderPath, RESOURCE_FOLDER).getAbsolutePath() : RESOURCE_FOLDER;
	}

	public String getFolderAbsolutePath(MethodElement e) {
		MethodLibrary library = UmaUtil.getMethodLibrary(e);
		File libDir = new File(MultiFileSaveUtil.getFinalURI(library.eResource()).toFileString()).getParentFile();
		return new File(libDir, getRelativeElementPath(e)).getAbsolutePath();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.epf.services.ILibraryPersister#delete(java.util.Collection)
	 */
	public void delete(Collection<MethodElement> elems) {
		ArrayList elements = new ArrayList();
		for (Iterator<MethodElement> it = elems.iterator(); it.hasNext();) {
			getObjectsWithDirectResources(it.next(), elements);
		}
		deleteAndSave(elements);
	}

}