/******************************************************************************
 * Copyright (c) 2002, 2009 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 API and implementation 
 ****************************************************************************/

package org.eclipse.gmf.runtime.emf.core.internal.resources;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import java.util.Map.Entry;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IPathVariableChangeEvent;
import org.eclipse.core.resources.IPathVariableChangeListener;
import org.eclipse.core.resources.IPathVariableManager;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.emf.core.internal.plugin.EMFCoreDebugOptions;
import org.eclipse.gmf.runtime.emf.core.internal.plugin.EMFCorePlugin;
import org.eclipse.gmf.runtime.emf.core.internal.util.EMFCoreConstants;
import org.eclipse.gmf.runtime.emf.core.resources.GMFResource;
import org.eclipse.gmf.runtime.emf.core.resources.IPathmapManager;
import org.eclipse.gmf.runtime.emf.core.resources.IPathmapManager2;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
import org.osgi.framework.Bundle;
import org.osgi.service.prefs.BackingStoreException;

/**
 * This class manages GMF path mappings for URI conversion.
 * 
 * @author rafikj
 */
public class PathmapManager extends AdapterImpl implements IPathmapManager, IPathmapManager2 {
	// path maps can be defined using an extension point: Pathmaps
	//  or by referencing an eclipse path variable
	//  or by adding a pathmap manually

	// The variable name.
	private static final String NAME = "name"; //$NON-NLS-1$

	//The plugin containing the path.
	private static final String PLUGIN = "plugin"; //$NON-NLS-1$

	// The path.
	private static final String PATH = "path"; //$NON-NLS-1$
	
	private static final String NODE_QUALIFIER = EMFCorePlugin.getDefault().getBundle().getSymbolicName();
	private static final String PREFERENCE_KEY = "referenced.path.variables"; //$NON-NLS-1$

	// The path map as defined by the extensions and the referenced path variables and the manually
	//  added pathmaps.
	private static final Map PATH_MAP = Collections.synchronizedMap(configure());
	private static final Set FILE_VARIABLES = Collections.synchronizedSet(new HashSet());
	
	private static final Map instances = Collections.synchronizedMap(new WeakHashMap());
	
	// The list of eclipse path variables that are being used in this path map manager
	private static Set referencedPathVariablesList;
	
	private static IEclipsePreferences preferenceStore = null;
	
	static {
		IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager();
		
		// We will get the initial list of referenced path variables from our preference store
		IEclipsePreferences preferences = getPreferenceStore();
		String referencedPathVariables = preferences.get(PREFERENCE_KEY, ""); //$NON-NLS-1$
		StringTokenizer tokenizer = new StringTokenizer(referencedPathVariables, " "); //$NON-NLS-1$
		referencedPathVariablesList = new HashSet(tokenizer.countTokens());
		for (;tokenizer.hasMoreTokens();) {
			String pathVariable = tokenizer.nextToken();
			addPathVariableReference(pathVariable);
		}
		// Update the preference store in case some path variables have been deleted since the
		//  last time we saved the store.
		updatePreferenceStore();
		
		// Register this listener to keep up-to-date with the eclipse path variables and update our
		//  referenced path variables appropriately.
		pathManager.addChangeListener(new IPathVariableChangeListener() {
			public void pathVariableChanged(IPathVariableChangeEvent event) {
				switch (event.getType()) {
					case IPathVariableChangeEvent.VARIABLE_DELETED:
						removePathVariableReference(event.getVariableName());
						updatePreferenceStore();
						break;
					case IPathVariableChangeEvent.VARIABLE_CHANGED:
						// We only care about variables that we are referencing that
						//  have changed.
						if (referencedPathVariablesList.contains(event.getVariableName())) {
							// Check to see if it has become incompatible
							if (!isDirectory(event.getValue())) {
								removePathVariableReference(event.getVariableName());
							} else {
								setPathVariable(event.getVariableName(), URI.createFileURI(event.getValue().toString()).toString());
							}
							
							updatePreferenceStore();
						}
						break;
				}
			}
		});
	}

	private static IEclipsePreferences getPreferenceStore() {
		if (preferenceStore == null) {
			IScopeContext ctx = new InstanceScope();
			preferenceStore = ctx.getNode(NODE_QUALIFIER);
		}
		
		return preferenceStore;
	}
	
	/**
	 * Adds a new reference to a path variable defined in eclipse
	 *  to be used by this pathmap manager. It is assumed that this
	 *  path variable is declared in the eclipes path variable manager
	 *  and that it is a valid path variable for our purposes. 
	 *  See {@link #isCompatiblePathVariable(String)} for more details.
	 *  
	 * @param pathVariable A valid path variable that has been defined in the
	 *  eclipse {@link IPathVariableManager} and is compatible with our path maps.
	 */
	public static void addPathVariableReference(String pathVariable) {
		if (getAllPathVariables().contains(pathVariable)) {
			// We already reference this path variable so we can assume that it is added
			//  and is compatible.
			return;
		}
		
		if (!isCompatiblePathVariable(pathVariable)) {
			return;
		}
		
		IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager();
		IPath value = pathManager.getValue(pathVariable);
		if (value != null) {
			referencedPathVariablesList.add(pathVariable);
			setPathVariable(pathVariable, URI.createFileURI(value.toString()).toString());
		}
	}
	
	/**
	 * Updates the preference store with the current set of path variables that this manager
	 *  is currently referencing from the eclipse {@link IPathVariableManager}.
	 */
	public static void updatePreferenceStore() {
		StringBuffer referencedPathVariables = new StringBuffer();
		for (Iterator i = referencedPathVariablesList.iterator(); i.hasNext();) {
			referencedPathVariables.append((String)i.next());
			referencedPathVariables.append(' ');
		}
		
		getPreferenceStore().put(PREFERENCE_KEY, referencedPathVariables.toString());
		try {
			getPreferenceStore().flush();
		} catch (BackingStoreException e) {
			EMFCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, EMFCorePlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e));
		}
	}
	
	/**
	 * Removes a reference to a path variable defined in eclipse that was being
	 *  used by this pathmap manager.
	 *  
	 * @param pathVariable A path variable that was once referenced by this pathmap
	 *  manager pointing to a variable declared in the eclipse {@link IPathVariableManager}.
	 */
	public static void removePathVariableReference(String pathVariable) {
		if (referencedPathVariablesList.contains(pathVariable)) {
			referencedPathVariablesList.remove(pathVariable);
			unsetPathVariable(pathVariable);
		}
	}
	
	public static Set getPathVariableReferences() {
		return Collections.unmodifiableSet(referencedPathVariablesList);
	}
	
	/**
	 * Obtains a set of all path variable names, registered on the extension
	 * point and referenced from Eclipse Platform path variables.
	 * 
	 * @return the set of all mapped path variables
	 */
	public static Set getAllPathVariables() {
		return Collections.unmodifiableSet(PATH_MAP.keySet());
	}
	
	/**
	 * Queries whether the specified path variable name is registered on the
	 * extension point (versus selected by the user from the platform variables).
	 * 
	 * @param variable the variable name
	 * 
	 * @return <code>true</code> if this variable name is registered on the
	 *     path maps extension point; <code>false</code>, otherwise
	 */
	public static boolean isRegisteredPathVariable(String variable) {
		return PATH_MAP.containsKey(variable)
				&& !referencedPathVariablesList.contains(variable);
	}
	
	/**
	 * If the specified <code>variable</code> is registered on the extension
	 * point, then retrieve its value.
	 * 
	 * @param variable the registered variable to retrieve
	 * @return the registered variable's value or <code>null</code> if
	 *     it is not registered
	 */
	public static String getRegisteredValue(String variable) {
		return (String) PATH_MAP.get(variable);
	}
	
	public static boolean isCompatiblePathVariable(String variable) {
		if (referencedPathVariablesList.contains(variable)) {
			// We assume that if this variable is already referenced then it is valid.
			return true;
		}
		
		IPathVariableManager pathManager = ResourcesPlugin.getWorkspace().getPathVariableManager();
		IPath value = pathManager.getValue(variable);
		
		if (value == null)
			return false;
		
		// Check to see if it is a directory first.
		// EMF will not correctly handle extension parsing
		//  of a pathmap URI if we point directly to a file. This
		//  means that the wrong resource factory could be called.
		// This could possibly change in the future.
		return isDirectory(value);
	}

	private static boolean isDirectory(IPath value) {
		File f = new File(value.toString());
		return (f.isDirectory());
	}

	/**
	 * Constructor.
	 */
	public PathmapManager() {

		super();

		instances.put(this, Boolean.TRUE);
	}

	/**
	 * Obtains all of the instances of this class.
	 * 
	 * @return my instances
	 */
	private static Set allInstances() {
		return instances.keySet();
	}
	
	/**
	 * Obtains the pathmap manager attached to the specified resource set, if any.
	 * 
	 * @param rset a resource set
	 * @return the attached pathmap manager, or <code>null</code> if none
	 */
	public static PathmapManager getExistingPathmapManager(ResourceSet rset) {
		PathmapManager result = null;
		List adapters = rset.eAdapters();
		
		for (int i = 0, size = adapters.size(); (result == null) && (i < size); i++) {
			Object next = adapters.get(i);
			
			if (next instanceof PathmapManager) {
				result = (PathmapManager) next;
			}
		}
		
		return result;
	}
	
	/**
	 * Set the value of a pathmap variable. Dirties any resources
	 *  that have HREF's that need to be changed.
	 * 
	 * @param var the path map variable name
	 * @param val the path map variable value (must be an encoded URI)
	 */
	public static void setPathVariable(String var, String val) {
		setPathVariable(var, val, true);
	}
	
	/**
	 * Sets the value of a pathmap variable (a folder). The provided flag
	 *  determines if resources should be dirtied if they have HREF's that
	 *  should be changed.
	 *  
	 * @param var the path map variable name
	 * @param val the path map variable value (must be an encoded URI)
	 * @param dirtyResources true, if resources should be dirtied so that
	 *  their modified HREF's are saved. false, otherwise.
	 */
	public static void setPathVariable(String var, String val, boolean dirtyResources) {
		internalSetPathVariable(var, val);

		for (Iterator i = allInstances().iterator(); i.hasNext();) {
			((PathmapManager) i.next()).resyncEntries(true, dirtyResources);
		}
	}

	private static void internalSetPathVariable(String var, String val) {
		// We must try to determine if this pathmap resides in the workspace as some container
		//  so that we store into the pathmap a substitution that is a platform:/resource 
		//  type of substitution. This is required because otherwise, pathmap URIs normalize
		//  to file URIs while platform URIs do not normalize, they remain as platform URIs.
		//  This will break some comparisons that might occur when trying to load a resource
		//  that is already loaded because the normalized version of the platform URI to be loaded
		//  will not match the normalized version of the pathmap URI causing two instances of
		//  the same resource to be loaded.
		java.net.URI valURI = java.net.URI.create(val);
		IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(valURI);
		if (containers.length == 1) {
			val = URI.createPlatformResourceURI(containers[0].getFullPath().toString(),true).toString();
		}
		IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(valURI);
		if (files.length == 1) {
			val = URI.createPlatformResourceURI(files[0].getFullPath().toString(),true).toString();
		}
		
		PATH_MAP.put(var, val);
	}
	
	/**
	 * Set the value of a pathmap variable to point to a specific file (not a folder). The
	 *  provided flag determines whether resource should be dirtied if their HREF's need to
	 *  be changed.
	 * 
	 * @param var the path map variable name
	 * @param val the path map variable value (must be an encoded URI pointing to a file, not a folder)
	 * @param dirtyResources true, if resources should be dirtied so that their HREF's can be
	 * changed. false, otherwise.
	 */
	public static void setFilePathVariable(String var, String val, boolean dirtyResources) {
		FILE_VARIABLES.add(var);
		internalSetPathVariable(var, val);
		for (Iterator i = allInstances().iterator(); i.hasNext();) {
			((PathmapManager) i.next()).resyncEntries(true, dirtyResources);
		}
	}
	
	/**
	 * Sets the value of a map of pathmap variables to point to specific files (not folders)
	 * The provided flag determines whether resource should be dirtied if their HREF's need to
	 * be changed.
	 *
	 * @param settings A map of new variables(Strings) to their values(Strings).
	 * @param dirtyResource true, if resources should be dirtied so that their HREF's can
	 *  be changed. false, otherwise.
	 */
	public static void setFilePathVariables(Map settings, boolean dirtyResources) {
		FILE_VARIABLES.addAll(settings.keySet());
		
		for (Iterator i = settings.entrySet().iterator(); i.hasNext();) {
			Map.Entry entry = (Map.Entry)i.next();
			internalSetPathVariable((String)entry.getKey(), (String)entry.getValue());
		}
		
		for (Iterator i = allInstances().iterator(); i.hasNext();) {
			((PathmapManager) i.next()).resyncEntries(true, dirtyResources);
		}
	}
	
	/**
	 * Sets the value of a map of pathmap variables to point specific folders (not files).
	 * The provided flag determines whether resource should be dirtied if their HREF's need
	 * to be changed.
	 * 
	 * @param settings A map of new variables(Strings) to their values(Strings).
	 * @param dirtyResource ture, if resources should be dirtied so that their HREF's can
	 *  be changed. false, otherwise.
	 */
	public static void setPathVariables(Map settings, boolean dirtyResources) {
		for (Iterator i = settings.entrySet().iterator(); i.hasNext();) {
			Map.Entry entry = (Map.Entry)i.next();
			internalSetPathVariable((String)entry.getKey(), (String)entry.getValue());
		}
		
		for (Iterator i = allInstances().iterator(); i.hasNext();) {
			((PathmapManager) i.next()).resyncEntries(true, dirtyResources);
		}
	}

	public IStatus addPathVariable(String name, String value) {
		setPathVariable(name, value);
		
		return Status.OK_STATUS; // TODO: report accurate status
	}
	
	public IStatus addFilePathVariable(String name, String value, boolean dirtyResources) {
		setFilePathVariable(name, value, dirtyResources);
		
		return Status.OK_STATUS; // TODO: report accurate status
	}
	
	public IStatus addFilePathVariables(Map settings, boolean dirtyResources) {
		setFilePathVariables(settings, dirtyResources);
		
		return Status.OK_STATUS; // TODO: report accurate status
	}
	
	public IStatus addFolderPathVariable(String name, String value, boolean dirtyResources) {
		setPathVariable(name, value, dirtyResources);
		
		return Status.OK_STATUS;
	}
	
	public IStatus addFolderPathVariables(Map settings, boolean dirtyResources) {
		setPathVariables(settings, dirtyResources);
		
		return Status.OK_STATUS;
	}
	
	/**
	 * Remove a pathmap variable.
	 */
	public static void unsetPathVariable(String var) {
		PATH_MAP.remove(var);

		for (Iterator i = allInstances().iterator(); i.hasNext();) {
			((PathmapManager) i.next()).resyncEntries(true, true);
		}
	}
	
	public IStatus removePathVariable(String name) {
		unsetPathVariable(name);
		
		return Status.OK_STATUS; // TODO: report accurate status
	}
	
	/**
	 * Obtains the resource set for which I manage the path mappings.
	 * 
	 * @return my resource set
	 */
	private ResourceSet getResourceSet() {
		return (ResourceSet) getTarget();
	}

	/**
	 * Get the value of a pathmap variable.
	 * 
	 * @param var the path map variable name
	 * @return the path map variable value (a URI) or an empty string if
	 *    the specified variable is undefined
	 */
	public String getPathVariable(String var) {

		URI varURI = makeURI(var);

		if (varURI != null) {

			URI valURI = (URI) getURIMap().get(varURI);

			if (valURI != null) {

				String val = valURI.toString();

				if (val != null) {

					int len = val.length();

					if (len != 0) {

						if (val.charAt(len - 1) == EMFCoreConstants.PATH_SEPARATOR)
							val = val.substring(0, len - 1);

						return val;
					}
				}
			}
		}

		return EMFCoreConstants.EMPTY_STRING;
	}

	/**
	 * Configure the Pathmaps extension point.
	 */
	private static Map configure() {
		Map paths = new HashMap();
		
		IConfigurationElement[] configs = Platform.getExtensionRegistry()
				.getExtensionPoint(EMFCorePlugin.getPluginId(), "Pathmaps") //$NON-NLS-1$
				.getConfigurationElements();

		for (int i = 0; i < configs.length; ++i) {

			IConfigurationElement element = configs[i];

			String var = element.getAttribute(NAME);

			if ((var == null) || (var.length() == 0))
				continue;

			String path = element.getAttribute(PATH);

			if (path == null)
				path = EMFCoreConstants.EMPTY_STRING;

			String plugin = element.getAttribute(PLUGIN);

			if ((plugin == null) || (plugin.length() == 0))
				plugin = element.getDeclaringExtension().getNamespaceIdentifier();

			Bundle bundle = Platform.getBundle(plugin);

			if (bundle == null)
				continue;

			URL url = bundle.getEntry(path);

			if (url == null)
				continue;

			try {
				url = FileLocator.resolve(url);

				if (url == null)
					continue;
				
				// We must encode here because everything that is placed into the path
				//  map must be encoded to match the encoded URI's on each resource
				//  in the resource set.
				paths.put(var, URI.createURI(url.toString(),true).toString());
			} catch (IOException e) {
				Trace.catching(EMFCorePlugin.getDefault(),
					EMFCoreDebugOptions.EXCEPTIONS_CATCHING, PathmapManager.class,
					"configure", e); //$NON-NLS-1$
			}
		}

		return paths;
	}
	
	public void notifyChanged(Notification msg) {
		if (msg.getFeatureID(ResourceSet.class) == ResourceSet.RESOURCE_SET__RESOURCES) {
			switch (msg.getEventType()) {
			case Notification.ADD:
				denormalize((Resource) msg.getNewValue(), getResourceSet().getURIConverter());
				break;
			case Notification.ADD_MANY:
				List resources = (List)msg.getNewValue();
				if (resources == null)
					break;
				
				for (Iterator i = resources.iterator(); i.hasNext();) {
					denormalize((Resource)msg.getNewValue(), getResourceSet().getURIConverter());
				}
				break;
			case Notification.REMOVE:
				normalize((Resource)msg.getOldValue(), getResourceSet().getURIConverter());
				break;
			case Notification.REMOVE_MANY:
				resources = (List)msg.getNewValue();
				if (resources == null)
					break;
				
				for (Iterator i = resources.iterator(); i.hasNext();) {
					normalize((Resource)msg.getNewValue(), getResourceSet().getURIConverter());
				}
				break;
			}
		}
	}

	public void setTarget(Notifier newTarget) {
		// get the old resource set
		ResourceSet rset = getResourceSet();
		
		if (rset != null) {
			// remove all path mappings from existing resources
			resyncEntries(false, true);
		}
		
		super.setTarget(newTarget);
		
		// get the new resource set
		rset = getResourceSet();
		
		if (rset != null) {
			// denormalize all resources using the path mappings
			resyncEntries(true, true);
		}
	}
	
	/**
	 * Add all entries.
	 */
	private void resyncEntries(boolean resync, boolean dirtyResources) {

		// save URIs of all resources.
		Map savedURIs = new HashMap();

		ResourceSet rset = getResourceSet();
		
		if (rset == null)
			return;

		for (Iterator i = rset.getResources().iterator(); i.hasNext();) {

			Resource resource = (Resource) i.next();

			URI uri = resource.getURI();

			savedURIs.put(resource, uri);
		}

		// normalize all resource URIs before clearing the map.
		normalizeAll();

		// get the URI Map.
		Map uriMap = getURIMap();

		// save the URI Map.
		Map savedURIMap = new HashMap();
		
		Set<Entry<?,?>> uriMapEntrySet = uriMap.entrySet();
		for (Entry<?, ?> uriMapEntry : uriMapEntrySet) {
			URI key = (URI) uriMapEntry.getKey();

			if ((key != null)
				&& (!EMFCoreConstants.PATH_MAP_SCHEME.equals(key.scheme())))
				savedURIMap.put(key, uriMapEntry.getValue());
		}
		
		// clear the map.
		getURIMap().clear();

		if (resync) {
			synchronized(PATH_MAP) {
				// rebuild the map.
				for (Iterator i = PATH_MAP.entrySet().iterator(); i.hasNext();) {
		
					Map.Entry entry = (Entry) i.next();
		
					addEntry((String) entry.getKey(), (String) entry.getValue());
				}
			}
		}
		
		// restore the map.
		Set<Entry<?, ?>> savedURIEntrySet = savedURIMap.entrySet();
		for (Entry<?, ?> savedURIEntry : savedURIEntrySet) {
			URI key = (URI) savedURIEntry.getKey();
			if(key != null){
				uriMap.put(key, savedURIEntry.getValue());
			}
		}

		if (resync) {
			// denormalize all.
			denormalizeAll();
		}
		
		// if some resources have changed their URI, ensure their exports are
		// dirtied.
		if (dirtyResources) {
			for (Iterator i = rset.getResources().iterator(); i.hasNext();) {
	
				Resource resource = (Resource) i.next();
	
				URI uri = resource.getURI();
	
				URI savedURI = (URI) savedURIs.get(resource);
	
				if (uri != savedURI) {
	
					if ((uri != null) && (!uri.equals(savedURI))) {
	
						Collection exports = EMFCoreUtil.getExports(resource);
	
						for (Iterator j = exports.iterator(); j.hasNext();) {
	
							Resource export = (Resource) j.next();
	
							if (!export.isModified())
								export.setModified(true);
						}
					}
				}
			}
		}
	}

	/**
	 * Add entry to map.
	 */
	private void addEntry(String var, String val) {

		URI varURI = makeURI(var);

		if (varURI != null) {

			int len = val.length();

			if (len == 0)
				return;

			StringBuffer uri = new StringBuffer();

			uri.append(val);

			// TODO
			if (!FILE_VARIABLES.contains(var) && val.charAt(len - 1) != EMFCoreConstants.PATH_SEPARATOR)
				uri.append(EMFCoreConstants.PATH_SEPARATOR);

			URI valURI = URI.createURI(uri.toString());

			getURIMap().put(varURI, valURI);
		}
	}

	/**
	 * Normalize the URI of a set of resources.
	 */
	private void normalizeAll() {

		ResourceSet rset = getResourceSet();

		URIConverter converter = rset.getURIConverter();

		if (converter != null) {

			for (Iterator i = rset.getResources().iterator(); i
				.hasNext();) {

				Resource resource = (Resource) i.next();
				normalize(resource, converter);
			}
		}
	}
	
	private void normalize(Resource resource, URIConverter converter) {
		URI uri = resource.getURI();
		
		if (uri == null)
			return;
		
		if ((EMFCoreConstants.PATH_MAP_SCHEME.equals(uri.scheme()))
				&& (resource instanceof GMFResource)) {

				((GMFResource) resource)
					.setRawURI(converter.normalize(uri));
			}
	}

	/**
	 * Denormalize the URI of a set of resources.
	 */
	private void denormalizeAll() {

		ResourceSet rset = getResourceSet();

		URIConverter converter = rset.getURIConverter();

		if (converter != null) {

			for (Iterator i = rset.getResources().iterator(); i
				.hasNext();) {

				Resource resource = (Resource) i.next();
				denormalize(resource, converter);
			}
		}
	}
	
	private void denormalize(Resource resource, URIConverter converter) {
		URI uri = resource.getURI();
		
		if (uri == null)
			return;

		if (resource instanceof GMFResource)
			((GMFResource) resource).setURI(converter.normalize(uri));
	}

	/**
	 * Make a pathmap uri from a pathmap variable name.
	 */
	private static URI makeURI(String var) {

		int len = var.length();

		if (len == 0)
			return null;

		StringBuffer uri = new StringBuffer();

		uri.append(EMFCoreConstants.PATH_MAP_SCHEME);
		uri.append(EMFCoreConstants.SCHEME_SEPARATOR);
		uri.append(EMFCoreConstants.PATH_SEPARATOR);
		uri.append(EMFCoreConstants.PATH_SEPARATOR);
		uri.append(var);

		//TODO
		if (!FILE_VARIABLES.contains(var) && var.charAt(len - 1) != EMFCoreConstants.PATH_SEPARATOR)
			uri.append(EMFCoreConstants.PATH_SEPARATOR);

		return URI.createURI(uri.toString());
	}

	/**
	 * Get EMF's URI map.
	 */
	private Map getURIMap() {
		return getResourceSet().getURIConverter().getURIMap();
	}

	/**
	 * Denormalizes a given resource's URI to a pathmap URI if it is possible.
	 * 
	 * @param uri A file or platform URI that has been denormalized as much
	 *  possible.
	 *  
	 * @return The original URI if it could not be denormalized any further
	 *  or a new pathmap URI otherwise.
	 */
	public static URI denormalizeURI(URI uri) {
		String uriAsString = uri.toString();
		
		String maxValueString = null;
		String maxKey = null;
		
		synchronized(PATH_MAP) {
			for (Iterator i = PATH_MAP.entrySet().iterator(); i.hasNext();) {
				Map.Entry entry = (Map.Entry)i.next();
				String valueString = (String)entry.getValue();
				
				// Wipe out the trailing separator from the value if necessary
				if (valueString.endsWith("/")) { //$NON-NLS-1$
					valueString = valueString.substring(0,valueString.length()-1);
				}

				if ((uriAsString.startsWith(valueString) &&
					(valueString.length() == uriAsString.length() || 
				     uriAsString.charAt(valueString.length()) == EMFCoreConstants.PATH_SEPARATOR))
				    && (maxValueString == null || maxValueString.length() < valueString.length())) {
					
					maxValueString = valueString;
					maxKey = (String)entry.getKey();
				}
			}
		}
		
		if (maxKey != null) {
			URI valueURI = URI.createURI(maxValueString);
			URI pathmapURI = makeURI(maxKey);
			
			int segmentStart = valueURI.segmentCount();
			int segmentCount = uri.segmentCount();
			
			for (int j=segmentStart; j < segmentCount; j++) {
				pathmapURI = pathmapURI.appendSegment(uri.segment(j));
			}
			
			return pathmapURI;
		}
		
		return uri;
	}
}