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