Allow proxy resolution from the EMF Compare content merge viewers

Bug: 532484
Change-Id: Id92ebeb8f41dbd224cdae843ee4133880e0d394c
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
index 5e7bd76..8c9c342 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/ManyStructuralFeatureAccessorImpl.java
@@ -290,7 +290,7 @@
 	 */
 	protected List<?> getFeatureValues(MergeViewerSide side) {
 		final EObject eObject = getEObject(side);
-		return ReferenceUtil.getAsList(eObject, getStructuralFeature());
+		return ReferenceUtil.getAsListResolving(eObject, getStructuralFeature());
 	}
 
 	/**
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/SingleStructuralFeatureAccessorImpl.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/SingleStructuralFeatureAccessorImpl.java
index 06ef29f..4c5a690 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/SingleStructuralFeatureAccessorImpl.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/contentmergeviewer/accessor/impl/SingleStructuralFeatureAccessorImpl.java
@@ -77,7 +77,7 @@
 		Object value = null;
 		EObject eObject = getEObject(side);
 		if (eObject != null) {
-			value = ReferenceUtil.safeEGet(eObject, getStructuralFeature());
+			value = ReferenceUtil.safeResolvingEGet(eObject, getStructuralFeature());
 		}
 		return value;
 	}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/ReferenceUtil.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/ReferenceUtil.java
index 488b724..52b26c8 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/ReferenceUtil.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/ReferenceUtil.java
@@ -78,6 +78,43 @@
 	}
 
 	/**
+	 * This utility simply allows us to retrieve the value of a given feature as a List.
+	 * <p>
+	 * <b>Note</b> that contrary to {@link #getAsList(EObject, EStructuralFeature)}, this will allow proxy
+	 * resolution.
+	 * </p>
+	 * 
+	 * @param object
+	 *            The object for which feature we need a value.
+	 * @param feature
+	 *            The actual feature of which we need the value.
+	 * @return The value of the given <code>feature</code> for the given <code>object</code> as a list. An
+	 *         empty list if this object has no value for that feature or if the object is <code>null</code>.
+	 */
+	@SuppressWarnings("unchecked")
+	public static List<Object> getAsListResolving(EObject object, EStructuralFeature feature) {
+		if (object != null && feature != null) {
+			Object value = safeResolvingEGet(object, feature);
+			final List<Object> asList;
+			if (feature == EcorePackage.Literals.ECLASS__ESUPER_TYPES
+					|| feature == EcorePackage.Literals.EOPERATION__EEXCEPTIONS) {
+				// workaround 394286. Use the normal list, resolution is not much of a problem on these.
+				asList = (List<Object>)value;
+			} else if (value instanceof List) {
+				asList = (List<Object>)value;
+			} else if (value instanceof Iterable) {
+				asList = ImmutableList.copyOf((Iterable<Object>)value);
+			} else if (value != null) {
+				asList = ImmutableList.of(value);
+			} else {
+				asList = Collections.emptyList();
+			}
+			return asList;
+		}
+		return Collections.emptyList();
+	}
+
+	/**
 	 * In case of dynamic EObjects, the EClasses of both sides might be different, making "eget" fail in
 	 * "unknown feature". We assume that even if the EClasses are distinct instances, they are the same
 	 * nonetheless, and thus we can use the feature name in order to retrieve the feature's value.
@@ -94,6 +131,26 @@
 	}
 
 	/**
+	 * In case of dynamic EObjects, the EClasses of both sides might be different, making "eget" fail in
+	 * "unknown feature". We assume that even if the EClasses are distinct instances, they are the same
+	 * nonetheless, and thus we can use the feature name in order to retrieve the feature's value.
+	 * <p>
+	 * <b>Note</b> that contrary to {@link #safeEGet(EObject, EStructuralFeature)}, this will allow proxy
+	 * resolution.
+	 * </p>
+	 * 
+	 * @param object
+	 *            The object for which feature we need a value, must not be <code>null</code>.
+	 * @param feature
+	 *            The actual feature of which we need the value, must not be <code>null</code>.
+	 * @return The value of the given {@code feature} for the given {@code object}.
+	 */
+	public static Object safeResolvingEGet(EObject object, EStructuralFeature feature) {
+		final int featureID = getFeatureID(feature, object.eClass());
+		return ((InternalEObject)object).eGet(featureID, true, true);
+	}
+
+	/**
 	 * In case of dynamic EObjects, the EClasses of both sides might be different, making "isset" fail in
 	 * "unknown feature". We assume that even if the EClasses are distinct instances, they are the same
 	 * nonetheless, and thus we can use the feature name in order to retrieve the feature's value.