[516508] Cache unresolvable proxies in NotLoadingResourceSet
This change also aims at simplifying the quite confusing resolveProxies
method.
Bug: 516508
Change-Id: Ia7a488ad8e3c72ea60e57eda1471887f6de11d5c
Signed-off-by: Philip Langer <planger@eclipsesource.com>
diff --git a/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/NotLoadingResourceSet.java b/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/NotLoadingResourceSet.java
index 923a513..0e0920e 100644
--- a/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/NotLoadingResourceSet.java
+++ b/plugins/org.eclipse.emf.compare.ide/src/org/eclipse/emf/compare/ide/internal/utils/NotLoadingResourceSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2015 Obeo and others.
+ * Copyright (c) 2012, 2017 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
@@ -8,6 +8,7 @@
* Contributors:
* Obeo - initial API and implementation
* Stefan Dirix - bug 464904
+ * Philip Langer - bug 516508
*******************************************************************************/
package org.eclipse.emf.compare.ide.internal.utils;
@@ -283,9 +284,12 @@
public Resource getResource(URI uri, boolean loadOnDemand) {
checkNotDisposed();
- // Bypass the load on demand policies when possible
- final Resource cached = getURIResourceMap().get(uri);
- if (cached != null) {
+ // Bypass the load on demand policies when possible.
+ // Note that we cache null as well, so if a proxy fails to resolve we don't repeatedly try to load it.
+ // That lookup can be expensive for a resource set with hundreds of resources.
+ Map<URI, Resource> uriToResource = getURIResourceMap();
+ final Resource cached = uriToResource.get(uri);
+ if (cached != null || uriToResource.containsKey(uri)) {
return cached;
}
@@ -305,6 +309,11 @@
resource = super.getResource(uri, false);
}
}
+
+ // This is only necessary to cache the case of null.
+ // Caching that allows us to avoid repeated looking up a resource that doesn't exist in the case of a
+ // broken proxy.
+ uriToResource.put(uri, resource);
return resource;
}
@@ -329,21 +338,30 @@
EObject eObject = proxyEntry.eObject;
EStructuralFeature proxyFeature = proxyEntry.proxyFeature;
- Object values = eObject.eGet(proxyFeature, true);
- if (values instanceof InternalEList<?>) {
- final ListIterator<?> crossRefs = ((InternalEList<?>)values).basicListIterator();
+ // Get the value without resolving proxies.
+ Object value = eObject.eGet(proxyFeature, false);
+ // If it's a list...
+ if (value instanceof InternalEList<?>) {
+ // Iterate over the values without resolving proxies.
+ @SuppressWarnings("unchecked")
+ InternalEList<InternalEObject> values = (InternalEList<InternalEObject>)value;
+ final ListIterator<InternalEObject> crossRefs = values.basicListIterator();
while (crossRefs.hasNext()) {
- final Object nextValue = crossRefs.next();
- if (nextValue instanceof EObject && ((EObject)nextValue).eIsProxy()) {
- final URI proxyURI = ((InternalEObject)nextValue).eProxyURI();
- final Resource targetRes = getResource(proxyURI.trimFragment(), false);
-
- if (targetRes != null) {
- // resolve this one
- ((InternalEList<?>)values).get(crossRefs.previousIndex());
- }
+ // If it has a proxy URI and that resource is already loaded...
+ final InternalEObject nextValue = crossRefs.next();
+ URI eProxyURI = nextValue.eProxyURI();
+ if (eProxyURI != null && getResource(eProxyURI.trimFragment(), false) != null) {
+ // Force it to be resolved.
+ values.get(crossRefs.previousIndex());
}
}
+ } else if (value != null) {
+ // It must be an EObject and if has a proxy URI and that resource is already loaded...
+ URI eProxyURI = ((InternalEObject)value).eProxyURI();
+ if (eProxyURI != null && getResource(eProxyURI.trimFragment(), false) != null) {
+ // Force it to be resolved.
+ eObject.eGet(proxyFeature, true);
+ }
}
monitor.worked(1);
@@ -479,6 +497,7 @@
@Override
public Resource createResource(URI uri, String contentType) {
checkNotDisposed();
+ getURIResourceMap().remove(uri); // clear potentially cached null value
return super.createResource(uri, contentType);
}
@@ -552,16 +571,18 @@
* Helper class to encapsulate pairs of {@link EObject}s and {@link EStructuralFeature}s pointing to proxy
* objects.
*/
- private class ProxyEntry {
+ private static class ProxyEntry {
/**
- * The {@link EObject} containing a {@link EStructuralFeature} pointing to a proxy object.
+ * The {@link EObject} containing a {@link EStructuralFeature} pointing to a proxy object. It's
+ * protected to avoid a generated bridge method when accessed.
*/
- private final EObject eObject;
+ protected final EObject eObject;
/**
- * The {@link EStructuralFeature} within the {@link #eObject} pointing to a proxy object.
+ * The {@link EStructuralFeature} within the {@link #eObject} pointing to a proxy object. It's
+ * protected to avoid a generated bridge method when accessed.
*/
- private final EStructuralFeature proxyFeature;
+ protected final EStructuralFeature proxyFeature;
/**
* Constructor.