From 5f12efaeef7553898c40e609f51c1d916b7d27ab Mon Sep 17 00:00:00 2001
From: Christian W. Damus
Date: Sat, 23 Jan 2016 10:26:29 -0500
Subject: Bug 485220: [Architecture] Provide a more modular architecture
https://bugs.eclipse.org/bugs/show_bug.cgi?id=485220
Fix regression caused by removal of the EMF Facet content-provider
handling in the EMFHelper::getEObject API. The facet tree nodes
don't provide the object that we need as their EObject adapter,
so we introduce a new generalized service for resolving EObjects.
Also fix the failure to run the Profile Drafter tests in the build,
which aren't in a fragment bundle but actually a plug-in bundle.
---
.../META-INF/MANIFEST.MF | 1 +
.../org/eclipse/papyrus/infra/emf/Activator.java | 21 +++++++
.../emf/spi/resolver/ChainedEObjectResolver.java | 42 +++++++++++++
.../emf/spi/resolver/EObjectResolverService.java | 72 ++++++++++++++++++++++
.../infra/emf/spi/resolver/IEObjectResolver.java | 44 +++++++++++++
.../emf/spi/resolver/IdentityEObjectResolver.java | 35 +++++++++++
.../eclipse/papyrus/infra/emf/utils/EMFHelper.java | 7 +++
.../papyrus/infra/ui/internal/emf/Activator.java | 8 +++
8 files changed, 230 insertions(+)
create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/ChainedEObjectResolver.java
create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/EObjectResolverService.java
create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IEObjectResolver.java
create mode 100644 plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IdentityEObjectResolver.java
(limited to 'plugins/infra/emf')
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF
index a12f69a073d..f79d3178a14 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/META-INF/MANIFEST.MF
@@ -7,6 +7,7 @@ Export-Package: org.eclipse.papyrus.infra.emf,
org.eclipse.papyrus.infra.emf.requests,
org.eclipse.papyrus.infra.emf.resource,
org.eclipse.papyrus.infra.emf.resource.index,
+ org.eclipse.papyrus.infra.emf.spi.resolver,
org.eclipse.papyrus.infra.emf.utils
Require-Bundle: org.eclipse.papyrus.infra.core.log;bundle-version="1.2.0",
org.eclipse.papyrus.infra.tools;bundle-version="1.2.0",
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/Activator.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/Activator.java
index 4841a9fd239..fe845446d23 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/Activator.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/Activator.java
@@ -17,12 +17,15 @@ import java.util.ArrayList;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.papyrus.emf.facet.custom.core.ICustomizationManager;
import org.eclipse.papyrus.emf.facet.custom.core.ICustomizationManagerFactory;
import org.eclipse.papyrus.infra.core.log.LogHelper;
+import org.eclipse.papyrus.infra.emf.spi.resolver.EObjectResolverService;
+import org.eclipse.papyrus.infra.emf.spi.resolver.IEObjectResolver;
import org.osgi.framework.BundleContext;
/**
@@ -47,10 +50,13 @@ public class Activator extends Plugin {
// temp resourceSet
private ResourceSet facetRecsourceSet = new ResourceSetImpl();
+ private EObjectResolverService resolverService;
+
/**
* The constructor
*/
public Activator() {
+ super();
}
@Override
@@ -58,10 +64,16 @@ public class Activator extends Plugin {
super.start(context);
plugin = this;
log = new LogHelper(this);
+
+ resolverService = new EObjectResolverService(context);
+ resolverService.open();
}
@Override
public void stop(final BundleContext context) throws Exception {
+ resolverService.close();
+ resolverService = null;
+
plugin = null;
super.stop(context);
}
@@ -106,4 +118,13 @@ public class Activator extends Plugin {
return builder.toString();
}
+ /**
+ * Obtain the instance of the {@link EObject} resolver service, if any.
+ *
+ * @return the object resolver service (never {@code null} while this bundle is active)
+ */
+ public IEObjectResolver getEObjectResolver() {
+ return resolverService;
+ }
+
}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/ChainedEObjectResolver.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/ChainedEObjectResolver.java
new file mode 100644
index 00000000000..7ad2f97c012
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/ChainedEObjectResolver.java
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.emf.spi.resolver;
+
+/**
+ * A composite resolver.
+ */
+class ChainedEObjectResolver implements IEObjectResolver {
+
+ private final IEObjectResolver car;
+ private final IEObjectResolver cdr;
+
+ ChainedEObjectResolver(IEObjectResolver first, IEObjectResolver second) {
+ super();
+
+ this.car = first;
+ this.cdr = second;
+ }
+
+ @Override
+ public Object resolve(Object object) {
+ Object result = car.resolve(object);
+
+ if ((result == null) || (result == object)) {
+ result = cdr.resolve(object);
+ }
+
+ return result;
+ }
+
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/EObjectResolverService.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/EObjectResolverService.java
new file mode 100644
index 00000000000..9b2e0ecb239
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/EObjectResolverService.java
@@ -0,0 +1,72 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.emf.spi.resolver;
+
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Stream;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * A resolver that delegates to registered OSGi services in a Chain of Command
+ * pattern to provide the first available service result.
+ */
+public class EObjectResolverService extends ServiceTracker implements IEObjectResolver {
+ private final AtomicReference delegate = new AtomicReference<>(IEObjectResolver.identity());
+
+ /**
+ * Initializes me with the bundle context in which I track resolver services.
+ *
+ * @param context
+ * the bundle context
+ */
+ public EObjectResolverService(BundleContext context) {
+ super(context, IEObjectResolver.class, null);
+ }
+
+ @Override
+ public Object resolve(Object object) {
+ IEObjectResolver delegate = this.delegate.get();
+ if (delegate == null) {
+ // Recompute
+ delegate = Stream.of(getServices(new IEObjectResolver[getTrackingCount()]))
+ .filter(Objects::nonNull) // If the array has more slots than we have services
+ .reduce(IEObjectResolver.identity(), IEObjectResolver::compose);
+ this.delegate.set(delegate);
+ }
+
+ return delegate.resolve(object);
+ }
+
+ @Override
+ public IEObjectResolver addingService(ServiceReference reference) {
+ IEObjectResolver result = super.addingService(reference);
+
+ // We will have to recompute our delegates
+ delegate.set(null);
+
+ return result;
+ }
+
+ @Override
+ public void removedService(ServiceReference reference, IEObjectResolver service) {
+ super.removedService(reference, service);
+
+ // We will have to recompute our delegates
+ delegate.set(null);
+ }
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IEObjectResolver.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IEObjectResolver.java
new file mode 100644
index 00000000000..8f968d2db5e
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IEObjectResolver.java
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.emf.spi.resolver;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ * A service interface for resolution of the {@linkplain EObject EMF object} wrapped
+ * in an EMF Facet content-provider node or anything else that doesn't implement
+ * the usual {@link IAdaptable} protocol with respect to provision of an {@link EObject}.
+ */
+@FunctionalInterface
+public interface IEObjectResolver {
+ /**
+ * Resolves the object wrapped in a possible content-provider node.
+ *
+ * @param object
+ * an object that may be a content-provider node from a selection
+ * in an EMFFacet-based view, or something even more exotic
+ *
+ * @return the wrapped object, or the original {@code object} if it isn't our kind of wrapper
+ */
+ Object resolve(Object object);
+
+ default IEObjectResolver compose(IEObjectResolver other) {
+ return new ChainedEObjectResolver(this, other);
+ }
+
+ static IEObjectResolver identity() {
+ return IdentityEObjectResolver.INSTANCE;
+ }
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IdentityEObjectResolver.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IdentityEObjectResolver.java
new file mode 100644
index 00000000000..729f38f7d6b
--- /dev/null
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/spi/resolver/IdentityEObjectResolver.java
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * Copyright (c) 2016 Christian W. Damus 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:
+ * Christian W. Damus - Initial API and implementation
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.infra.emf.spi.resolver;
+
+/**
+ * A non-resolver.
+ */
+final class IdentityEObjectResolver implements IEObjectResolver {
+ static final IdentityEObjectResolver INSTANCE = new IdentityEObjectResolver();
+
+ private IdentityEObjectResolver() {
+ super();
+ }
+
+ @Override
+ public Object resolve(Object object) {
+ return object;
+ }
+
+ @Override
+ public IEObjectResolver compose(IEObjectResolver other) {
+ return other;
+ }
+}
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
index b0ebdee7994..feef59d314d 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.emf/src/org/eclipse/papyrus/infra/emf/utils/EMFHelper.java
@@ -220,6 +220,13 @@ public class EMFHelper {
*/
public static EObject getEObject(final Object source) {
+ // Support for EMF 0.2 CustomizedTree: The TreeElements are IAdaptable, but the
+ // EObject adapter for some of them (e.g. reference node) is not what we need
+ Object resolved = Activator.getDefault().getEObjectResolver().resolve(source);
+ if ((resolved != source) && isEMFModelElement(resolved)) {
+ return (EObject) resolved;
+ }
+
// General case
if (isEMFModelElement(source)) {
return (EObject) source;
diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/internal/emf/Activator.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/internal/emf/Activator.java
index ca3d404c299..ea8b59f2f9e 100644
--- a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/internal/emf/Activator.java
+++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/internal/emf/Activator.java
@@ -25,9 +25,11 @@ import org.eclipse.papyrus.emf.facet.custom.core.ICustomizationCatalogManager;
import org.eclipse.papyrus.emf.facet.custom.core.ICustomizationCatalogManagerFactory;
import org.eclipse.papyrus.emf.facet.custom.core.ICustomizationManager;
import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.custom.Customization;
+import org.eclipse.papyrus.emf.facet.custom.ui.CustomizedContentProviderUtils;
import org.eclipse.papyrus.infra.core.log.LogHelper;
import org.eclipse.papyrus.infra.emf.CustomizationComparator;
import org.eclipse.papyrus.infra.emf.readonly.spi.IReadOnlyManagerProcessor;
+import org.eclipse.papyrus.infra.emf.spi.resolver.IEObjectResolver;
import org.eclipse.papyrus.infra.ui.internal.emf.readonly.EditorReloadProcessor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
@@ -51,6 +53,7 @@ public class Activator extends AbstractUIPlugin {
*/
public static LogHelper log;
+ private ServiceRegistration eobjectResolverReg;
private ServiceRegistration roManagerProcessorReg;
private ICustomizationManager customizationManager;
@@ -67,6 +70,7 @@ public class Activator extends AbstractUIPlugin {
plugin = this;
log = new LogHelper(this);
+ eobjectResolverReg = context.registerService(IEObjectResolver.class, CustomizedContentProviderUtils::resolve, null);
roManagerProcessorReg = context.registerService(IReadOnlyManagerProcessor.class, new EditorReloadProcessor(), null);
}
@@ -76,6 +80,10 @@ public class Activator extends AbstractUIPlugin {
roManagerProcessorReg.unregister();
roManagerProcessorReg = null;
}
+ if (eobjectResolverReg != null) {
+ eobjectResolverReg.unregister();
+ eobjectResolverReg = null;
+ }
plugin = null;
super.stop(context);
--
cgit v1.2.3