blob: c103ec24d72b5a4e0fd0d00533a801bfec8661c7 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type"
content="application/xhtml+xml; charset=utf-8">
<meta name="generator" content="Windows Notepad">
<link rel="stylesheet" href="http://dev.eclipse.org/default_style.css"
type="text/css">
<link rel="stylesheet" type="text/css"
href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-vcm-home/layout.css"
title="Grey boxes stylesheet">
<link rel="stylesheet" type="text/css"
href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-vcm-home/colors.css">
<title>Eclipse Platform - Adaptable Contributions</title>
</head>
<body>
<h1>Support for adaptable contributions in Eclipse 3.1</h1>
Last Updated: February 10th, 2005<br>
by Jean-Michel Lemieux<br>
<br>
<span style="font-weight: bold;">Context</span><br>
<br>
All adaptable workbench contributions only support adapting to
IResource.<br>
<br>
<span style="font-weight: bold;">Problem</span> <br>
<br>
An adaptable flag was added to three workbench extension points to
allow contributions (e.g. popupMenus, property pages, decorators) to be
applied to
classes that do not share a common ancestor. For example, to enable CVS
contributions to appear in the Java Packages View. The CVS plug-in
defines adaptable contributions on IResource types and JDT would
provide adapters from Java elements to IResources. The problem is that <span
style="font-weight: bold;">adaptable contributions are
currently limited to IResource classes</span>.<br>
<br>
<span style="font-weight: bold;">Adapting models: the key to rich
integration</span><br>
<br>
In Eclipse plug-ins are free to model their application data using their model
of choice. A key to providing integration in Eclipse is to allow bridging of the
models. A model is a fairly generic term, but is known to most people as the actual
data representation for an application. But there are actually three types of
models:<font size="-1"><br>
<br>
</font>
<table cellpadding="2" cellspacing="2" border="1"
style="text-align: left; width: 100%;">
<tbody>
<tr>
<td style="vertical-align: top; width: 15%;"><strong>Types</strong></td>
<td style="vertical-align: top;"><strong>Descirption</strong></td>
</tr>
<tr>
<td style="vertical-align: top; width: 15%;">Meta-model</td>
<td style="vertical-align: top;">A model that includes types whose instances
are also types. Meta-models are often used to specify other models. For
example, EMF provides a meta-model (ECore) for describing models. </td>
</tr>
<tr>
<td style="vertical-align: top; width: 15%;">Model</td>
<td style="vertical-align: top;">A model of a specific application domain.
These instances are called meta-objects. A model is the actual data representation
for an application. For example, in JDT the model is composed of ICompilationUnit,
IJavaProject... The model can be instances of a meta-model or a standalone
model (e.g. simply a set of classes and interfaces).</td>
</tr>
<tr>
<td style="vertical-align: top; width: 15%;">User Objects<br>
</td>
<td style="vertical-align: top;">Instances of the elements of a model.</td>
</tr>
</tbody>
</table>
<font size="2" face="Arial, Helvetica"><br>
</font>Figure 1 describes the common relationships between plug-ins and
models in Eclipse. In this example, Model A is defined as a base model;
an adapter is defined for elements from model B and C that will return
and element from model A.
Adaptable contributions is the mechanism that allows models to accept
contributions made to
base models without requiring the model implementation to inherit or
implement classes from the base model.<br>
<br>
<div style="text-align: center;"><img src="adapters.png" alt=""
style="width: 501px; height: 342px;"><br>
</div>
Figure 1: Plug-ins and models<br>
<br>
Currently the only base model supported in Eclipse is IResource. The
goal for opening this up is to allow other base models to exist and
thus allow bridging between other domain models.<br>
<br>
<span style="font-weight: bold;">Note</span>: When adapting to a base
model it is not fair to accept that all adapters represent a 1-1
mapping between model elements. Consider providing a mapping interface
which allows a flexible representation of the mapping between two
models.<br>
<br>
<span style="font-weight: bold;">Adapters <span
style="font-weight: bold;"><br>
</span></span><br>
A historic problem with Adapters in Eclipse was that they were defined
at runtime. This meant that using them for contributions was not
possible since plug-in that were'nt loaded would not get a chance to
contribute adapters. The result was that contributions may not be
visible until a plug-in was loaded. This was solved in 3.0 with the
support for declarative specification of adapter factories.<br>
<br>
Contributions are adapted using the adapter factory to query the
supported adapters for a given type. This means that for adaptable
contributions to be supported plug-ins must move any runtime adapter
specification to use the new declarative extension point. There are two
distinct participants involved in supporting adaptable contributions:<br>
<ol>
<li>A plug-in that defines a model must define the adapters it
supports. <br>
</li>
<li>A plug-in that defines common contributions must define the base
model elements they apply to and ensure that the contributions are
marked adaptable.</li>
</ol>
<span style="font-weight: bold;">Defining the adapters</span><br>
<br>
A plug-in can define the adapters it supports by registering an
IAdapterFactory with the <span style="font-style: italic;">org.eclipse.runtime.adapters</span>
extension point as follows:<br>
<pre style="background-color: rgb(204, 204, 255);">&lt;extension<br> point="org.eclipse.core.runtime.adapters"&gt;<br> &lt;factory<br> class="logicalView.views.AdapterFactory"<br> adaptableType="logicalView.views.MyLogicalElement"&gt;<br> &lt;adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/&gt;<br> &lt;/factory&gt;<br>&lt;/extension&gt;<br></pre>
This plugin.xml snippet defines an adapter that can adapt instances of MyLogicalElement
to ResourceMapping. An adapter factory can adapt the same adaptableType to different
types. Simply add another <span
style="font-style: italic;">adapter </span>element to the extension point. The
adapter factory implementation would be:<br>
<pre style="background-color: rgb(204, 204, 255);">public class AdapterFactory implements IAdapterFactory {<br> public Object getAdapter(Object adaptable, Class adapterType) {<br> if(adaptableinstanceof MyLogicalElement &amp;&amp; <br> adapterType == ResourceMapping.class) {<br> return new MyLogicalElementResourceMapping(<br> (MyLogicalElement)adaptable);<br> } <br> return null;<br> }<br><br> public Class[] getAdapterList() {<br> return new Class[] {IResourceMapper.class};<br> }<br>}<br></pre>
<span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>A
rule of thumb when deciding what adapters to register, try and adapt to
the most specific type possible. For example, although it is
technically possible to return the IProject for a java IMethod (e.g.
the project that contains the method) the relationship is too vague and
would be best to return the IFile instead.<span
style="font-weight: bold;"><span style="font-weight: bold;"></span><br>
<br>
Definining the contributions</span><br>
<br>
The syntax for defining contributions hasn't changed simply, that the adaptable
attribute will be honoured even when the object class is not IResource. Here is
a snippet for defining a popup menu that should appear on ResourceMapping instances:<br>
<pre style="background-color: rgb(204, 204, 255);">&lt;extension<br> point="org.eclipse.ui.popupMenus"&gt;<br>&lt;objectContribution<br> objectClass="org.eclipse.core.resources.mapping.ResourceMapping"<br> adaptable="true"<br> id="myaction.id"&gt;<br> &lt;action<br> label="Do It"<br> class="myplug.actions.DoItAction"<br> menubarPath="additions"<br> id="myaction.id.doit"&gt;<br> &lt;/action&gt;<br>&lt;/objectContribution&gt;&lt;/extension&gt;</pre>
The implementation of the action can assume the following:<br>
<ul>
<li>The selection is always converted to the type specified in
objectClass. This implies that <br>
</li>
<li>Filters (e.g IActionFilter, enablement rules) applied to a
contribution are given the type specified in objectClass.</li>
</ul>
<p><span style="font-weight: bold;">IContributorResourceAdapter</span><br>
<br>
An interface was added in Eclipse 2.0 to allow plug-ins to adapt IResource elements
differently when they were used for workbench contributions (see Bug <a
href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=6247">6247</a> for a background
discussion). This interface is still honnoured when adapting to IResource by
first checking if an objects adapts to IContributorResourceAdapter then to IResource.
In 3.1, a subinterface IContributorResourceAdapter2 has been added to support
context dependant adaptation to ResourceMappings.</p>
<p><span style="font-weight: bold;">Note: </span>This class is defined in the
IDE plug-in meaning that applications not including the IDE can't use this support.<br>
<br>
<span style="font-weight: bold;">Problems with IActionFilter</span><br>
<br>
Action filters are designed to allow contributions to filter their visibility
based on a filter queried at runtime. The workbench tries to find an IActionFilter
for an object in the selection by asking the adapted selection if it can adapt
to IActionFilter. This is restrictive since it allows only one implementation
of an IActionFilter per type. Another more flexible approach is to use the new
enablement attribute that was added in 3.0. The following enablement will show
the contribution only if it is shared with a CVS project. The enablement tester
is provived in the contribution instead of via the selection, which makes this
approach more flexible.<br>
</p>
<pre style="background-color: rgb(204, 204, 255);">&lt;extension<br> point="org.eclipse.ui.popupMenus"&gt;<br>&lt;objectContribution<br> objectClass="org.eclipse.core.resources.mapping.ResourceMapping"<br> adaptable="true"<br> id="myaction.id"&gt;<br> &lt;enablement&gt;<br> &lt;test property=&quot;org.eclipse.ui.ide.projectPersistentProperty&quot;
args=&quot;org.eclipse.team.core.repository=org.eclipse.team.cvs.core.cvsnature&quot; /&gt;<br> &lt;/enablement&gt;<br> ...<br>&lt;/objectContribution&gt;&lt;/extension&gt;</pre>
The property tester would is contributed as follows:<br>
<pre style="background-color: rgb(204, 204, 255);">&lt;extension<br> point="org.eclipse.core.expressions.propertyTesters"&gt;<br> &lt;propertyTester
namespace=&quot;org.eclipse.ui.ide&quot;
type=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;
class=&quot;org.eclipse.ui.internal.ide.model.ProjectPersistentPropertyTester&quot;
properties=&quot;projectPersistentProperty&quot;
id=&quot;org.eclipse.ui.ide.projectPersistentPropertyTester&quot; /&gt;<br>&lt;/extension&gt;</pre>
<span style="font-weight: bold;">Related Bugs</span><br>
<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=32436<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=53217<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=76599<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=38041<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=36968<br>
https://bugs.eclipse.org/bugs/show_bug.cgi?id=37084<br>
<br>
<span style="font-weight: bold;">Related problems not addressed</span><br>
<ul>
<li>Visibility of contributions is based on a homogenous selection
algorithm. This ensure that all objects in the selection have a common
class and/or adapter. Heterogenous selection is not yet supported.</li>
<li>The IAdapterManager is non-transitive. This implies that all
contributions must define direct adapters for each type.</li>
<li>IContributorResourceAdapter is in IDE, thus IDE must be
references
for IResource adaptables to work.<br>
</li>
</ul>
<br>
<br>
</body>
</html>