//------------------------------------------------------------------------------
// 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.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.eclipse.core.resources.IResource;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.AbstractTreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
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.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLLoad;
import org.eclipse.emf.ecore.xmi.XMLSave;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.library.persistence.ILibraryResource;
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.resourcemanager.ResourceDescriptor;
import org.eclipse.epf.resourcemanager.ResourceManager;
import org.eclipse.epf.services.ILibraryPersister;
import org.eclipse.epf.uma.ContentDescription;
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.Section;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
import org.eclipse.epf.uma.ecore.util.DefaultValueManager;
import org.eclipse.epf.uma.ecore.util.OppositeFeatureNotification;
import org.eclipse.epf.uma.util.Scope;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.osgi.util.NLS;

/**
 * Resource implementation for library XMI persistence
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class MultiFileXMIResourceImpl extends XMIResourceImpl 
implements ILibraryResource, IFailSafeSavable
{

	private static String tempDir;

	private URI finalURI;

	private URI oldURI;

	private String backupFile;

	private String currentTxID;

	private long lastLoadTimeStamp;

	private ResourceDescriptor resourceDescriptor;

	private boolean isUnloading;

	/** Cached modification stamp of the resource file */
	private long modificationStamp;

	private IFileInfo fileInfo;

	public MultiFileXMIResourceImpl(URI uri) {
		super(uri);
		setIntrinsicIDToEObjectMap(new HashMap());		
	}

	protected XMLLoad createXMLLoad() {
		return new MultiFileXMILoadImpl(createXMLHelper());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#createXMLSave()
	 */
	protected XMLSave createXMLSave() {
		return new MultiFileXMISaveImpl(createXMLHelper());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl#createXMLHelper()
	 */
	protected XMLHelper createXMLHelper() {
		return new MultiFileXMIHelperImpl(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.XMLResource#getID(org.eclipse.emf.ecore.EObject)
	 */
	public String getID(EObject eObject) {
		String id = MultiFileSaveUtil.getGuid(eObject);
		if (id != null)
			return id;
		return super.getID(eObject);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#setID(org.eclipse.emf.ecore.EObject,
	 *      java.lang.String)
	 */
	public void setID(EObject eObject, String id) {
		Object oldID = id != null ? getEObjectToIDMap().put(eObject, id)
				: getEObjectToIDMap().remove(eObject);

		Map guidToMethodElementMap = ((MultiFileResourceSetImpl) getResourceSet())
				.getGuidToMethodElementMap();

		if (oldID != null) {
			getIDToEObjectMap().remove(oldID);
			
			if (eObject instanceof MethodElement) {
				// remove object from guidToMethodElementMap only if it is a proxy
				//
				if(eObject.eIsProxy()) {
					EObject obj = (EObject) guidToMethodElementMap.get(id);
					if(obj != null && obj.eIsProxy()) {
						guidToMethodElementMap.remove(id);
					}
				}
				else {
					guidToMethodElementMap.remove(id);
				}
			}
		}

		if (id != null) {
			getIDToEObjectMap().put(id, eObject);
			if (eObject instanceof MethodElement) {
				guidToMethodElementMap.put(id, eObject);

				MethodElement e = (MethodElement) eObject;
				if (!e.getGuid().equals(id)) {
					e.setGuid(id);
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#useUUIDs()
	 */
	protected boolean useUUIDs() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.Resource#getURIFragment(org.eclipse.emf.ecore.EObject)
	 */
	public String getURIFragment(EObject eObject) {
		try {
			String id = getID(eObject);

			if (id != null) {
				return id;
			} else {
				List uriFragmentPath = new ArrayList();
				for (EObject container = eObject.eContainer(); container != null
						&& container.eResource() == this; container = eObject
						.eContainer()) {
					uriFragmentPath.add(((InternalEObject) container)
							.eURIFragmentSegment(eObject.eContainingFeature(),
									eObject));
					eObject = container;
				}

				StringBuffer result = new StringBuffer("/"); //$NON-NLS-1$
				result.append(getURIFragmentRootSegment(eObject));

				for (ListIterator i = uriFragmentPath
						.listIterator(uriFragmentPath.size()); i.hasPrevious();) {
					result.append('/');
					result.append((String) i.previous());
				}
				return result.toString();
			}
		} catch (RuntimeException e) {
			System.err.println("Error getting URI fragment for " + eObject); //$NON-NLS-1$
			throw e;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#attachedHelper(org.eclipse.emf.ecore.EObject)
	 */
	protected void attachedHelper(EObject eObject) {
		super.attachedHelper(eObject);

		if (useIDs()) {
			String id = getID(eObject);
			if (id != null) {
				// update the eObjectToIDMap
				//
				getEObjectToIDMap().put(eObject, id);
				
				if (eObject instanceof MethodElement) {
					((MultiFileResourceSetImpl) getResourceSet())
							.getGuidToMethodElementMap().put(id, eObject);
				}
			}
		}

		if (isTrackingModification() && eObject.eResource() != this) {
			// remove the modification tracking adapter from the eObject
			//
			eObject.eAdapters().remove(modificationTrackingAdapter);
		}
	}

	private void attachedAllWithIDs(EObject eObj) {
		// attachedHelper(eObj);
		// List list = eObj.eContents();
		// int size = list.size();
		// for (int i = 0; i < size; i++) {
		// EObject o = (EObject) list.get(i);
		// if (o.eResource() == this) {
		// attachedAllWithIDs(o);
		// }
		// }

		Iterator allContents = new ContentTreeIterator(eObj);

		while (allContents.hasNext()) {
			attachedHelper((EObject) allContents.next());
		}
	}

	private void basicAttachedAll(EObject eObj) {
		eObj.eAdapters().add(modificationTrackingAdapter);
		List list = eObj.eContents();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			EObject o = (EObject) list.get(i);
			if (o.eResource() == this) {
				basicAttachedAll(o);
			}
		}
	}

	/**
	 * Calls on an object and all of its offstring objects that are in the same
	 * resource as the object when the object is attached to this resource. This
	 * method is expensive, so use it with caution.
	 * 
	 * @param eObj
	 */
	public void attachedAll(EObject eObj) {
		if (useIDs()) {
			attachedAllWithIDs(eObj);
		} else {
			basicAttachedAll(eObj);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.Resource.Internal#attached(org.eclipse.emf.ecore.EObject)
	 */
	public void attached(EObject eObject) {
		attachedAll(eObject);
	}

	private void detachedAllWithIDs(EObject eObj) {
		Iterator allContents = new ContentTreeIterator(eObj);

		while (allContents.hasNext()) {
			detachedHelper((EObject) allContents.next());
		}
	}

	private void basicDetachedAll(EObject eObj) {
		eObj.eAdapters().remove(modificationTrackingAdapter);
		List list = eObj.eContents();
		int size = list.size();
		for (int i = 0; i < size; i++) {
			EObject o = (EObject) list.get(i);
			if (o.eResource() == this) {
				basicDetachedAll(o);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#getEObjectByID(java.lang.String)
	 */
	protected EObject getEObjectByID(String id) {
		for (Iterator iter = getContents().iterator(); iter.hasNext();) {
			EObject element = (EObject) iter.next();
			String guid = MultiFileSaveUtil.getGuid(element);
			if (guid != null && guid.equals(id))
				return element;
		}

		// return super.getEObjectByID(id);

		if (idToEObjectMap != null) {
			InternalEObject eObject = (InternalEObject) idToEObjectMap.get(id);
			if (eObject != null && !eObject.eIsProxy()) {
				return eObject;
			}
		}

		return null;
	}
	
	private IFileInfo getFileInfo() {
		if(fileInfo == null || !new File(getURI().toFileString()).equals(fileInfo.getFile())) {
			fileInfo = FileManager.getInstance().getFileInfo(this); 
		}
		return fileInfo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#load(java.util.Map)
	 */
	public void load(Map options) throws IOException {
		if (isUnloading) {
			return;
		}
		
		boolean old = DefaultValueManager.INSTANCE.isUseStatic();
		try {
			DefaultValueManager.INSTANCE.setUseStatic(true);
			super.load(options);		
			updateTimeStamps();
		}
		finally {
			DefaultValueManager.INSTANCE.setUseStatic(old);
		}
		
		if (MultiFileSaveUtil.DEBUG) {
			if (getURI().toString().equals(testResourceURIStr)) {
				testResourceLoaded = true;
			}
		}
	}

	private static boolean testResourceLoaded;

	private static final String testResourceURIStr = "file:/C:/temp/newlib/library.xmi"; //$NON-NLS-1$

	public long getModificationStamp() {
		return modificationStamp;
	}
	
	/**
	 * Reloads this resource. Old objects will become proxies and they will be
	 * added to the specified collection <code>proxies</code>
	 * 
	 * @param proxies
	 */
	synchronized boolean reload(Collection proxies) throws IOException {
		if (isLoaded) {
			Notification notification = setLoaded(false);
			doUnload(proxies, false);
			// doUnload() might have set this resource loaded again
			// set isLoaded to false and contents to null to make sure
			//
			isLoaded = false;
			contents = null;
			if (notification != null) {
				eNotify(notification);
			}
			load(getResourceSet().getLoadOptions());
			return true;
		}
		return false;
	}

	/*
	 * Javadoc copied from interface.
	 */
	final void unloadWithoutRemove() {
		if (isLoaded) {
			// save the ResourceDescriptor pf this resource for later use to
			// create URI for the proxies after unload
			//
			ResourceDescriptor resDesc = MultiFileSaveUtil
					.getResourceDescriptor(this);
			if (resDesc != null) {
				setResourceDescriptor(resDesc);
			}

			Notification notification = setLoaded(false);
			doUnload(null, false);
			if (notification != null) {
				eNotify(notification);
			}
		}
	}

	/**
	 * Does all the work of unloading the resource. It calls
	 * {@link #unloaded unloaded} for each object it the content
	 * {@link #getAllContents tree}, and clears the
	 * {@link #getContents contents}, {@link #getErrors errors}, and
	 * {@link #getWarnings warnings}.
	 */
	protected void doUnload() {
		doUnload(null, true);
	}

	/**
	 * @author Phong Nguyen Le - Jul 17, 2006
	 * @since 1.0
	 */
	private final class ContentTreeIterator extends AbstractTreeIterator {
		/**
		 * Comment for <code>serialVersionUID</code>
		 */
		private static final long serialVersionUID = 1L;

		/**
		 * @param object
		 */
		private ContentTreeIterator(Object object) {
			super(object);
		}

		protected Iterator getChildren(Object object) {
			if (object instanceof EObject) {
				ArrayList children = new ArrayList();
				EContentsEList contents = new EContentsEList((EObject) object) {
					/*
					 * (non-Javadoc)
					 * 
					 * @see org.eclipse.emf.ecore.util.EContentsEList#resolve()
					 */
					protected boolean resolve() {
						return false;
					}
				};
				for (Iterator iter = contents.basicIterator(); iter.hasNext();) {
					EObject o = (EObject) iter.next();
					if (o.eResource() == MultiFileXMIResourceImpl.this
							|| o.eIsProxy()) {
						children.add(o);
					}
				}
				return children.iterator();
			}
			return Collections.EMPTY_LIST.iterator();
		}
	}

	/**
	 * Unloads this resource. Old objects will be come proxies and will be added
	 * to the specified collection <code>proxies</code>
	 * 
	 * @param proxies
	 * @param remove
	 *            if <code>true</code> will remove all the unloaded objects in
	 *            the resource from their containers and all opposite feature
	 *            data of the unloaded objects will be cleared.
	 */
	protected void doUnload(Collection proxies, boolean remove) {
		isUnloading = true;

		try {
			// from ResourceImpl
			//

			Iterator allContents = getAllProperContents(new ArrayList(
					getContents()));

			// This guard is needed to ensure that clear doesn't make the
			// resource
			// become loaded.
			//
			if (!getContents().isEmpty()) {
				if (remove) {
					getContents().clear();
				} else {
					// don't call getContents().clear() to keep the references
					// to elements
					// that just became proxies after unload
					//
					contents = null;
				}

			}
			getErrors().clear();
			getWarnings().clear();

			ArrayList<EObject> unloadedObjects = new ArrayList<EObject>();
			
			ArrayList allContentList = new ArrayList();
			while (allContents.hasNext()) {
				allContentList.add(allContents.next());
			}
			Iterator it = allContentList.iterator();
			
			try {
				while (it.hasNext()) {
					try {
						InternalEObject o = (InternalEObject) it
								.next();
						unloaded(o, remove);
						unloadedObjects.add(o);
					} catch (Exception e) {
						CommonPlugin.INSTANCE.log(e);
					}
				}
			} catch (Exception e) {
				CommonPlugin.INSTANCE.log(e);
			}
			if (proxies != null && !unloadedObjects.isEmpty()) {
				proxies.addAll(unloadedObjects);
			}
			if (remove) {
				// remove the unloaded objects from its container to prevent the
				// whole library from staying
				// in memory if only one of its element is leaked
				// 
				for (Iterator iter = unloadedObjects.iterator(); iter.hasNext();) {
					EObject object = (EObject) iter.next();
					EcoreUtil.remove(object);
				}
			}

			// from XMLResourceIml
			//		

			if (idToEObjectMap != null) {
				for (Iterator iter = idToEObjectMap.keySet().iterator(); iter
						.hasNext();) {
					((MultiFileResourceSetImpl) getResourceSet())
							.getGuidToMethodElementMap().remove(iter.next());
				}
				idToEObjectMap.clear();
			}

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

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

			if (intrinsicIDToEObjectMap != null) {
				intrinsicIDToEObjectMap.clear();
			}
			
			modificationStamp = IResource.NULL_STAMP;
			
		} finally {
			isUnloading = false;
		}
	}

	protected void unloaded(InternalEObject internalEObject) {
		unloaded(internalEObject, true);
	}
	
	/**
	 * @param internalEObject
	 * @param clear
	 *            if <code>true</code> all opposite feature data of the
	 *            unloaded objects will be cleared.
	 */
	private void unloaded(InternalEObject internalEObject, boolean clear) {
		String guid = MultiFileSaveUtil.getGuid(internalEObject);
		if (guid != null) {
			URI uri = resourceDescriptor != null ? MultiFileURIConverter
					.createURI(resourceDescriptor.getId()) : getURI();
			internalEObject.eSetProxyURI(uri.appendFragment(guid));
		}
		internalEObject.eAdapters().clear();

		if (internalEObject instanceof MultiResourceEObject && clear) {
			MultiResourceEObject multiResourceEObject = ((MultiResourceEObject) internalEObject);

			// clear own opposite feature map
			//			
			Map oppositeFeatureMap = multiResourceEObject
					.basicGetOppositeFeatureMap();
			if (oppositeFeatureMap != null) {
				oppositeFeatureMap.clear();
			}

			// remove itself from all opposite features
			// 
			multiResourceEObject.removeFromAllOppositeFeatures();
		}
		
		if(internalEObject instanceof ContentDescription || internalEObject instanceof Section) {
			// set all string attributes to NULL to release memory
			//
			for (EAttribute attr : internalEObject.eClass().getEAllAttributes()) {
				if(attr != UmaPackage.eINSTANCE.getMethodElement_Guid() && 
						attr.getEAttributeType().getInstanceClass().isAssignableFrom(String.class)) {
					internalEObject.eSet(attr, attr.getDefaultValue());
				}
			}
			
			if(internalEObject.eDirectResource() != null && internalEObject instanceof MultiResourceEObject) {
				((MultiResourceEObject)internalEObject).eSetResource(null);
			}
		}
	}

	public void detachedAll(EObject eObj) {
		if (useIDs()) {
			detachedAllWithIDs(eObj);
		} else {
			basicDetachedAll(eObj);
		}
	}		

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.Resource.Internal#detached(org.eclipse.emf.ecore.EObject)
	 */
	public void detached(EObject eObject) {
		detachedAll(eObject);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#createModificationTrackingAdapter()
	 */
	protected Adapter createModificationTrackingAdapter() {
		return new ModificationTrackingAdapter() {
			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl.ModificationTrackingAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification)
			 */
			public void notifyChanged(Notification notification) {
				// don't handle OppositeFeatureNotification b/c it does not
				// really modify this resource
				//
				if (notification instanceof OppositeFeatureNotification) {
					return;
				}
				super.notifyChanged(notification);
			}
		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#setModified(boolean)
	 */
	public void setModified(boolean isModified) {
		// boolean wasModified = isModified();
		super.setModified(isModified);
		// if(MultiFileSaveUtil.getMethodElement(this) instanceof
		// ProcessComponent) {
		// System.out.println("MultiFileXMIResourceImpl.setModified(): " +
		// this);
		// }
		// this code is needed to set dirty flag to the item provider's label
		//
		// if(wasModified != isModified && !getContents().isEmpty()) {
		// // refresh the label of the resource's object
		// //
		// EObject obj = (EObject) getContents().get(0);
		// for (Iterator iter = obj.eAdapters().iterator(); iter.hasNext();) {
		// Object adapter = iter.next();
		// if(adapter instanceof ItemProviderAdapter) {
		// ((ItemProviderAdapter)adapter).fireNotifyChanged(new
		// ViewerNotification(new NotificationImpl(Notification.SET, obj, obj),
		// obj, false, true));
		// }
		// }
		// }

		if (MultiFileSaveUtil.DEBUG) {
			if (testResourceLoaded
					&& getURI().toString().equals(testResourceURIStr)) {
				System.out.println("isModified=" + isModified); //$NON-NLS-1$
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.common.notify.impl.NotifierImpl#eDeliver()
	 */
	public boolean eDeliver() {
		ResourceSet resourceSet = getResourceSet();
		if (resourceSet != null && !resourceSet.eDeliver())
			return false;

		return super.eDeliver();
	}

	public void save(Map options) throws IOException {
		boolean old = DefaultValueManager.INSTANCE.isUseStatic();
		
		Process proc = null;
		Scope scope = null;
		
		try {
			DefaultValueManager.INSTANCE.setUseStatic(true);
			
			if (options == null) {
				options = MultiFileResourceSetImpl.DEFAULT_SAVE_OPTIONS;
			}

			MethodElement e = PersistenceUtil.getMethodElement(this);
			if (e instanceof ProcessComponent) {
				proc = ((ProcessComponent) e).getProcess();
				if (proc != null && proc.getDefaultContext() instanceof Scope) {
					boolean oldDeliver = proc.eDeliver();
					try {
						proc.eSetDeliver(false);
						scope = (Scope) proc.getDefaultContext();
						proc.setDefaultContext(null);
						proc.getValidContext().clear();
					} finally {
						proc.eSetDeliver(oldDeliver);
					}
				}
			}			
			
			handleSynFreeFlag(e);
			
			super.save(options);

			// Special handling for saving MethodLibrary to remove all references to
			// MethodConfigurations from library file.
			//
			//MethodElement e = PersistenceUtil.getMethodElement(this);
			
			if (e instanceof MethodLibrary) {
				MethodLibrary lib = (MethodLibrary) e;
				// remove ResourceDescriptors of configuration files
				//
				ResourceManager resMgr = MultiFileSaveUtil.getResourceManager(this);
				if (resMgr != null) {
					for (Iterator iter = lib.getPredefinedConfigurations()
							.iterator(); iter.hasNext();) {
						MethodConfiguration config = (MethodConfiguration) iter
						.next();
						ResourceDescriptor resDesc = resMgr
						.getResourceDescriptor(config.getGuid());
						if (resDesc != null) {
							EcoreUtil.remove(resDesc);
						}
					}
				}
				List configs = new ArrayList(lib.getPredefinedConfigurations());
				boolean oldDeliver = lib.eDeliver();
				try {
					lib.eSetDeliver(false);
					lib.getPredefinedConfigurations().clear();

					// Save library file again to remove all references to configurations.
					// The previous save is still needed to save new configuration in its own file
					//
					super.save(options);
				} finally {
					lib.getPredefinedConfigurations().addAll(configs);
					lib.eSetDeliver(oldDeliver);
				}
			}
		}
		finally {
			DefaultValueManager.INSTANCE.setUseStatic(old);
			if (proc != null && scope != null) {
				boolean oldDeliver = proc.eDeliver();
				try {
					proc.eSetDeliver(false);
					proc.setDefaultContext(scope);
					proc.getValidContext().add(scope);
				} finally {
					proc.eSetDeliver(oldDeliver);
				}
			}
		}
	}

	public URI getFinalURI() {
		if (finalURI != null) {
			return finalURI;
		}
		return getURI();
	}

	public void setFinalURI(URI uri) {
		finalURI = uri;
	}

	public void backUpURI() {
		oldURI = getURI();
	}

	public boolean hasTempURI() {
		if (currentTxID != null) {
			return createTempURI().equals(getURI());
		}
		return false;
	}

	private URI createTempURI() {
		MethodElement e = PersistenceUtil.getMethodElement(this);
		return URI.createFileURI(new StringBuffer(getTempDir()).append(
				File.separator).append(currentTxID)
				.append("new").append(e.getGuid()).toString()); //$NON-NLS-1$
	}

	static String getTempDir() {
		if (tempDir == null) {
			tempDir = new File(FileManager.getTempDir(), "EPF").getAbsolutePath(); //$NON-NLS-1$
		}
		return tempDir;
	}

	/**
	 * Sets the temporary URI to save this resource to and it will be renamed to
	 * the original URI when saving is done
	 */
	public void setTempURI(String txID) {
		if (finalURI == null) {
			finalURI = oldURI = getURI();
			currentTxID = txID;

			URI tempURI = createTempURI();
			setURI(tempURI);

			MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
			resourceSet.getURIToTempURIMap().put(oldURI, tempURI);
		}
	}

	/**
	 * Restores the resource URI to the original one. This method must be call
	 * after saving regarless of its success.
	 * 
	 */
	private void restoreURI() {
		if (oldURI != null) {
			setURI(oldURI);
		}
	}

	public boolean txStarted() {
		return moveStarted() || saveStarted();
	}

	protected void updateTimeStamps() {
		FileManager.getInstance().refresh(this);
		lastLoadTimeStamp = System.currentTimeMillis();
		IFileInfo info = getFileInfo();
		if(info != null) {
			modificationStamp = info.getModificationStamp();
		}
	}
	
	/**
	 * Checks if this resource is currently synchronized with its data store
	 * 
	 * @return <li> -1 don't know
	 *         <li> 0 no
	 *         <li> 1 yes
	 * @deprecated use {@link #isSynchronized()} instead
	 */
	public int checkSynchronized() {
//		long currentTime = new File(getURI().toFileString()).lastModified();
//		if(MultiFileSaveUtil.same(currentTime, fileLastModified)) {
//			// some team providers changed the timestamp of last file modification by removing second fraction
//			// even the file was not changed
//			//
//			return 1;
//		}
//		return -1;
		return isSynchronized() ? 1 : 0;
	}
	
	public boolean isSynchronized() {
		IFileInfo fileInfo = getFileInfo();
		if (fileInfo != null) {
			return modificationStamp == fileInfo.getModificationStamp();
		}
		else {
			return true;
		}
	}

	public void txFinished(boolean successful) {
		boolean wasMove = !oldURI.equals(finalURI);
		if (successful) {
			setURI(finalURI);
			if(!wasMove) {
				setModified(false);
			}
			updateTimeStamps();
			if(!wasMove) {
				MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
				if(resourceSet != null) {
					resourceSet.getUnresolvedProxyMarkerManager().validateMarkers(this);
				}
			}
		} else {
			restoreURI();
			if (wasMove) {
				// finalURI must be cleared before restoring URI of its child
				// resources so the URI of its child resources can be resolved
				// correctly. See ResourceDescriptorImpl.getResolvedURI()
				//
				finalURI = null;
				
				// restore uri of ResourceDescriptor of this resource
				//
				MultiFileSaveUtil.updateURIMappings(this, oldURI, null, true);
			}
		}
		if (oldURI != null) {
			MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
			if (resourceSet != null) {
				resourceSet.getURIToTempURIMap().remove(oldURI);
			}
			oldURI = null;
		}
		currentTxID = null;
		finalURI = null;
	}

	public void deleteBackup() {
		if (backupFile != null) {
			try {
				// FileManager.getInstance().delete(backupFile);
				new File(backupFile).delete();
				backupFile = null;
			} catch (Throwable e) {
				CommonPlugin.INSTANCE.log(e);
				if (MultiFileSaveUtil.DEBUG) {
					e.printStackTrace();
				}
			}
		}
	}

	public boolean restore() {
		File src = null, dest = null;
		boolean moved = false;
		if (backupFile != null) {
			src = new File(backupFile);
			dest = new File(getFinalURI().toFileString());
		} else {
			moved = oldURI != null && !oldURI.equals(finalURI);
			if (moved) {
				File file = new File(getFinalURI().toFileString());
				dest = new File(oldURI.toFileString());
				moved = file.exists() && !dest.exists();
				if (moved) {
					src = file;
				}
			}
		}
		if (src != null) {
			if (dest.exists()) {
				FileUtil.moveFile(dest,new File(getURI().toFileString()));
			}
			boolean success;
			if (moved) {
				success = MultiFileSaveUtil.move(this, src, dest);
				// if(success) {
				// MultiFileSaveUtil.updateURIMappings(this, null);
				// }
			} else {
				// don't restore file if the source and destination are the same
				//
				success = src.lastModified() == dest.lastModified() && FileUtil.getSize(src) == FileUtil.getSize(dest);
				if(!success) {
					success = FileUtil.moveFile(src, dest);
				}
			}
			if (!success) {
				throw new MultiFileIOException(NLS.bind(PersistenceResources.restoreResourceError_msg, 
						FileManager.toFileString(getFinalURI())));
			}
			return true;
		}
		return false;
	}

	URI getOldURI() {
		return oldURI;
	}

	boolean moveStarted() {
		return oldURI != null && !oldURI.equals(getFinalURI());
	}

	boolean saveStarted() {
		return currentTxID != null;
	}
	
	private void refreshURIOfChildResources() {
		// refresh resolve URIs in ResourceDescriptors of the child
		// resources of this resource
		//
		HashMap<URI, ResourceDescriptor> oldURIToResourceDescriptorMap = null;
		ResourceManager resMgr = MultiFileSaveUtil
				.getResourceManager(this);
		if (resMgr != null) {
			oldURIToResourceDescriptorMap = new HashMap<URI, ResourceDescriptor>();
			for (Iterator<?> iter = resMgr.eAllContents(); iter
					.hasNext();) {
				Object obj = iter.next();
				if (obj instanceof ResourceDescriptor) {
					ResourceDescriptor desc = ((ResourceDescriptor) obj);
					oldURIToResourceDescriptorMap.put(desc
							.getResolvedURI(), desc);
					desc.clearResolvedURI();
				}
			}
		}

		// refresh URI of loaded child resources of this resource
		//
		if (oldURIToResourceDescriptorMap != null) {
			// go thru the list of loaded resources in resource set
			// to update the URI
			//
			for (Resource res : getResourceSet().getResources()) {
				ResourceDescriptor desc = (ResourceDescriptor) oldURIToResourceDescriptorMap
						.get(res.getURI());
				if (desc != null) {
					res.setURI(desc.getResolvedURI());
				}
			}
		}
	}

	public void commit() {
		if (finalURI != null && !getContents().isEmpty()) {
			File finalFile = new File(finalURI.toFileString());
			boolean wasMove = !oldURI.equals(finalURI);
			if (wasMove) {
				Object e = PersistenceUtil.getMethodElement(this);
				if (e instanceof ContentDescription) {
					if (finalFile.exists()) {
						// name for finalFile is already taken
						// try to get the next available name
						//
						finalURI = URI.createFileURI(MethodLibraryPersister
								.getNextAvailableFileName(finalFile.getParent()
										+ File.separator,
										(ContentDescription) e));
						finalFile = new File(finalURI.toFileString());
					}
				}
			} else {
				// back up the file
				//
				String backup = getBackupFilePath();
				File bakFile = new File(backup);

				// trying to delete the old backup file if it exists
				//
				if (bakFile.exists()) {
					bakFile.delete();
				}

				if (finalFile.exists()) {
					// some CM provider like ClearCase renamed the versioned
					// file it its repository as soon as user renamed the file
					// in the workspace. To avoid this, use only regular rename
					// routine of java.io.File instead of IResource routine
					//
					if (FileUtil.moveFile(finalFile, bakFile)) {
						backupFile = backup;
					} else {
						String msg = NLS.bind(
								PersistenceResources.renameError_msg,
								finalFile, backup);
						throw new MultiFileIOException(msg);
					}
				}
			}

			// rename the resource file to the original name
			//
			File currentFile = new File(wasMove ? oldURI.toFileString()
					: getURI().toFileString());
			boolean success = false;
			Exception ex = null;
			if (wasMove) {
				success = MultiFileSaveUtil.move(this, currentFile, finalFile);
			} else {
				// some CM provider like ClearCase renamed the versioned file in
				// its repository as soon as user renamed the file
				// in the workspace. To avoid this, use only regular rename
				// routine of java.io.File instead of IResource routine
				//
				try {
					FileUtil.doMoveFile(currentFile, finalFile);
					success = true;
				}
				catch(Exception e) {
					ex = e;
				}
			}
			if (!success) {
				String msg = NLS.bind(PersistenceResources.renameError_msg,
						currentFile, finalFile);
				if(ex != null) {
					msg = msg + ": "  + (ex.getMessage() != null ? ex.getMessage() : ex.toString()); //$NON-NLS-1$
				}
				throw new MultiFileIOException(msg);
			} else {
				if (wasMove) {
					// refresh resolve URI of ResourceDescriptor of this
					// resource
					//
					ResourceDescriptor resDesc = MultiFileSaveUtil
							.getResourceDescriptor(this);
					if (resDesc != null) {
						resDesc.clearResolvedURI();
						resDesc.getResolvedURI();
					} 
					else {
						if (MultiFileSaveUtil.DEBUG) {
							MethodElement e = PersistenceUtil
									.getMethodElement(this);
							if (e != null
									&& !getLibraryPersister()
											.hasOwnResourceWithoutReferrer(e)) {
								String msg = "FATAL ERROR: no ResourceDescriptor found in parent resource for " + this; //$NON-NLS-1$
								CommonPlugin.INSTANCE.log(msg);
								System.err.println(msg);
							}
						}
					}

					refreshURIOfChildResources();
				}

				RefreshJob.getInstance().resourceSaved(this);
			}
		}
	}

	public String getBackupFilePath() {
		String backupFile = new StringBuffer(getTempDir())
				.append(File.separator)
				.append(currentTxID)
				.append("old").append(PersistenceUtil.getMethodElement(this).getGuid()).toString(); //$NON-NLS-1$
		return backupFile;
	}

	/**
	 * @return the lastLoadTimeStamp
	 */
	public long getLastLoadTimeStamp() {
		return lastLoadTimeStamp;
	}

	static void clearDetachedEObjectToIDMap() {
		DETACHED_EOBJECT_TO_ID_MAP.clear();
	}

	/**
	 * @param resDesc
	 */
	void setResourceDescriptor(ResourceDescriptor resDesc) {
		resourceDescriptor = resDesc;
	}
	
	public ResourceDescriptor getResourceDescriptor() {
		return resourceDescriptor;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.library.persistence.ILibraryResource#getLoadStamp()
	 */
	public long getLoadStamp() {
		return getLastLoadTimeStamp();
	}

	public URI getProxyURI(EObject object) {
		String guid = MultiFileSaveUtil.getGuid(object);
		if (guid != null) {
			ResourceDescriptor resourceDescriptor = this.resourceDescriptor != null ? this.resourceDescriptor :
					MultiFileSaveUtil.getResourceDescriptor(this);
			URI uri = resourceDescriptor != null ? MultiFileURIConverter
					.createURI(resourceDescriptor.getId()) : getURI();
			return uri.appendFragment(guid);
		}
		return getURI().appendFragment(getID(object));
	}

	public void setTxID(String txID) {
		setTempURI(txID);
	}
	
	private ILibraryPersister getLibraryPersister() {
		return ((MultiFileResourceSetImpl)resourceSet).getPersister();
	}
	
	private void handleSynFreeFlag(MethodElement e) {
		if (e instanceof MethodPlugin || e instanceof ProcessComponent) {
			MethodLibrary lib = UmaUtil.getMethodLibrary(e);
			if (lib == null) {
				lib = ((MultiFileResourceSetImpl)resourceSet).getMethodLibrary();
			}
			if (lib != null) {
				boolean isSynFree = UmaUtil.isSynFreeLibrary(lib);
				if (isSynFree) {
					if (e instanceof MethodPlugin) {
						MethodPlugin p = (MethodPlugin) e;
						if (! UmaUtil.isSynFreePlugin(p)) {
							UmaUtil.setSynFreePlugin(p, true);
						}					
					}
				}
			}
		}
	}
}