platform-vcm-home/docs/online/team3.1/logical-physical-mappings.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (view) (download) (as text)

1 : mvalenta 1.1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2 :     <html>
3 :     <head>
4 :     <title>Support Logical Resources: Resource Mappings</title>
5 :     </head>
6 :     <body>
7 :     <table border="0" cellspacing="5" cellpadding="2" width="100%">
8 :     <tbody>
9 :     <tr>
10 :     <td align="left" valign="top" bgcolor="#0080c0"> <b><font
11 :     color="#ffffff" face="Arial,Helvetica"> Eclipse 3.1 - Support Logical Resources
12 :     - Resource Mappings</font></b></td>
13 :     </tr>
14 :     </tbody>
15 :     </table>
16 :     <h1>Support Logical Resources - Resource Mappings</h1>
17 :     This document outlines the chosen solution to the adaptables problem outlined
18 :     in the <a href="logical-physical-public.html"><strong>Support Logical Resources</strong></a>
19 :     plan item problem description document. Feedback is strongly encouraged and may
20 :     be provided on the platform-team-dev mailing list or in the <a
21 :     href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37723">bug report</a> for
22 :     this plan item. The API described in this document is not yet final and may undergo
23 :     some revision before the end of the Eclipse 3.1 development cycle.
24 :     <h3>The Basic Resource Mapping API</h3>
25 :     <p>This solution involves adding API to the Resources plugin that maps logical
26 : mvalenta 1.2 models elements to workspace (i.e. file system) resources. The API is purposely
27 :     simple with logical model manipulations omitted. A client can't use this interface
28 :     to display logical models or gain any interesting additional knowledge about
29 :     it. It's purpose is simply to map one or more model elements to workspace resources.
30 :     </p>
31 :     <p>The API consists of the following classes: </p>
32 : mvalenta 1.1 <ul>
33 : mvalenta 1.2 <li><strong>ResourceMapping</strong>: The Class to which logical model elements
34 : mvalenta 1.1 adapt to indicate that the model corresponds to a set of resources in the
35 :     workspace. The complete <code>ResourceMapping</code> class can be viewed <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.core.resources/src/org/eclipse/core/resources/mapping/ResourceMapping.java?rev=HEAD&content-type=text/vnd.viewcvs-markup">here</a>.
36 :     The methods of interest are:
37 :     <ul>
38 :     <li><code>Object getModelObject()</code>: The model object from which the
39 :     mapping was derived (or adapted).</li>
40 :     <li><code>ResourceTraversal[] getTraversals(ResourceMappingContext, IProgressMonitor)</code>:
41 :     The resource traversal that cover the resources that constitute the model
42 :     object.</li>
43 :     </ul>
44 :     </li>
45 :     <li><strong>ResourceTraversal</strong>: A <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.core.resources/src/org/eclipse/core/resources/mapping/ResourceTraversal.java?rev=HEAD&content-type=text/vnd.viewcvs-markup"><code>ResourceTraversal</code></a>
46 :     simply contains a set of resources and a depth flag that indicates the depth
47 :     to which the resources in the traversal are associated with the originating
48 :     model object. Resource traversals are provided to a client by a resource mapping
49 :     in order to describe the contents of a model in sich a way that a repository
50 : mvalenta 1.2 provider can perform its operations in as efficient a means as possible. Methods
51 :     of interest are:
52 :     <ul>
53 :     <li><code>getResources()</code></li>
54 :     <li><code>getDepth()</code></li>
55 :     </ul>
56 :     </li>
57 : mvalenta 1.1 <li><strong>ResourceMappingContext</strong>: a context that is provided to the
58 : mvalenta 1.2 resource mapping by the client when obtaining traversals. This context allows
59 :     the logical model to determine what the remote state of the model is so that
60 :     the proper resources can be covered by the resource traversals returned by
61 :     the resource mapping. The use of the<code> <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.core.resources/src/org/eclipse/core/resources/mapping/ResourceMappingContext.java?rev=HEAD&content-type=text/vnd.viewcvs-markup">ResourceMappingContext</a></code>
62 : mvalenta 1.1 is a bit more complicated and is described <a href="#ResourceMappingContext">later</a>.</li>
63 :     </ul>
64 :     <p>There are two types of plugins that should be interested in resource mappings.
65 : mvalenta 1.2 Those who provide a model that consists of, or is persisted in, resources in
66 :     the workspace and those that want to perform operations on resources. The following
67 : mvalenta 1.1 two sections describe how to associate a resource mapping with a model object
68 :     and how to contribute menus to objects that adapt to resource mappings.</p>
69 :     <h4>Adapting a Model to a ResourceMapping</h4>
70 :     <p>Plugins that adapted their model objects to <code>IResource</code> in order
71 : mvalenta 1.2 to get resource specific actions shown in the context menu can now adapt to
72 :     <code>ResourceMapping</code> if a richer description of how the object adapts
73 :     to resources is benefitial. However, they are not required to do so if there
74 :     is no benefit. For instance a Java class that now currently adapts to <code>IFile</code>
75 :     need not adapt to <code>ResourceMapping</code> since nothing is gained. However,
76 :     a Java package should adapt to <code>ResourceMapping</code> in order to indicate
77 :     that the package is only the files in the corresponding folder and not the subfolders.</p>
78 :     <p>The preferred way to adapt model elements to a resource mapping is to use an
79 :     adapter factory. The following is the XML markup for contributing an adapter
80 :     factory in a plugin manifest. </p>
81 : mvalenta 1.1 <pre style="background-color: rgb(204, 204, 255);"> &lt;extension<br> point=&quot;org.eclipse.core.runtime.adapters&quot;&gt;<br> &lt;factory<br> class=&quot;org.eclipse.example.library.logical.AdapterFactory&quot;<br> adaptableType=&quot;org.eclipse.example.library.Book&quot;&gt;<br> &lt;adapter type=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;/&gt;<br> &lt;/factory&gt;<br> &lt;factory<br> class=&quot;org.eclipse.example.library.logical.AdapterFactory&quot;<br> adaptableType=&quot;org.eclipse.example.library.Library&quot;&gt;<br> &lt;adapter type=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;/&gt;<br> &lt;/factory&gt;<br> ...<br> &lt;/extension&gt;</pre>
82 : mvalenta 1.2 <p>The adapter factory implementation would look something like this:</p>
83 :     <pre style="background-color: rgb(204, 204, 255);">public class AdapterFactory implements IAdapterFactory {
84 :     public Object getAdapter(Object adaptableObject, Class adapterType) {
85 :     if((adaptableObject instanceof EObject) && adapterType == ResourceMapping.class) {
86 :     return new EMFResourceMapping((EObject)adaptableObject);
87 :     }
88 :     return null;
89 :     }
90 :    
91 :     public Class[] getAdapterList() {
92 :     return new Class[] {ResourceMapping.class};
93 :     }
94 :     }</pre>
95 : mvalenta 1.1 <p>For popup menu contribuions, it is not required that the model objects implement
96 :     the <code>IAdaptable</code> interface. However, if they do they must ensure
97 :     that the Platform adapter manager is consulted. This can be done by either subclassing
98 :     <code>PlatformObject</code> or by using the following line of code:</p>
99 :     <blockquote>
100 :     <p><code>Platform.getAdapterManager().getAdapter(Object, Class)</code></p>
101 :     </blockquote>
102 :     <p>The above is the preferrable approach. However, the model object can implement
103 :     the IAdaptable interface and provide a <code>getAdapter(Class)</code> implementation
104 :     that creates returns an instance of <code>ResourceMapping</code> explicitly
105 :     when asked for one. This is a more straightforward approach but the least desirable
106 :     as the model must have explicit knowledge of the adaptation to resources.</p>
107 : mvalenta 1.3 <p>The implementation of the <code>ResourceMapping</code> subclass for a Java
108 :     package would look something like this.</p>
109 :     <pre style="background-color: rgb(204, 204, 255);">public class JavaPackageResourceMapping extends ResourceMapping {
110 :     IPackageFragment package;
111 :     ...
112 :     public getModelObject() {
113 :     return package;
114 :     }
115 :     public ResourceTraversals[] getTraversals(
116 :     ResourceMappingContext context,
117 :     IProgressMonitor monitor) {
118 :     return new ResourceTraversal[] {
119 :     new ResourceTraversal(
120 :     new IResource[] { package.getCorrespondingResource() },
121 :     IResource.DEPTH_ONE, IResource.NONE)
122 :     }
123 :     }
124 :     }</pre>
125 :     <p>This is a fairly straightforward mapping so the implementaion is not complex.
126 :     The complexity of the resource mapping implementation will, of course, vary
127 :     from model to model. The <code>EMFResourceMapping</code> example used above
128 :     is implemented in the example and it a much more complicated implementation.</p>
129 : mvalenta 1.1 <h4>Contributing Menus to Resource Mappings</h4>
130 :     <p>Plug-ins that contribute extensions to adaptable extension points will have
131 :     to make two changes to support the new <code>ResourceMapping</code> APIs:</p>
132 :     <ol>
133 :     <li>Update their plugin.xml files tochange the objectClass of their adaptable
134 :     contributions to <code>ResourceMapping</code> (for those for which this is
135 :     appropriate).</li>
136 :     <li>Update their actions to work on <code>ResourceMapping</code> instead of
137 :     IResource and respect the depth constraints provided in the traversals.</li>
138 :     <li>(Optional) provide a <code>ResourceMappingContext</code> if they manage
139 :     remote resources (more on this <a href="#ResourceMappingContext">below</a>)</li>
140 :     </ol>
141 :     <p>First of all, plugins that add object contributions to <code>IResource</code>
142 :     (CVS, Search, Compare) can now add them to <code>ResourceMapping</code> instead,
143 :     if the action can apply to multiple resources. Here is an XML snipet:</p>
144 :     <pre style="background-color: rgb(204, 204, 255);"> &lt;extension<br> point=&quot;org.eclipse.ui.popupMenus&quot;&gt;<br> &lt;objectContribution<br> adaptable=&quot;true&quot;<br> objectClass=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;<br> id=&quot;org.eclipse.example.library.ResourceMappingContributions&quot;&gt;<br> &lt;action<br> label=&quot;Show Resource Mappings&quot;<br> class=&quot;org.eclipse.example.library.contributions.ShowResourceMappingsAction&quot;<br> menubarPath=&quot;additions&quot;<br> id=&quot;org.eclipse.example.library.showMappings&quot;/&gt; <br> &lt;/objectContribution&gt;<br> &lt;/extension&gt;</pre>
145 :     <p>Contributions to <code>ResourceMapping</code> will automatically apply to objects
146 :     that adapt to <code>IResource</code>. This transitive association is handled
147 :     by the Workbench.</p>
148 :     <p>Filtering of the contributions to resource mappings can be done using action
149 :     filters or expressions although expressions are perferrable. An expression for
150 :     filtering by project persistant property has been added to allow repository
151 :     providers to have their menus appear on projects that are mapped to their repositories.</p>
152 :     <pre style="background-color: rgb(204, 204, 255);"> &lt;extension<br> point=&quot;org.eclipse.ui.popupMenus&quot;&gt;<br> &lt;objectContribution<br> objectClass=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;<br> adaptable=&quot;true&quot;<br> id=&quot;org.eclipse.team.ccvs.ui.ResourceMapperContributions&quot;&gt;<br> &lt;enablement&gt;<br> &lt;adapt type=&quot;org.eclipse.core.resources.mapping.ResourceMapping&quot;&gt;<br> &lt;test
153 :     property=&quot;org.eclipse.ui.ide.projectPersistentProperty&quot;
154 :     args=&quot;org.eclipse.team.core.repository=org.eclipse.team.cvs.core.cvsnature&quot; /&gt;<br> &lt;/adapt&gt;<br> &lt;/enablement&gt;<br> &lt;action<br> label=&quot;%UpdateAction.label&quot;<br> definitionId=&quot;org.eclipse.team.cvs.ui.update&quot;<br> class=&quot;org.eclipse.team.internal.ccvs.ui.actions.UpdateAction&quot;<br> tooltip=&quot;%UpdateAction.tooltip&quot;<br> menubarPath=&quot;team.main/group2&quot;<br> id=&quot;org.eclipse.team.cvs.ui.update&quot;&gt;<br> &lt;/action&gt;
155 :     ...<br> &lt;/objectContribution&gt;<br> &lt;/extension&gt;</pre>
156 :     <p>Actions that have been contributed to the <code>ResourceMapping</code> class
157 :     will be given a selection that contains one or more <code>ResourceMappings</code>.
158 :     It is the actions responsibility to translate the resource mapping into a set
159 :     of resources to be operated on. This can be done by calling <code>getTraversals</code>
160 :     to get the traversals of the mapping. Traversals are used to allow the clients
161 :     of the traversal to optimize their operations based on the depth of the resources
162 :     being traversed. A client may traverse the resource manually or may use the
163 :     resource and the depth as input into an operation that the action delegates
164 :     to do the work. As an example, if the user performs a CVS update on a java package
165 :     and the java package resource mapping maps to a folder of depth one, CVS would
166 :     issue an appropriat command (&quot;cvs update -l&quot; for those who are curious)
167 :     which would perform a shallow update on the folder the pakcage represents.</p>
168 :     <h3><a name="ResourceMappingContext"></a>Resource Mapping Context</h3>
169 :     <p>One of the advantages of a Resouce Mapping API is that it allows plug-ins to
170 :     implement any operations they desire in terms of resource mappings (e.g. CVS
171 :     update, CVS commit, CVS tag, dirty decoration, etc.). However, the API that
172 :     has been introduced so far deals only with the local state of the model. When
173 :     working with a model that may be shared between developers, you end up in a
174 :     situation where the remote state of the model (i.e. the state of the model that
175 :     another user has checked-in to the repository) may differ from the state in
176 :     the workspace. If you performed a CVS update, you would want the local state
177 :     of the model to match the remote state even if it meant that additional files
178 :     needed to be included or some files needed to be removed.</p>
179 :     <p>This is not an issue for some logical models. For instance, a java package
180 :     is a container visited to a depth of one, regardless of the remote state of
181 :     the model. Given this, a repository provider can easily determine that outgoing
182 :     deletions should be included when committing or that incoming additions should
183 :     be included when updating. However, the resources that constitute some logical
184 :     models may change over time. For instance, the resources that constitute a model
185 :     element may depend of the contents of a manifest file (or some other similar
186 :     mechanism). In order for the ResourceMapping to return the proper traversal,
187 :     it must access the remote contents of the manifest file (if it differes from
188 :     the local contents) in order to see if there are additional resources that need
189 :     to be included. These additional resources may not exist in the workspace but
190 :     the repository provider would know how to make sure they did when the selected
191 :     action was performed.</p>
192 :     <p>In order to support these more complex models, a <code>ResourceMappingContext</code>
193 :     can be passed to the <code>ResourceMapping#getTraversals</code> method. When
194 :     a context is provided, the mapping can use it to ensure that all the necessary
195 :     resources are included in the traversal. If a context is not provided, the mapping
196 :     can assume that only the local state is of interest. </p>
197 :     <h4>When does a ResourceMapping need to worry about the ResourceMappingContext?</h4>
198 :     <p>A <code>ResourceMapping</code> need only worry about a context supplied to
199 :     the <code>getTraversals</code> method in cases were the resources that make
200 :     up a model change over time and the relationship between the model and resources
201 :     cannot be described by a simple traversal that is gauranteed to encompass those
202 :     resources (and only those resources) that consitute the model. For example,
203 :     although the resources of a Java package may change over time, the package can
204 : mvalenta 1.3 be described as a folder of depth of one so a resource mapping for java packages
205 : mvalenta 1.1 would not ned to make use of the resource mapping context. </p>
206 :     <p>As a more complicated example, consider an HTML file that contains several
207 :     images. Let's mak the assumption that any images references from an HTML file
208 :     ae part of the model of that file. When updating the local contents of the HTML
209 :     file from a repository, the user would expect that any new images would be included.
210 :     The getTraversals method for a ResourceMapping for the HTML file model would
211 :     look something like this:</p>
212 : mvalenta 1.2 <pre style="background-color: rgb(204, 204, 255);">public class HTMLResourceMapping extends ResourceMapping {
213 : mvalenta 1.1 private HTMLFile htmlFile;
214 :     getTraversals(ResourceMappingContext context, IPorgressMonitor monitor) {
215 :     IResource[] resources = htmlFile.getRsources();
216 :     if (context != null) {
217 :     // Look for any additional resources on the server
218 :     IFile file = htmlFile.getFile();
219 :     if (context.contentDiffers(file, monitor) {
220 :     IStorage storage = context.fetchContents(file, monitor);
221 :     IResource[] additionalResources = getReferences(storage.getContents());
222 :     resources = combine(resources, additionalResources);
223 :    
224 :     }
225 :     }
226 :     return new ResourceTraversal(resources, IResource.DEPTH_ZERO);
227 :    
228 :     }<br>}</pre>
229 :     <h4>When does a client need to provide a ResourceMappingContext?</h4>
230 :     <p>Any client that is providing the ability of sharing workspace resources through
231 :     a repository and is supporting ResourceMappings should provide an appropriate
232 :     context for determining the relevant remote state o the model resources. The
233 :     context provides three basic quieries:</p>
234 :     <ul>
235 :     <li>Does the local contents differ from the remote contents</li>
236 :     <li>What are the remote contents of a file</li>
237 :     <li>What are the remote memebers of a folder</li>
238 :     </ul>
239 :     <p>The answer to the first question above depends on the type of operation that
240 :     is being performed:</p>
241 :     <ul>
242 :     <li>When checking in a resource, the context would consider that a file's contents
243 :     differ if the local contents have been modified since the last check-in.</li>
244 :     <li>When updating a resource, the context would consider that a file's contents
245 :     differ if the remote contents have been modified since the users last update.</li>
246 :     <li>When replacing a resource, the context would consider that a file's contents
247 :     differ if either the the local or remote contents have changed since the last
248 :     synchronization.</li>
249 :     </ul>
250 :     <p>The Eclipse Team API includes a <code>Subcriber</code> class that defines an
251 :     API for providing the synchronization state between the local workspace and
252 :     a remote server. A <code>SubscriberResourceMappingContext</code> has been created
253 :     that uses a <code>Subscriber</code> to access the necessary remote state. Clients
254 :     that have a <code>Subscriber</code> do not need to do any additional work to
255 :     get a resource mapping context.</p>
256 :     <h2>How this will affect existing plug-ins</h2>
257 :     <p>Existing plugins do not need to change at all unless they want to take advantage
258 :     of the new API. For plugins that provide logical modes, it may be worthwhile
259 :     for them to adapt their model objects to <code>ResourceMappings</code>. Of course,
260 :     this is only a benefit when combined with a repository provider implementation
261 :     that contributes at last some of it's actions to resource mappings.</p>
262 :     <span style="font-weight: bold;"></span>
263 :     <h2>Open Issues</h2>
264 :     <p>The following issues would need to be addressed for this solutions.</p>
265 :     <ul>
266 :     <li> Plugins that add object contributions will have to modify their actions
267 :     to handle logical resources. There should be some standard UI components for
268 :     showing the mappings. For instance you could show the logical model at the
269 :     top and in a details part the physical files/folders that will be affected
270 :     by the operation.</li>
271 :     <li>Would it be possible to add a workbench adapter to specific implementations
272 :     IModelElement in order to get an image and label for a model element?</li>
273 :     <li>Can the user benefit from resource mappings in cases where the repository
274 : mvalenta 1.3 provider isn't mapping aware?</li>
275 :     <li>What about reposiory providers that cannot provide a remote mapping context?</li>
276 :     <li>What should a model provider do if they canno reliably determine the remote
277 :     model state? </li>
278 :     <li>Need to reference the example<br>
279 : mvalenta 1.1 </li>
280 :     </ul>
281 :     </body>
282 :     </html>