//------------------------------------------------------------------------------
// 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.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.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;
		if (resource instanceof MultiFileXMIResourceImpl) {
			uri = ((MultiFileXMIResourceImpl) resource).getFinalURI();
		} else {
			uri = resource.getURI();
		}
		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);
	}

	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 path relative to the library root directory to the resource
	 * folder of the given MethodElement object.
	 * 
	 * @param e
	 * @return
	 */
	public static String getResourcePath(MethodElement e) {
		String folderPath = getElementPath(e);
		if (folderPath == null || folderPath.equals("")) //$NON-NLS-1$
		{
			return RESOURCE_FOLDER;
		} else if (folderPath.endsWith(File.separator)) {
			return new StringBuffer(folderPath).append(RESOURCE_FOLDER)
					.toString();
		} else {
			return new StringBuffer(folderPath).append(File.separator).append(
					RESOURCE_FOLDER).toString();
		}
	}

	public static String getElementPath(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.out
						.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.out
					.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 relUri = uri.deresolve(MultiFileSaveUtil
						.getFinalURI(libRes));
				relPluginPath = relUri.trimSegments(1).toFileString();
			}
		} else {
			// the library is not saved yet
			relPluginPath = plugin.getName();
		}
		String folderPath = staticGetFolderRelativePath(e);

		return (folderPath.length() == 0 ? relPluginPath : 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);
		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();
		}

		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 resources;
					if(libResourceToSave != null) {
						resources = new ArrayList();
						resources.add(resource);
						resources.add(libResourceToSave);
					}
					else {
						resources = Collections.singletonList(resource);
					}
					MultiFileSaveUtil.checkModify(resources);
					MultiFileSaveUtil.checkOutOfSynch(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);
			}
		}

		/**
		 * @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);

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

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

				// 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--) {
						((MultiFileXMIResourceImpl) 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 {

		/**
		 * @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());
			}
		}

	}

	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();
		URI uri = MultiFileSaveUtil.createFileURI(element);
		Map options = resourceSet.getDefaultSaveOptions(); 
		MultiFileXMIResourceImpl 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;
	}

}