//------------------------------------------------------------------------------
// 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.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.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.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.ecore.impl.MultiResourceEObject;
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;

	private long fileLastModified;

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#load(java.util.Map)
	 */
	public void load(Map options) throws IOException {
		if (isUnloading) {
			return;
		}
		super.load(options);
		updateTimeStamps();
		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$

	/**
	 * @return the fileLastModified
	 */
	public long getFileLastModified() {
		return fileLastModified;
	}

	/**
	 * 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.
	 */
	public 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.
	 */
	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;
				}

				// Map objToContainerMap = null;
				// Map containerToDeliverMap = null;
				// if(!remove) {
				// objToContainerMap = MultiFileSaveUtil.getContainers(this);
				// if(!objToContainerMap.isEmpty()) {
				// // save the current deliver flag of all containers of content
				// objects
				// // and disable notification on those container so
				// getContent().clear() will
				// // not dispatch notification that might update UI. And we
				// don't want to update
				// // UI at this stage
				// //
				// containerToDeliverMap = new HashMap();
				// for (Iterator iter = objToContainerMap.values().iterator();
				// iter.hasNext();) {
				// EObject container = (EObject) iter.next();
				// containerToDeliverMap.put(container, new
				// Boolean(container.eDeliver()));
				// container.eSetDeliver(false);
				// }
				// }
				// }
				// getContents().clear();
				// if(!remove && containerToDeliverMap != null) {
				// // restore the container of contents objects
				// //
				// for (Iterator iter = objToContainerMap.entrySet().iterator();
				// iter.hasNext();) {
				// Map.Entry entry = (Map.Entry) iter.next();
				// MultiResourceEObject obj =
				// ((MultiResourceEObject)entry.getKey());
				// InternalEObject container = (InternalEObject)
				// entry.getValue();
				// obj.eBasicSetContainer(container, obj.eContainerFeatureID());
				// }

				// // restore the deliver flag of contents objects;
				// //
				// for (Iterator iter =
				// containerToDeliverMap.entrySet().iterator(); iter.hasNext();)
				// {
				// Map.Entry entry = (Map.Entry) iter.next();
				// EObject container = (EObject) entry.getKey();
				// boolean deliver = ((Boolean)entry.getValue()).booleanValue();
				// container.eSetDeliver(deliver);
				// }
				// }
			}
			getErrors().clear();
			getWarnings().clear();

			ArrayList unloadedObjects = new ArrayList();
			try {
				while (allContents.hasNext()) {
					try {
						InternalEObject o = (InternalEObject) allContents
								.next();
						unloaded(o);
						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();
			}
		} finally {
			isUnloading = false;
		}
	}

	protected void unloaded(InternalEObject internalEObject) {
		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) {
			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();
		}
	}

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

	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$
	}

	private 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() {
		lastLoadTimeStamp = System.currentTimeMillis();
		fileLastModified = new File(getURI().toFileString()).lastModified();
	}
	
	/**
	 * Checks if this resource is currently synchronized with its data store
	 * 
	 * @return <li> -1 don't know
	 *         <li> 0 no
	 *         <li> 1 yes
	 */
	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;
	}

	public void txFinished(boolean successful) {
		boolean wasMove = !oldURI.equals(finalURI);
		if (successful) {
			setURI(finalURI);
			setModified(false);
			updateTimeStamps();
			FileManager.getInstance().refresh(this);
			if(!wasMove) {
				MultiFileResourceSetImpl resourceSet = (MultiFileResourceSetImpl) getResourceSet();
				if(resourceSet != null) {
					resourceSet.getUnresolvedProxyMarkerManager().validateMarkers(this);
				}
			}
		} else {
			restoreURI();
			if (wasMove) {
				// 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 {
				success = FileUtil.moveFile(src,dest);
			}
			if (!success) {
				throw new MultiFileIOException(NLS.bind(
						PersistenceResources.restoreResourceError_msg, this));
			}
			return true;
		}
		return false;
	}

	URI getOldURI() {
		return oldURI;
	}

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

	boolean saveStarted() {
		return currentTxID != null;
	}

	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;
			if (wasMove) {
				success = MultiFileSaveUtil.move(this, currentFile, finalFile);
			} else {
				// 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
				//
				success = FileUtil.moveFile(currentFile, finalFile);
			}
			if (!success) {
				String msg = NLS.bind(PersistenceResources.renameError_msg,
						currentFile, finalFile);
				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();
					} else {
						String msg = "FATAL ERROR: no ResourceDescriptor found in parent resource for " + this; //$NON-NLS-1$
						CommonPlugin.INSTANCE.log(msg);
						System.err.println(msg);
					}

					// refresh resolve URIs in ResourceDescriptors of the child
					// resources of this resource
					//
					HashMap oldURIToResourceDescriptorMap = null;
					ResourceManager resMgr = MultiFileSaveUtil
							.getResourceManager(this);
					if (resMgr != null) {
						oldURIToResourceDescriptorMap = new HashMap();
						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 (Iterator iter = getResourceSet().getResources()
								.iterator(); iter.hasNext();) {
							Resource res = (Resource) iter.next();
							ResourceDescriptor desc = (ResourceDescriptor) oldURIToResourceDescriptorMap
									.get(res.getURI());
							if (desc != null) {
								res.setURI(desc.getResolvedURI());
							}
						}
					}
				}

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