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

import java.util.ArrayList;
import java.util.Collection;
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.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
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.epf.common.utils.ExtensionHelper;
import org.eclipse.epf.common.utils.IMarkerAttributeContributer;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.persistence.FileManager;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.persistence.PersistencePlugin;
import org.eclipse.epf.uma.ecore.IProxyResolutionListener;
import org.eclipse.epf.uma.ecore.ResolveException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.osgi.util.NLS;


/**
 * Background job that manage markers for unresolved proxies
 * 
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class UnresolvedProxyMarkerManager extends WorkspaceJob implements IProxyResolutionListener {

	private static final long DELAY = 0;
	
	public static final String MARKER_ID = PersistencePlugin.getDefault().getId() + ".unresolvedProxyMarker"; //$NON-NLS-1$
	public static final String PROXY_URI = "proxyURI"; //$NON-NLS-1$
	public static final String OWNER_GUID = "ownerGUID"; //$NON-NLS-1$
	
	private static class ValidObject {
		boolean valid;
		Object object;
		
		/**
		 * @param valid
		 * @param object
		 */
		public ValidObject(Object object) {
			super();
			this.object = object;
			valid = true;			
		}
				
	}
	
	private Map<URI, Set<ResolveException>> uriToExceptionsMap;
	private List<ResolveException> exceptions;
	private Map<String, ValidObject> resourceGUIDToMarkersMap;
	private Map<String, Collection<ValidObject>> elementGUIToMarkersMap;
	private ResourceSet resourceSet;
	private boolean enabled = true;
	private List<Resource> resourcesToValidateMarkers;
	private boolean autoScheduled = true;

	public UnresolvedProxyMarkerManager(ResourceSet resourceSet) {
		super(PersistenceResources.unresolvedProxyLoggerJob_name);		
		this.resourceSet = resourceSet;
//		unresolvedResourceGUIDToMarkersMap = new HashMap();
		uriToExceptionsMap = new HashMap<URI, Set<ResolveException>>();
		exceptions = new ArrayList<ResolveException>(); 
		resourceGUIDToMarkersMap = new HashMap<String, ValidObject>();
		elementGUIToMarkersMap = new HashMap<String, Collection<ValidObject>>();
		resourcesToValidateMarkers = new UniqueEList<Resource>();
	}

	public IMarker findMarker(IFile file, String proxyURI, int start, int end) throws CoreException {
		IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO);
		return findMarker(markers, proxyURI, start, end);
	}
	
	private IMarker findMarker(IMarker[] markers, String proxyURI, int start, int end) throws CoreException {
		for (int i = 0; i < markers.length; i++) {
			IMarker marker = markers[i];
			if(proxyURI.equals(marker.getAttribute(PROXY_URI))
					&& marker.getAttribute(IMarker.CHAR_START, -1) == start
					&& marker.getAttribute(IMarker.CHAR_END, -1) == end) 
			{
				return marker;
			}
		}
		return null;
	}
	
	private IMarker findMarker(Collection<IMarker> markers, int start, int end) throws CoreException {
		for (IMarker marker : markers) {
			if(marker.getAttribute(IMarker.CHAR_START, -1) == start
					&& marker.getAttribute(IMarker.CHAR_END, -1) == end) 
			{
				return marker;
			}
		}
		return null;
	}


	private boolean addException(ResolveException re) {
		synchronized(exceptions) {
			URI uri = ((InternalEObject)re.getProxy()).eProxyURI();
			Set<ResolveException> exceptions = uriToExceptionsMap.get(uri);		
			if(exceptions == null) {
				exceptions = new HashSet<ResolveException>();
				uriToExceptionsMap.put(uri, exceptions);
			}
			if(exceptions.add(re)) {
				this.exceptions.add(re);
				return true;
			}
			return false;
		}
	}
	
	/**
	 * Document based character sequence.
	 */
	private static class DocumentCharSequence implements CharSequence {

		/** Document */
		private IDocument fDocument;

		/**
		 * Initialize with the sequence of characters in the given
		 * document.
		 *
		 * @param document the document
		 */
		public DocumentCharSequence(IDocument document) {
			fDocument= document;
		}

		/*
		 * @see java.lang.CharSequence#length()
		 */
		public int length() {
			return fDocument.getLength();
		}

		/*
		 * @see java.lang.CharSequence#charAt(int)
		 */
		public char charAt(int index) {
			try {
				return fDocument.getChar(index);
			} catch (BadLocationException x) {
				throw new IndexOutOfBoundsException(x.getLocalizedMessage());
			}
		}

		/*
		 * @see java.lang.CharSequence#subSequence(int, int)
		 */
		public CharSequence subSequence(int start, int end) {
			try {
				return fDocument.get(start, end - start);
			} catch (BadLocationException x) {
				throw new IndexOutOfBoundsException(x.getLocalizedMessage());
			}
		}
	}
	
	private static class MarkersAndLocations {
		Collection<IMarker> markers;
		Collection<int[]> locations;				
	}
	
	private void updateMarker(IMarker[] markers, Resource resource, IProgressMonitor monitor) {
		URI containerURI = resource.getURI();
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IPath path = new Path(containerURI.toFileString());
		IFile file = workspace.getRoot().getFileForLocation(path);
		if (file != null) {
			try {
				file.refreshLocal(IResource.DEPTH_ZERO, null);
				
				Map<String, MarkersAndLocations> proxyURIToMarkersAndLocationsMap = new HashMap<String, MarkersAndLocations>();
				for (int i = 0; i < markers.length; i++) {
					IMarker marker = markers[i];
					Object proxyURI = marker.getAttribute(PROXY_URI);
					if(proxyURI != null) {
						String proxyURIStr = proxyURI.toString();
						MarkersAndLocations markersAndLocations = proxyURIToMarkersAndLocationsMap.get(proxyURIStr);
						if(markersAndLocations == null) {
							markersAndLocations = new MarkersAndLocations();
							markersAndLocations.markers = new HashSet<IMarker>();
							markersAndLocations.locations = new HashSet<int[]>();
							proxyURIToMarkersAndLocationsMap.put(proxyURIStr, markersAndLocations);
						}
						markersAndLocations.markers.add(marker);
					}
				}
				
				// locate the text of unresolved URI in file
				//
				ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
				try {
					manager.connect(path, LocationKind.LOCATION, monitor);
					ITextFileBuffer fileBuffer= manager.getTextFileBuffer(path, LocationKind.LOCATION);
					fileBuffer.requestSynchronizationContext();
					fileBuffer.getDocument();
					IDocument doc = fileBuffer.getDocument();
					if(doc != null) {
						for (Map.Entry<String, MarkersAndLocations> entry : proxyURIToMarkersAndLocationsMap.entrySet()) {
							String proxyURI = entry.getKey();
							Pattern pattern = PatternConstructor.createPattern(proxyURI, true, false);
							Matcher matcher = pattern.matcher(new DocumentCharSequence(doc));
							while(matcher.find()) {
								int start = matcher.start();
								int end = matcher.end();
								if(start != end) {
									entry.getValue().locations.add(new int[] { start, end });
								}
							}
						}
					}
					fileBuffer.releaseSynchronizationContext();
				}
				finally {
					manager.disconnect(path, LocationKind.LOCATION, monitor);
				}
				
				// make sure that resolver is still in the open library by checking whether its resource
				// still belongs to a resource set
				//
				if(resource != null && resource.getResourceSet() != null) {
					for (MarkersAndLocations markersAndLocations : proxyURIToMarkersAndLocationsMap.values()) {
						process_entry:
						for (Iterator<int[]> iterator = markersAndLocations.locations.iterator(); iterator.hasNext();) {
							if(markersAndLocations.markers.isEmpty()) {
								break process_entry;
							}
							int[] loc = iterator.next();
							int start = loc[0];
							int end = loc[1];
							IMarker marker = findMarker(markersAndLocations.markers, start, end);
							if(marker == null) {
								Iterator<IMarker> iter = markersAndLocations.markers.iterator();
								marker = iter.next();
								iter.remove();
								marker.setAttribute(IMarker.CHAR_START, start);	
								marker.setAttribute(IMarker.CHAR_END, end);
							}
							else {
								markersAndLocations.markers.remove(marker);
							}
						}
						if(!markersAndLocations.markers.isEmpty()) {
							// invalid markers, must be deleted
							//
							for (IMarker marker : markersAndLocations.markers) {
								if(marker.exists()) {
									try {
										marker.delete();
									}
									catch(CoreException e) {
										PersistencePlugin.getDefault().getLogger().logError(e);
									}
								}
							}
						}
					}
				}

			} catch (CoreException ex) {
				PersistencePlugin.getDefault().getLogger().logError(ex);
				if (MultiFileSaveUtil.DEBUG) {
					ex.printStackTrace();
				}
			}
		}
	}
	
	private void addMarker(ResolveException re, Resource resource, URI proxyURI, String errMsg, String ownerGUID, IProgressMonitor monitor) {
		URI containerURI = resource.getURI();
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IPath path = new Path(containerURI.toFileString());
		IFile file = workspace.getRoot().getFileForLocation(path);
		if (file != null) {
			String location = containerURI != null ? containerURI
					.toFileString() : StrUtil.EMPTY_STRING;					
			
			try {
				file.refreshLocal(IResource.DEPTH_ZERO, null);
				IMarker marker = findMarker(file, proxyURI.toString(), 0, 0);
				if (marker != null) {
					marker.setAttribute(OWNER_GUID, ownerGUID);
					return;
				}
				createMarker(re, proxyURI, errMsg, ownerGUID, file,
						location, proxyURI.toString(), 0, 0);
			} catch (CoreException e) {
				IStatus status = e.getStatus();
				int code;
				if(status instanceof IResourceStatus && 
						((code = ((IResourceStatus) status).getCode()) == IResourceStatus.MARKER_NOT_FOUND
								|| code == IResourceStatus.RESOURCE_NOT_FOUND)) {
					// do nothing
				} else {
					PersistencePlugin.getDefault().getLogger().logError(e);
					if (MultiFileSaveUtil.DEBUG) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	private IMarker createMarker(ResolveException re, URI proxyURI,
			String errMsg, String ownerGUID, IFile file, String location,
			String proxyURIStr, int start, int end) throws CoreException {
		IMarker marker;
		marker = file.createMarker(MARKER_ID);
		marker.setAttribute(IMarker.SEVERITY,
				IMarker.SEVERITY_ERROR);
		marker.setAttribute(IMarker.MESSAGE, errMsg);
		marker.setAttribute(IMarker.LOCATION, location);
		marker.setAttribute(IMarker.TRANSIENT, true);
		marker.setAttribute(IMarker.CHAR_START, start);	
		marker.setAttribute(IMarker.CHAR_END, end);
		marker.setAttribute(PROXY_URI, proxyURIStr);
		marker.setAttribute(OWNER_GUID, ownerGUID);
		
		IMarkerAttributeContributer attAdder = ExtensionHelper.getMarkerAttributeContributer();
		if (attAdder != null) {
			attAdder.addAddtionalAttributes(marker, re);
		}

		// cache marker to it can be found easily and deleted
		//
		cacheMarker(marker, proxyURI);
		return marker;
	}
	
	private void addMarker(ResolveException re, IProgressMonitor monitor) {
		InternalEObject proxy = (InternalEObject) re.getProxy();
		URI containerURI = null;
		Resource resource = null;
		if(re.getResolver() != null) {
			resource = re.getResolver().eResource();
			
			// make sure that resolver is still in the open library by checking whether its resource
			// still belongs to a resource set
			//
//			System.out.println("UnresolvedProxyMarkerManager.addMarker(): resourceSet=" + resource.getResourceSet().hashCode());
			if(resource != null && resource.getResourceSet() != null) {				
				containerURI = resource.getURI();
			}
		}				
		if (containerURI != null) {
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			IPath path = new Path(containerURI.toFileString());
			IFile file = workspace.getRoot().getFileForLocation(path);
			if (file != null) {
				String errMsg;
				if (re.exception() != null && re.exception().getLocalizedMessage() != null && 
						re.exception().getLocalizedMessage().trim().length() > 0) {
					errMsg = re.exception().getLocalizedMessage();
				}
				else {
					errMsg = re.getMessage() == null ? NLS.bind(PersistenceResources.UnresolvedProxyMarkerManager_couldNotResolveProxy, proxy.eProxyURI()) : re
								.getMessage();
				}
				addMarker(re, resource, proxy.eProxyURI(), errMsg, MultiFileSaveUtil.getGuid(re.getResolver()), monitor);
			}
		}
	}

	/**
	 * @param marker
	 * @param uri proxy uri 
	 */
	private void cacheMarker(IMarker marker, URI uri) {
		synchronized(elementGUIToMarkersMap) {
			String resourceGUID = uri.authority();
			if(resourceGUID != null) {
				ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID);
				if(vo == null) {
					vo = new ValidObject(new HashSet<IMarker>());
					resourceGUIDToMarkersMap.put(resourceGUID, vo);
				}
				Collection<IMarker> markers = (Collection<IMarker>) vo.object;
				markers.add(marker);
			}
			String elementGUID = uri.fragment();
			Collection<ValidObject> markers = elementGUIToMarkersMap.get(elementGUID);
			if(markers == null) {
				markers = new HashSet<ValidObject>();
				elementGUIToMarkersMap.put(elementGUID, markers);
			}
			markers.add(new ValidObject(marker));
		}
	}

	public void clearAll() {
		boolean oldEnabled = enabled;
		try {
			enabled = false;
			cancel();

			synchronized (exceptions) {
				uriToExceptionsMap.clear();
				exceptions.clear();
			}
			synchronized(elementGUIToMarkersMap) {
				if(!elementGUIToMarkersMap.isEmpty()) {
					for (Collection<ValidObject> markers : elementGUIToMarkersMap.values()) {
						for (ValidObject vo : markers) {
							IMarker marker = (IMarker) vo.object;
							try {
								if(marker.exists()) {
									marker.delete();
								}
							}
							catch(Exception e) {
								CommonPlugin.INSTANCE.log(e);
							}
						}
						markers.clear();
					}
					elementGUIToMarkersMap.clear();
					resourceGUIDToMarkersMap.clear();
				}	
			}
			synchronized(resourcesToValidateMarkers) {
				resourcesToValidateMarkers.clear();
			}
		}
		finally {
			enabled = oldEnabled;
//			System.out.println("UnresolvedProxyMarkerManager.clearAll(): end");
		}
	}

	public boolean hasUnresolvedProxy() {
		return !elementGUIToMarkersMap.isEmpty();
	}
	
	private ResolveException nextException() {
		synchronized(exceptions) {			
			// synchronized: in order to atomically obtain and clear requests
			if(exceptions.isEmpty()) {
				return null;
			}
			else {
				ResolveException e = (ResolveException) this.exceptions.remove(0);
				URI uri = ((InternalEObject)e.getProxy()).eProxyURI();
				Set<ResolveException> exceptions = uriToExceptionsMap.get(uri);
				if(exceptions != null) {
					exceptions.remove(e);
					if(exceptions.isEmpty()) {
						uriToExceptionsMap.remove(uri);
					}
				}
				return e;
			}
		}
	}
	
	private Resource nextResourceToValidateMarkers() {
		synchronized(resourcesToValidateMarkers) {
			if(resourcesToValidateMarkers.isEmpty()) {
				return null;
			}
			else {
				return (Resource) resourcesToValidateMarkers.remove(0);
			}
		}
	}
	
	private void yield() {
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			//
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor)
	 */
	public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
//		System.out.println("UnresolvedProxyMarkerManager.runInWorkspace(): begin");
		try {
		if(!enabled) return Status.OK_STATUS;

		try {
			// add markers
			//
			ResolveException re;
			while(!monitor.isCanceled() && (re = nextException()) != null) {
				try {
					addMarker(re, monitor);
				}
				catch(Exception e) {
					PersistencePlugin.getDefault().getLogger().logError(e);
				}	
				yield();
			}
			
			if(monitor.isCanceled()) {
				throw new OperationCanceledException();
			}
			
			// remove invalid markers
			//
			removeMarkers(monitor);
			yield();
			
			// validate resource markers
			//
			Resource resource;
			while(!monitor.isCanceled() && (resource = nextResourceToValidateMarkers()) != null) {
				doValidateMarkers(resource);
				yield();
			}
		}
		catch(Exception e) {
			if(e instanceof OperationCanceledException) {
				throw (OperationCanceledException) e;
			}
			PersistencePlugin.getDefault().getLogger().logError(e);
		}
		
		return Status.OK_STATUS;
		}
		finally {
//			System.out.println("UnresolvedProxyMarkerManager.runInWorkspace(): end");
		}
	}
	
	private boolean removeFromResourceGUIDToMarkersMap(String proxyURI, IMarker marker) {
		URI uri = URI.createURI(proxyURI);
		String resourceGUID = uri.authority();
		if(resourceGUID != null) {
			ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID);
			if(vo != null) {
				Collection markers = ((Collection)vo.object);
				boolean ret = markers.remove(marker);
				if(markers.isEmpty()) {
					resourceGUIDToMarkersMap.remove(resourceGUID);
				}
				return ret;
			}
		}
		return false;
	}
	
	private void removeFromElementGUIDToMarkersMap(String proxyURI, IMarker marker) {
		URI uri = URI.createURI(proxyURI);
		String elementGUID = uri.fragment();
		if(elementGUID != null) {
			Collection<ValidObject> validObjects = elementGUIToMarkersMap.get(elementGUID);
			if(validObjects != null) {
				for (Iterator<ValidObject> iterator1 = validObjects.iterator(); iterator1
				.hasNext();) {
					ValidObject vo1 = (ValidObject) iterator1.next();
					if(vo1.object == marker) {
						iterator1.remove();
					}
				}
				if(validObjects.isEmpty()) {
					elementGUIToMarkersMap.remove(elementGUID);
				}	
			}
		}
	}
	
	private void removeMarkers(IProgressMonitor monitor) {
		synchronized(elementGUIToMarkersMap) {
		for (Collection<ValidObject> markers : elementGUIToMarkersMap.values()) {
			for (Iterator<ValidObject> iterator = markers.iterator(); iterator.hasNext();) {
				ValidObject vo = (ValidObject) iterator.next();
				if(!vo.valid) {
					try {
						IMarker marker = (IMarker) vo.object;
						if(marker.exists()) {
							String proxyURI = (String) marker.getAttribute(PROXY_URI);

							marker.delete();

							// remove this marker from resourceGUIToMarkersMap
							//
							removeFromResourceGUIDToMarkersMap(proxyURI, marker);
						}
						iterator.remove();

					} catch (Exception e) {
						CommonPlugin.INSTANCE.log(e);
					}
				}
			}
		}
		for (Iterator<ValidObject> iter = resourceGUIDToMarkersMap.values().iterator(); iter.hasNext();) {
			ValidObject vo = (ValidObject) iter.next();
			if(!vo.valid) {
				vo.valid = true;
				Collection<IMarker> markers = (Collection<IMarker>) vo.object;
				for (Iterator<IMarker> iterator = markers.iterator(); iterator.hasNext();) {
					IMarker marker;
					try {
						marker = (IMarker) iterator.next();
						if(marker.exists()) {
							String proxyURIStr = (String) marker.getAttribute(PROXY_URI);
							URI proxyURI = URI.createURI(proxyURIStr);

							// proxy is in the same resource that is just loaded 
							// try to get the object with this proxy URI without loading new resource
							//
//							EObject o = resourceSet.getEObject(proxyURI, false);
							String elementGUID = proxyURI.fragment();							
							EObject o = (EObject) ((MultiFileResourceSetImpl)resourceSet).getGuidToMethodElementMap().get(elementGUID);
							if(o != null && !o.eIsProxy()) {
								marker.delete();
								iterator.remove();	

								// remove this marker from elementGUIToMarkersMap
								//
								removeFromElementGUIDToMarkersMap(proxyURIStr, marker);
							}
						}
						else {
							iterator.remove();
						}
					}
					catch(Exception e) {
						CommonPlugin.INSTANCE.log(e);
					}
				}
				if(markers.isEmpty()) {
					iter.remove();
				}
			}
		}
		}
	}
	
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}
	
	public boolean isEnabled() {
		return enabled;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.epf.uma.ecore.IProxyResolutionListener#notifyException(java.lang.Exception)
	 */
	public void notifyException(Exception e) {
		if(!enabled) return;
		
		if(e instanceof ResolveException) {
			ResolveException re = (ResolveException) e;
			
//			URI uri = ((InternalEObject)re.getProxy()).eProxyURI();
//			if("_2J4YoPTDEdmkpYARNN468A".equals(uri.fragment())) {
//				System.out.println();
//			}
			
			if(addException(re) && autoScheduled) {			
				schedule(DELAY);
			}
		}
	}
	
	public void setAutoScheduled(boolean b) {
		autoScheduled = b;
	}
	
	public boolean isAutoScheduled() {
		return autoScheduled;
	}
	
	/**
	 * Schedules this job if exceptions are available to log
	 */
	public boolean start() {
		if(!enabled) return false;
		
		synchronized (exceptions) {
			if(!exceptions.isEmpty()) {
				schedule(DELAY);
				return true;
			}
			return false;
		}
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.epf.uma.ecore.IProxyResolutionListener#proxyResolved(java.lang.Object, java.lang.Object)
	 */
	public void proxyResolved(Object proxy, Object resolved) {
		if(!enabled) return;
		
		if(proxy instanceof InternalEObject) {
			URI uri = ((InternalEObject)proxy).eProxyURI();
			
//			if("_2J4YoPTDEdmkpYARNN468A".equals(uri.fragment())) {
//				System.out.println();
//			}
			
			// remove all exceptions for this URI
			//
			removeExceptions(uri);
			
			// invalidate all markers for this URI
			//
			if(invalidateMarkers(uri)) {
				schedule(DELAY);
			}						
		}		
	}
	
	/**
	 * @param uri
	 */
	private boolean invalidateMarkers(URI uri) {
		synchronized(elementGUIToMarkersMap) {
			boolean ret = false;
			String resourceGUID = uri.authority();
			if(resourceGUID != null) {
				ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID);
				if(vo != null) {
					vo.valid = false;
					ret = true;
				}
			}
			String elementGUID = uri.fragment();
			if(elementGUID != null) {
				Collection<ValidObject> markers = elementGUIToMarkersMap.get(elementGUID);
				if(markers != null && !markers.isEmpty()) {
					ret = true;
					for (ValidObject vo : markers) {
						vo.valid = false;
					}
				}
			}
			return ret;
		}
	}

	/**
	 * @param uri
	 */
	private void removeExceptions(URI uri) {
		synchronized (exceptions) {
			Set<ResolveException> exceptions = uriToExceptionsMap.get(uri);
			if(exceptions == null || exceptions.isEmpty()) return;
			this.exceptions.removeAll(exceptions);
			uriToExceptionsMap.remove(uri);
		}
	}

	/**
	 * Clears markers for unresolved proxies of the given resource
	 *  
	 * @param resource
	 */
	public void clearMarkers(Resource resource) {
		try {
			IResource file = FileManager.getResourceForLocation(resource.getURI().toFileString());
			if(file instanceof IFile) {
				IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO);
				for (int i = 0; i < markers.length; i++) {
					IMarker marker = markers[i];
					removeMarker(marker);
				}
			}
		}
		catch(Exception e) {
			PersistencePlugin.getDefault().getLogger().logError(e);
		}
	}
	
	public void removeMarker(IMarker marker) {
		String proxyURI = null;
		try {
			if(marker.exists()) {
				proxyURI = (String) marker.getAttribute(PROXY_URI);
				marker.delete();
			}
		} catch (Exception e) {
			PersistencePlugin.getDefault().getLogger().logError(e);
		}
		if(proxyURI != null) {
			synchronized(elementGUIToMarkersMap) {
				removeFromElementGUIDToMarkersMap(proxyURI, marker);
				removeFromResourceGUIDToMarkersMap(proxyURI, marker);
			}
		}		
	}

	private static class MarkerInfo {
		String proxyURI;
		String ownerGUID;
		String message;
		
		/* (non-Javadoc)
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if(obj instanceof MarkerInfo) {
				MarkerInfo info = (MarkerInfo) obj;
				if(proxyURI != null && ownerGUID != null && proxyURI.equals(info.proxyURI) && ownerGUID.equals(info.ownerGUID)) {
					return true;
				}
			}
			return super.equals(obj);
		}
		
		@Override
		public int hashCode() {
			int result = proxyURI.hashCode();
			result ^= ownerGUID.hashCode();
			result ^= message.hashCode();
			return result;
		}
	}
	
	/**
	 * Validates markers for unresolved proxies of the given resource
	 * 
	 * @param resource
	 */
	public void validateMarkers(Resource resource) {
		boolean newlyAdded = false;
		synchronized(resourcesToValidateMarkers) {
			newlyAdded = resourcesToValidateMarkers.add(resource);
		}
		if(newlyAdded) {
			schedule(DELAY);
		}
	}

	public void validateAllMarkers() {
		boolean newlyAdded = false;
		boolean invalid = false;
		if(!elementGUIToMarkersMap.isEmpty()) {
			ArrayList<Collection<ValidObject>> validObjectCollections = null;
			synchronized (elementGUIToMarkersMap) {
				if(!elementGUIToMarkersMap.isEmpty()) {					
					validObjectCollections = new ArrayList<Collection<ValidObject>>();
					for (Collection<ValidObject> collection : elementGUIToMarkersMap.values()) {
						if(!collection.isEmpty()) {
							validObjectCollections.add(new ArrayList<ValidObject>(collection));
						}
					}
				}
			}
			if(validObjectCollections != null) {
				synchronized(resourcesToValidateMarkers) {
					for (Collection<ValidObject> markers : validObjectCollections) {
						for (ValidObject vo : markers) {
							IMarker marker = (IMarker) vo.object;
							try {
								if(marker.exists()) {
									String location = (String)marker.getAttribute(IMarker.LOCATION);
									URI uri = URI.createFileURI(location);
									Resource resource = resourceSet.getResource(uri, true);
									newlyAdded = resourcesToValidateMarkers.add(resource) | newlyAdded;
								} else {
									vo.valid = false;
									invalid = true;
								}
							} catch (CoreException e) {
								PersistencePlugin.getDefault().getLogger().logError(e);
							}
						}
					}
				}

			}
		}
		if(newlyAdded) {
			schedule(DELAY);
		} else if(invalid) {
			removeMarkers(new NullProgressMonitor());
		}
	}
	
	public void doValidateMarkers(Resource resource) {
		try {
			IResource file = FileManager.getResourceForLocation(resource.getURI().toFileString());
			if(file instanceof IFile && file.exists()) {
				IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO);
				HashSet<IMarker> markersToUpdate = new HashSet<IMarker>();
				for (int i = 0; i < markers.length; i++) {
					IMarker marker = markers[i];
					String proxyURI = (String) marker.getAttribute(PROXY_URI);
					if(proxyURI != null) {
						URI uri = URI.createURI(proxyURI);
						// try to get the object with this proxy URI without loading new resource
						//
						String elementGUID = uri.fragment();							
						EObject o = (EObject) ((MultiFileResourceSetImpl)resourceSet).getGuidToMethodElementMap().get(elementGUID);
						if(o == null || o.eIsProxy()) {
							// marker still can exist, need to update it
							//
							markersToUpdate.add(marker);
						}
						else {
							// object is resolved, must delete marker
							//
							if(marker.exists()) {
								try {
									marker.delete();
								}
								catch(Exception e) {
									PersistencePlugin.getDefault().getLogger().logError(e);									
								}
							}
							synchronized(elementGUIToMarkersMap) {
								removeFromElementGUIDToMarkersMap(proxyURI, marker);
								removeFromResourceGUIDToMarkersMap(proxyURI, marker);
							}
						}
					}
				}
				if(!markersToUpdate.isEmpty()) {
					IMarker[] markerArray = new IMarker[markersToUpdate.size()];
					markersToUpdate.toArray(markerArray);
					updateMarker(markerArray, resource, new NullProgressMonitor());
				}
			}
		}
		catch(Exception e) {
			PersistencePlugin.getDefault().getLogger().logError(e);		
		}
	}

}
