platform-vcm-home/docs/online/team3.1/logical-physical-mappings.html
Parent Directory
|
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);"> <extension<br> point="org.eclipse.core.runtime.adapters"><br> <factory<br> class="org.eclipse.example.library.logical.AdapterFactory"<br> adaptableType="org.eclipse.example.library.Book"><br> <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/><br> </factory><br> <factory<br> class="org.eclipse.example.library.logical.AdapterFactory"<br> adaptableType="org.eclipse.example.library.Library"><br> <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/><br> </factory><br> ...<br> </extension></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);"> <extension<br> point="org.eclipse.ui.popupMenus"><br> <objectContribution<br> adaptable="true"<br> objectClass="org.eclipse.core.resources.mapping.ResourceMapping"<br> id="org.eclipse.example.library.ResourceMappingContributions"><br> <action<br> label="Show Resource Mappings"<br> class="org.eclipse.example.library.contributions.ShowResourceMappingsAction"<br> menubarPath="additions"<br> id="org.eclipse.example.library.showMappings"/> <br> </objectContribution><br> </extension></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);"> <extension<br> point="org.eclipse.ui.popupMenus"><br> <objectContribution<br> objectClass="org.eclipse.core.resources.mapping.ResourceMapping"<br> adaptable="true"<br> id="org.eclipse.team.ccvs.ui.ResourceMapperContributions"><br> <enablement><br> <adapt type="org.eclipse.core.resources.mapping.ResourceMapping"><br> <test | ||
| 153 : | property="org.eclipse.ui.ide.projectPersistentProperty" | ||
| 154 : | args="org.eclipse.team.core.repository=org.eclipse.team.cvs.core.cvsnature" /><br> </adapt><br> </enablement><br> <action<br> label="%UpdateAction.label"<br> definitionId="org.eclipse.team.cvs.ui.update"<br> class="org.eclipse.team.internal.ccvs.ui.actions.UpdateAction"<br> tooltip="%UpdateAction.tooltip"<br> menubarPath="team.main/group2"<br> id="org.eclipse.team.cvs.ui.update"><br> </action> | ||
| 155 : | ...<br> </objectContribution><br> </extension></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 ("cvs update -l" 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> |
| help@eclipse.org | ViewVC Help |
| Powered by ViewVC 1.0.3 |
