/*******************************************************************************
 * Copyright (c) 2011, 2018 Obeo 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:
 *     Obeo - initial API and implementation
 *     Michael Borkowski - public visibility
 *******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.logical.resolver;

import com.google.common.collect.Sets;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.AbstractEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.ide.internal.utils.DisposableResourceSet;
import org.eclipse.emf.compare.ide.internal.utils.INamespaceDeclarationListener;
import org.eclipse.emf.compare.ide.internal.utils.IProxyCreationListener;
import org.eclipse.emf.compare.ide.internal.utils.NoNotificationParserPool;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.ContentHandler;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;

/**
 * A thread-safe implementation of a ResourceSet that will prevent loading of resources unless explicitly
 * demanded through {@link #loadResource(URI)}.
 * 
 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
 */
// Visible for testing
public class SynchronizedResourceSet extends ResourceSetImpl implements DisposableResourceSet {
	/** The logger. */
	private static final Logger LOGGER = Logger.getLogger(SynchronizedResourceSet.class);

	/** Associates URIs with their resources. */
	private final ConcurrentHashMap<URI, Resource> uriCache;

	/**
	 * The list of URIs corresponding to namespaces as declared in the xml files ("xmlns:"). These must not go
	 * through our usual xml parser as they have to be properly (and completely) loaded. They also need to be
	 * kept in this resource set and made available for other resources to find as they might have associated
	 * factories to create objects.
	 */
	private final Set<URI> namespaceURIs;

	/** Keeps track of the packages manually loaded for some of this resource set's resources. */
	private final Set<Resource> loadedPackages;

	/** Never try and load the same package twice. We'll use this lock to prevent that from happening. */
	private final ReentrantLock packageLoadingLock;

	/**
	 * Constructor.
	 * 
	 * @param proxyListener
	 *            The listener to notify of proxy creations.
	 */
	public SynchronizedResourceSet(IProxyCreationListener proxyListener) {
		this.uriCache = new ConcurrentHashMap<URI, Resource>();
		this.resources = new SynchronizedResourcesEList<Resource>();
		this.namespaceURIs = Sets.newSetFromMap(new ConcurrentHashMap<URI, Boolean>());
		this.loadedPackages = Sets.newSetFromMap(new ConcurrentHashMap<Resource, Boolean>());
		this.packageLoadingLock = new ReentrantLock(true);
		this.loadOptions = super.getLoadOptions();
		/*
		 * This resource set is specifically designed to resolve cross resources links, it thus spends a lot
		 * of time loading resources. The following set of options is what seems to give the most significant
		 * boost in loading performances, though I did not fine-tune what's really needed here.
		 */
		final NoNotificationParserPool parserPool = new NoNotificationParserPool(true);
		parserPool.addProxyListener(proxyListener);
		parserPool.addNamespaceDeclarationListener(new INamespaceDeclarationListener() {
			public void schemaLocationDeclared(String key, URI uri) {
				namespaceURIs.add(uri.trimFragment());
			}
		});
		loadOptions.put(XMLResource.OPTION_USE_PARSER_POOL, parserPool);
		loadOptions.put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.FALSE);
		loadOptions.put(XTEXT_SCOPING_LIVE_SCOPE_OPTION, Boolean.TRUE);

		/*
		 * We don't use XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP whereas it could bring performance
		 * improvements because we are loading the resources concurrently and this map could be used (put and
		 * get) by several threads. Passing a ConcurrentMap here is not an option either as EMF sometimes
		 * needs to put "null" values in there. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403425 for
		 * more details.
		 */
		/*
		 * Most of the existing options we are not using from here, since none of them seems to have a single
		 * effect on loading performance, whether we're looking at time or memory. See also
		 * https://www.eclipse.org/forums/index.php/t/929918/
		 */
	}

	/**
	 * This will load the given URI as an EMF Resource.
	 * <p>
	 * This is the only entry point within this resource set to load an EMF resource, and it will _only_ load
	 * the resource pointed at by <code>uri</code>, ignoring all cross-referenced resources (including
	 * containment proxies).
	 * </p>
	 * 
	 * @param uri
	 *            The URI to load as a resource.
	 * @return The loaded Resource.
	 */
	public Resource loadResource(URI uri) {
		/*
		 * Don't use super.getResource : we know the resource does not exist yet as there will only be one
		 * "load" call for each given URI. The super implementation iterates over loaded resources before
		 * doing any actual work. That causes some minimal overhead but, more importantly, it can generate
		 * concurrent modification exceptions.
		 */
		final URIConverter theURIConverter = getURIConverter();
		final URI normalizedURI = theURIConverter.normalize(uri);

		Resource result = null;
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".loadResource for " + normalizedURI); //$NON-NLS-1$ //$NON-NLS-2$
		}
		result = uriCache.get(normalizedURI);
		if (result == null) {
			result = delegatedGetResource(uri, true);
			if (result != null) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".loadResource - caching " //$NON-NLS-1$ //$NON-NLS-2$
							+ normalizedURI);
				}
				Resource former = uriCache.putIfAbsent(normalizedURI, result);
				if (former != null) {
					result = former;
				}
			} else if (namespaceURIs.contains(uri)) {
				// This uri points to an EPackage (or profile) that needs to be loaded completely and
				// normally for its factory to be useable.
				result = demandPackageLoad(uri);
			}
		}

		if (result == null) {
			result = demandCreateResource(uri);
			if (getURIConverter() instanceof RevisionedURIConverter) {
				try {
					if (!((RevisionedURIConverter)getURIConverter()).prefetchStream(uri, getLoadOptions())) {
						// Don't try and load. This resource doesn't exist on that side
						return result;
					}
				} catch (IOException e) {
					// Let EMF handle this one.
				}
			}
			if (result == null) {
				// copy/pasted from super.getResource
				throw new RuntimeException("Cannot create a resource for '" + uri //$NON-NLS-1$
						+ "'; a registered resource factory is needed"); //$NON-NLS-1$
			}
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".loadResource - No caching for " //$NON-NLS-1$ //$NON-NLS-2$
						+ normalizedURI);
			}
			demandLoadHelper(result);
		}
		return result;
	}

	/**
	 * Loads the given URI as an EMF EPackage. We will disable our custom parser pool for this one as it need
	 * to be loaded properly for its factory to be functional.
	 * 
	 * @param uri
	 *            The uri to load.
	 * @param normalized
	 *            the normalized form of this URI.
	 * @return The loaded resource.
	 */
	private Resource loadPackage(URI uri, URI normalized) {
		final URI trimmed = uri.trimFragment();
		final Resource resource = createResource(trimmed, ContentHandler.UNSPECIFIED_CONTENT_TYPE);
		if (resource == null) {
			return null;
		}

		// cache this asap. there might be recursive calls to "getResource" with this package URI (as can be
		// observed with the UML Ecore profile for example) during the loading itself; in which case we need
		// to return that same "currently loading" instance.
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".getResource - caching package " + uri); //$NON-NLS-1$ //$NON-NLS-2$
		}
		Resource former = uriCache.putIfAbsent(normalized, resource);
		if (former != null) {
			// There was already a resource cached (multi-threading makes it possible)
			return former;
		}

		try (InputStream stream = getURIConverter().createInputStream(trimmed, null)) {
			resource.load(stream, Collections.emptyMap());
		} catch (IOException e) {
			handleDemandLoadException(resource, e);
		}
		loadedPackages.add(resource);
		return resource;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#handleDemandLoadException(org.eclipse.emf.ecore.resource.Resource,
	 *      java.io.IOException)
	 */
	@Override
	protected void handleDemandLoadException(Resource resource, IOException exception) {
		try {
			super.handleDemandLoadException(resource, exception);
		} catch (RuntimeException e) {
			// do nothing, continue with loading, the exception has been added to the diagnostics of the
			// resource
		}
	}

	/**
	 * Unload the given resource.
	 * 
	 * @param resource
	 *            Resource to unlod
	 * @param monitor
	 *            Progress monito to use (currently unused)
	 */
	public void unload(Resource resource, IProgressMonitor monitor) {
		final URI uri = resource.getURI();
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".unload " + uri); //$NON-NLS-1$ //$NON-NLS-2$
		}
		uriCache.remove(uri);
		getResources().remove(resource);
		resource.eAdapters().clear();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResource(org.eclipse.emf.common.util.URI,
	 *      boolean)
	 */
	@Override
	public Resource getResource(URI uri, boolean loadOnDemand) {
		// Never load resources from here, we only care for the EPackages to prevent the XMLHandler from going
		// into a stackoverflow
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".getResource for " + uri); //$NON-NLS-1$ //$NON-NLS-2$
		}
		final URI normalized = getURIConverter().normalize(uri);
		Resource demanded = uriCache.get(normalized);
		if (namespaceURIs.contains(uri) && demanded != null) {
			ensurePackageLoaded(demanded);
		}

		if (demanded == null) {
			final EPackage ePackage = getPackageRegistry().getEPackage(uri.toString());
			if (ePackage != null) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) //$NON-NLS-1$
							+ ".getResource - found in package registry : " + uri); //$NON-NLS-1$
				}
				demanded = ePackage.eResource();
				if (demanded != null) {
					if (LOGGER.isDebugEnabled()) {
						LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".getResource - caching " //$NON-NLS-1$ //$NON-NLS-2$
								+ uri);
					}
					Resource former = uriCache.putIfAbsent(normalized, demanded);
					if (former != null) {
						demanded = former;
					}
				}
			} else if (namespaceURIs.contains(uri)) {
				// This uri points to an EPackage (or profile) that needs to be loaded completely and
				// normally.
				demanded = demandPackageLoad(uri);
			}
		} else if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".getResource - FOUND in cache " + uri); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return demanded;
	}

	/**
	 * This will be used to load the uris matching those from {@link #namespaceURIs} normally.
	 * 
	 * @param uri
	 *            The uri of the package to load.
	 * @return The loaded package's resource.
	 */
	private Resource demandPackageLoad(URI uri) {
		final URI normalized = getURIConverter().normalize(uri);

		packageLoadingLock.lock();
		try {
			Resource demanded = uriCache.get(normalized);
			if (demanded == null) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) //$NON-NLS-1$
							+ ".getResource - loaded package normally : " + uri); //$NON-NLS-1$
				}
				demanded = loadPackage(uri, normalized);
			}
			return demanded;
		} finally {
			packageLoadingLock.unlock();
		}
	}

	/**
	 * {@link #loadPackage(URI, URI)} will push the packages' resource in {@link #uriCache cache} before the
	 * package is actually loaded in order to avoid multi-threading issues. However, multi-threading can also
	 * make it so that another thread asks for a resource in cache and return it before the actual loading
	 * ends. This will lock that latter thread until the package is finished loading.
	 */
	private void ensurePackageLoaded(Resource packageResource) {
		if (!packageResource.isLoaded() || ((Resource.Internal)packageResource).isLoading()) {
			packageLoadingLock.lock();
			try {
				ensurePackageLoaded(packageResource);
			} finally {
				packageLoadingLock.unlock();
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI)
	 */
	@Override
	public synchronized Resource createResource(URI uri) {
		return super.createResource(uri);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#createResource(org.eclipse.emf.common.util.URI,
	 *      java.lang.String)
	 */
	@Override
	public synchronized Resource createResource(URI uri, String contentType) {
		return super.createResource(uri, contentType);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getResources()
	 */
	@Override
	public EList<Resource> getResources() {
		return resources;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl#getLoadOptions()
	 */
	@Override
	public Map<Object, Object> getLoadOptions() {
		return loadOptions;
	}

	/**
	 * {@inheritDoc}
	 */
	public void dispose() {
		// unload these completely instead of using #unload(Resource)
		for (Resource resource : loadedPackages) {
			final URI uri = resource.getURI();
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("SRS@" + Integer.toHexString(hashCode()) + ".unload " + uri); //$NON-NLS-1$ //$NON-NLS-2$
			}
			uriCache.remove(uri);
			resource.unload();
			getResources().remove(resource);
		}
	}

	/**
	 * A synchronized implementation of {@link ResourcesEList}.
	 * <p>
	 * Note that this cannot be extracted out of the {@link SynchronizedResourceSet} since the
	 * {@link ResourcesEList} type is not visible.
	 * </p>
	 * 
	 * @param <E>
	 *            Type of this list's contents.
	 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
	 */
	private class SynchronizedResourcesEList<E extends Resource> extends ResourcesEList<E> {
		/** Generated SUID. */
		private static final long serialVersionUID = 7371376112881960414L;

		/** The lock we'll use for synchronization of the resources list. */
		private final Object lock = new Object();

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.util.AbstractCollection#containsAll(java.util.Collection)
		 */
		@Override
		public boolean containsAll(Collection<?> c) {
			synchronized(lock) {
				return super.containsAll(c);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#set(int, java.lang.Object)
		 */
		@Override
		public E set(int index, E object) {
			synchronized(lock) {
				return super.set(index, object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#dispatchNotification(org.eclipse.emf.common.notify.Notification)
		 */
		@Override
		protected void dispatchNotification(Notification notification) {
			// do nothing
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#add(java.lang.Object)
		 */
		@Override
		public boolean add(E object) {
			synchronized(lock) {
				return super.add(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#add(int, java.lang.Object)
		 */
		@Override
		public void add(int index, E object) {
			synchronized(lock) {
				super.add(index, object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(java.util.Collection)
		 */
		@Override
		public boolean addAll(Collection<? extends E> collection) {
			synchronized(lock) {
				return super.addAll(collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#addAll(int, java.util.Collection)
		 */
		@Override
		public boolean addAll(int index, Collection<? extends E> collection) {
			synchronized(lock) {
				return super.addAll(index, collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#remove(java.lang.Object)
		 */
		@Override
		public boolean remove(Object object) {
			synchronized(lock) {
				return super.remove(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#retainAll(java.util.Collection)
		 */
		@Override
		public boolean retainAll(Collection<?> collection) {
			synchronized(lock) {
				return super.retainAll(collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#move(int, java.lang.Object)
		 */
		@Override
		public void move(int index, E object) {
			synchronized(lock) {
				super.move(index, object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object object) {
			synchronized(lock) {
				return super.equals(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#hashCode()
		 */
		@Override
		public int hashCode() {
			synchronized(lock) {
				return super.hashCode();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#toString()
		 */
		@Override
		public String toString() {
			synchronized(lock) {
				return super.toString();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#iterator()
		 */
		@Override
		public Iterator<E> iterator() {
			return new SynchronizedEIterator();
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator()
		 */
		@Override
		public ListIterator<E> listIterator() {
			return new SynchronizedEListIterator();
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.AbstractEList#listIterator(int)
		 */
		@Override
		public ListIterator<E> listIterator(int index) {
			synchronized(lock) {
				int curSize = size();
				if (index < 0 || index > curSize) {
					throw new BasicIndexOutOfBoundsException(index, curSize);
				}
				return new SynchronizedEListIterator(index);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#indexOf(java.lang.Object)
		 */
		@Override
		public int indexOf(Object object) {
			synchronized(lock) {
				return super.indexOf(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#lastIndexOf(java.lang.Object)
		 */
		@Override
		public int lastIndexOf(Object object) {
			synchronized(lock) {
				return super.lastIndexOf(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#toArray()
		 */
		@Override
		public Object[] toArray() {
			synchronized(lock) {
				return super.toArray();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#toArray(T[])
		 */
		@Override
		public <T> T[] toArray(T[] array) {
			synchronized(lock) {
				return super.toArray(array);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#setData(int, java.lang.Object[])
		 */
		@Override
		public void setData(int size, Object[] data) {
			synchronized(lock) {
				super.setData(size, data);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#get(int)
		 */
		@Override
		public E get(int index) {
			synchronized(lock) {
				return super.get(index);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#basicGet(int)
		 */
		@Override
		public E basicGet(int index) {
			synchronized(lock) {
				return super.basicGet(index);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#shrink()
		 */
		@Override
		public void shrink() {
			synchronized(lock) {
				super.shrink();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#grow(int)
		 */
		@Override
		public void grow(int minimumCapacity) {
			synchronized(lock) {
				super.grow(minimumCapacity);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#clone()
		 */
		// CHECKSTYLE:OFF we're overriding...
		@Override
		public Object clone() {
			// CHECKSTYLE:ON
			synchronized(lock) {
				return super.clone();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(java.lang.Object)
		 */
		@Override
		public void addUnique(E object) {
			synchronized(lock) {
				super.addUnique(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addUnique(int, java.lang.Object)
		 */
		@Override
		public void addUnique(int index, E object) {
			synchronized(lock) {
				super.addUnique(index, object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.util.Collection)
		 */
		@Override
		public boolean addAllUnique(Collection<? extends E> collection) {
			synchronized(lock) {
				return super.addAllUnique(collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.util.Collection)
		 */
		@Override
		public boolean addAllUnique(int index, Collection<? extends E> collection) {
			synchronized(lock) {
				return super.addAllUnique(index, collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(java.lang.Object[], int,
		 *      int)
		 */
		@Override
		public boolean addAllUnique(Object[] objects, int start, int end) {
			synchronized(lock) {
				return super.addAllUnique(objects, start, end);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#addAllUnique(int, java.lang.Object[],
		 *      int, int)
		 */
		@Override
		public boolean addAllUnique(int index, Object[] objects, int start, int end) {
			synchronized(lock) {
				return super.addAllUnique(index, objects, start, end);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicAdd(java.lang.Object,
		 *      org.eclipse.emf.common.notify.NotificationChain)
		 */
		@Override
		public NotificationChain basicAdd(E object, NotificationChain notifications) {
			synchronized(lock) {
				return super.basicAdd(object, notifications);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#remove(int)
		 */
		@Override
		public E remove(int index) {
			synchronized(lock) {
				return super.remove(index);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#removeAll(java.util.Collection)
		 */
		@Override
		public boolean removeAll(Collection<?> collection) {
			synchronized(lock) {
				return super.removeAll(collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicRemove(java.lang.Object,
		 *      org.eclipse.emf.common.notify.NotificationChain)
		 */
		@Override
		public NotificationChain basicRemove(Object object, NotificationChain notifications) {
			synchronized(lock) {
				return super.basicRemove(object, notifications);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#clear()
		 */
		@Override
		public void clear() {
			synchronized(lock) {
				super.clear();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#setUnique(int, java.lang.Object)
		 */
		@Override
		public E setUnique(int index, E object) {
			synchronized(lock) {
				return super.setUnique(index, object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#basicSet(int, java.lang.Object,
		 *      org.eclipse.emf.common.notify.NotificationChain)
		 */
		@Override
		public NotificationChain basicSet(int index, E object, NotificationChain notifications) {
			synchronized(lock) {
				return super.basicSet(index, object, notifications);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#move(int, int)
		 */
		@Override
		public E move(int targetIndex, int sourceIndex) {
			synchronized(lock) {
				return super.move(targetIndex, sourceIndex);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicList()
		 */
		@Override
		public List<E> basicList() {
			synchronized(lock) {
				return super.basicList();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIterator()
		 */
		@Override
		public Iterator<E> basicIterator() {
			return new SynchronizedNonResolvingEIterator();
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator()
		 */
		@Override
		public ListIterator<E> basicListIterator() {
			return new SynchronizedNonResolvingEListIterator();
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicListIterator(int)
		 */
		@Override
		public ListIterator<E> basicListIterator(int index) {
			synchronized(lock) {
				int curSize = size();
				if (index < 0 || index > curSize) {
					throw new BasicIndexOutOfBoundsException(index, curSize);
				}
				return new SynchronizedNonResolvingEListIterator(index);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#contains(java.lang.Object)
		 */
		@Override
		public boolean contains(Object object) {
			synchronized(lock) {
				return super.contains(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContains(java.lang.Object)
		 */
		@Override
		public boolean basicContains(Object object) {
			synchronized(lock) {
				return super.basicContains(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicContainsAll(java.util.Collection)
		 */
		@Override
		public boolean basicContainsAll(Collection<?> collection) {
			synchronized(lock) {
				return super.basicContainsAll(collection);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicIndexOf(java.lang.Object)
		 */

		@Override
		public int basicIndexOf(Object object) {
			synchronized(lock) {
				return super.basicIndexOf(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicLastIndexOf(java.lang.Object)
		 */
		@Override
		public int basicLastIndexOf(Object object) {
			synchronized(lock) {
				return super.basicLastIndexOf(object);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray()
		 */
		@Override
		public Object[] basicToArray() {
			synchronized(lock) {
				return super.basicToArray();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.util.NotifyingInternalEListImpl#basicToArray(T[])
		 */
		@Override
		public <T> T[] basicToArray(T[] array) {
			synchronized(lock) {
				return super.basicToArray(array);
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#data()
		 */
		@Override
		public Object[] data() {
			synchronized(lock) {
				return super.data();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.notify.impl.NotifyingListImpl#getFeature()
		 */
		@Override
		public Object getFeature() {
			synchronized(lock) {
				return super.getFeature();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getFeatureID()
		 */
		@Override
		public int getFeatureID() {
			synchronized(lock) {
				return super.getFeatureID();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.ResourcesEList#getNotifier()
		 */
		@Override
		public Object getNotifier() {
			synchronized(lock) {
				return super.getNotifier();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#isEmpty()
		 */
		@Override
		public boolean isEmpty() {
			synchronized(lock) {
				return super.isEmpty();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.common.util.BasicEList#size()
		 */
		@Override
		public int size() {
			synchronized(lock) {
				return super.size();
			}
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see java.util.AbstractList#subList(int, int)
		 */
		@Override
		public List<E> subList(int fromIndex, int toIndex) {
			synchronized(lock) {
				return super.subList(fromIndex, toIndex);
			}
		}

		/**
		 * A synchronized implementation of the {@link AbstractEList.EIterator}.
		 * 
		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
		 */
		private class SynchronizedEIterator extends AbstractEList<E>.EIterator<E> {
			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
			 */
			@Override
			public boolean hasNext() {
				synchronized(lock) {
					return super.hasNext();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
			 */
			@Override
			public E next() {
				synchronized(lock) {
					return super.next();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()
			 */
			@Override
			public void remove() {
				synchronized(lock) {
					super.remove();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#equals(java.lang.Object)
			 */
			@Override
			public boolean equals(Object obj) {
				synchronized(lock) {
					return super.equals(obj);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#hashCode()
			 */
			@Override
			public int hashCode() {
				synchronized(lock) {
					return super.hashCode();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#toString()
			 */
			@Override
			public String toString() {
				synchronized(lock) {
					return super.toString();
				}
			}
		}

		/**
		 * A synchronized implementation of the {@link AbstractEList.EListIterator}.
		 * 
		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
		 */
		private class SynchronizedEListIterator extends AbstractEList<E>.EListIterator<E> {
			/**
			 * Delegates to the super constructor.
			 */
			public SynchronizedEListIterator() {
				super();
			}

			/**
			 * Delegates to the super constructor.
			 * 
			 * @param index
			 *            Index at which this list iterator should start.
			 */
			public SynchronizedEListIterator(int index) {
				super(index);
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#add(java.lang.Object)
			 */
			@Override
			public void add(E object) {
				synchronized(lock) {
					super.add(object);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
			 */
			@Override
			public boolean hasNext() {
				synchronized(lock) {
					return super.hasNext();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()
			 */
			@Override
			public boolean hasPrevious() {
				synchronized(lock) {
					return super.hasPrevious();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
			 */
			@Override
			public E next() {
				synchronized(lock) {
					return super.next();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()
			 */
			@Override
			public E previous() {
				synchronized(lock) {
					return super.previous();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()
			 */
			@Override
			public int previousIndex() {
				synchronized(lock) {
					return super.previousIndex();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#remove()
			 */
			@Override
			public void remove() {
				synchronized(lock) {
					super.remove();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#set(java.lang.Object)
			 */
			@Override
			public void set(E object) {
				synchronized(lock) {
					super.set(object);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#equals(java.lang.Object)
			 */
			@Override
			public boolean equals(Object obj) {
				synchronized(lock) {
					return super.equals(obj);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#hashCode()
			 */
			@Override
			public int hashCode() {
				synchronized(lock) {
					return super.hashCode();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#toString()
			 */
			@Override
			public String toString() {
				synchronized(lock) {
					return super.toString();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()
			 */
			@Override
			public int nextIndex() {
				synchronized(lock) {
					return super.nextIndex();
				}
			}
		}

		/**
		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEIterator}.
		 * 
		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
		 */
		private class SynchronizedNonResolvingEIterator extends AbstractEList<E>.NonResolvingEIterator<E> {
			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
			 */
			@Override
			public boolean hasNext() {
				synchronized(lock) {
					return super.hasNext();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
			 */
			@Override
			public E next() {
				synchronized(lock) {
					return super.next();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEIterator#remove()
			 */
			@Override
			public void remove() {
				synchronized(lock) {
					super.remove();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#equals(java.lang.Object)
			 */
			@Override
			public boolean equals(Object obj) {
				synchronized(lock) {
					return super.equals(obj);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#hashCode()
			 */
			@Override
			public int hashCode() {
				synchronized(lock) {
					return super.hashCode();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#toString()
			 */
			@Override
			public String toString() {
				synchronized(lock) {
					return super.toString();
				}
			}
		}

		/**
		 * A synchronized implementation of the {@link AbstractEList.NonResolvingEListIterator}.
		 * 
		 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
		 */
		private class SynchronizedNonResolvingEListIterator extends AbstractEList<E>.NonResolvingEListIterator<E> {
			/**
			 * Delegates to the super constructor.
			 */
			public SynchronizedNonResolvingEListIterator() {
				super();
			}

			/**
			 * Delegates to the super constructor.
			 * 
			 * @param index
			 *            Index at which the iteration should start.
			 */
			public SynchronizedNonResolvingEListIterator(int index) {
				super(index);
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#add(java.lang.Object)
			 */
			@Override
			public void add(E object) {
				synchronized(lock) {
					super.add(object);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#hasNext()
			 */
			@Override
			public boolean hasNext() {
				synchronized(lock) {
					return super.hasNext();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#hasPrevious()
			 */
			@Override
			public boolean hasPrevious() {
				synchronized(lock) {
					return super.hasPrevious();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EIterator#next()
			 */
			@Override
			public E next() {
				synchronized(lock) {
					return super.next();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previous()
			 */
			@Override
			public E previous() {
				synchronized(lock) {
					return super.previous();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#previousIndex()
			 */
			@Override
			public int previousIndex() {
				synchronized(lock) {
					return super.previousIndex();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#remove()
			 */
			@Override
			public void remove() {
				synchronized(lock) {
					super.remove();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.NonResolvingEListIterator#set(java.lang.Object)
			 */
			@Override
			public void set(E object) {
				synchronized(lock) {
					super.set(object);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#equals(java.lang.Object)
			 */
			@Override
			public boolean equals(Object obj) {
				synchronized(lock) {
					return super.equals(obj);
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#hashCode()
			 */
			@Override
			public int hashCode() {
				synchronized(lock) {
					return super.hashCode();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see java.lang.Object#toString()
			 */
			@Override
			public String toString() {
				synchronized(lock) {
					return super.toString();
				}
			}

			/**
			 * {@inheritDoc}
			 * 
			 * @see org.eclipse.emf.common.util.AbstractEList.EListIterator#nextIndex()
			 */
			@Override
			public int nextIndex() {
				synchronized(lock) {
					return super.nextIndex();
				}
			}
		}
	}
}
