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

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