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

		if(getResourceSet() == null) {
			System.out.println();
		}
		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();
		try {
			DefaultValueManager.INSTANCE.setUseStatic(true);
			
			if (options == null) {
				options = MultiFileResourceSetImpl.DEFAULT_SAVE_OPTIONS;
			}

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

	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);
			}
			FileManager.getInstance().refresh(this);
			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;
	}

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