|  | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | 
|  | <html> | 
|  | <head> | 
|  | </head> | 
|  | <body> | 
|  | <table width="100%" cellpadding="2" cellspacing="5" border="0"> | 
|  | <tbody> | 
|  | <tr> | 
|  | <td bgcolor="#0080c0" valign="top" align="left"> <b><font | 
|  | face="Arial,Helvetica" color="#ffffff"> Eclipse 3.1 - Plan item</font></b> | 
|  | </td> | 
|  | </tr> | 
|  | </tbody> | 
|  | </table> | 
|  | <h1>Support Logical Resources</h1> | 
|  | This document outlines the state of the Eclipse Platform <strong>Support | 
|  | Logical Resources</strong> plan item. Interested parties should review | 
|  | this document and verify that their use cases are reflected in the | 
|  | requirements then later that the solution provided satisfies their | 
|  | needs. Feedback is strongly encouraged and may be provided on the | 
|  | platform-vcm-dev mailing list or in the <a | 
|  | href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37723">bug report</a> | 
|  | for this plan item. | 
|  | <p class="MsoNormal">This is the plan item:</p> | 
|  | <blockquote> | 
|  | <p>"<em>The Eclipse Platform supports a strong physical view of | 
|  | projects, files, and folders in the workspace. However, there are many | 
|  | situations where a physical view is not the most salient or useful for | 
|  | many purposes. In some cases, multiple distinct objects happen to be | 
|  | stored in a single file, like an archive. Conversely, in other cases, | 
|  | something that is logically a single object is stored across multiple | 
|  | files. This discrepancy between logical and physical creates problems | 
|  | for common operations such as searching, comparing, and versioning, | 
|  | which need to work in the physical realm. Eclipse should support some | 
|  | way of mapping between a logical view and the physical organization of | 
|  | files on disk.</em>"</p> | 
|  | <p>Last Modified: July 2nd, 2003</p> | 
|  | </blockquote> | 
|  | <h1>Motivation</h1> | 
|  | <p>By definition Eclipse supports logical resources. It's a "an open | 
|  | extensible IDE for anything and nothing in particular". The | 
|  | applications that are built with it can be tailored to a particular | 
|  | problem domain and the workbench extensions can be used to provide | 
|  | support for any logical model. What Eclipse really doesn't support is | 
|  | integrating tools at the logical model. In order to integrate two | 
|  | plugins into Eclipse either the two plugins have to know about each | 
|  | other, or both plugins have to depend on some common plugin. While the | 
|  | first option is satisfactory for a few cases, the second case is the | 
|  | most common and the most problematic. To illustrate, the Eclipse SDK | 
|  | contains several plugins that are based on the Resources plugin (e.g. | 
|  | Team, Search, Compare, JDT). When an application is packaged based on | 
|  | the SDK, because the plugins in the SDK are resource based that is the | 
|  | common integration point between plug-ins.<br> | 
|  | </p> | 
|  | <p>As you will see later, even the users of the SDK (JDT+CVS+Resources) | 
|  | can observe some of the problems associated with the lack of support | 
|  | for logical resources and the implicit mapping to physical resources. | 
|  | The lack of a logical integration point causes the co-existance of | 
|  | plugins in Eclipse to be error prone for the user. The next sections | 
|  | will examine the relationships between logical and physical resources | 
|  | and outline the visible problems with Eclipse 3.0. </p> | 
|  | <h2>Existing Bugs</h2> | 
|  | <p>Bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=32582">32582</a> | 
|  | logical to physical mapping problem , 1 model element = 2 Files problem<br> | 
|  | Bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=3979">3979</a> | 
|  | [CVS Decorator] show version info works incorrectly for sub packages | 
|  | (1GFDIEB)</p> | 
|  | <h2>Logical Resources Defined<br> | 
|  | </h2> | 
|  | <p>Whereas logical resources are elements of the application that model | 
|  | the data/processes of a particular problem domain, the physical | 
|  | resources are the file system resources (e.g. files and folders) into | 
|  | which an application will eventually transform their application model | 
|  | for storage. Applications that don't use file system resources are not | 
|  | being considered as part of this plan item. For example, an application | 
|  | that stores it's application data directly into a database.</p> | 
|  | <p>The following table enumerates concrete examples of how logical and | 
|  | physical resources are used in current applications integrated into | 
|  | Eclipse.</p> | 
|  | <p><a name="#table1"></a>Table 1: Example logical to physical uses</p> | 
|  | <table border="1" width="100%"> | 
|  | <tbody> | 
|  | <tr> | 
|  | <td width="23%"> | 
|  | <div align="center"><strong>Relationships</strong></div> | 
|  | </td> | 
|  | <td width="77%"> | 
|  | <div align="center"><strong>Examples</strong></div> | 
|  | </td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td> | 
|  | <p>logical (1) <-> (*) physical</p> | 
|  | <p>one logical to many physical</p> | 
|  | </td> | 
|  | <td valign="top"> | 
|  | <p><a name="#1a"></a>(<strong>1a</strong>) EJB maps to several | 
|  | physical files: (WSAD + XDE Tester). This is the most common case we | 
|  | have found. </p> | 
|  | <blockquote> | 
|  | <p>/src/org/app/bean.java<br> | 
|  | /src/org/app/beanr.java<br> | 
|  | /src/org/app/beanlocal.java</p> | 
|  | </blockquote> | 
|  | <p><em>Note: If one of the logical resource's files was deleted | 
|  | who would remember that the file used to exist and is an outgoing | 
|  | deletion or that there is an incoming addition to the logical resource?</em></p> | 
|  | <p><a name="#1b"></a>(<strong>1b</strong>) Composite Object | 
|  | (logical) maps to several changed physical resources. (Rational XDE)</p> | 
|  | <p><em>Note</em>: <em>With 1 to many relationship there is | 
|  | always the complication that arises if the logical element maps to | 
|  | files in an other project? This would cause many problems in the | 
|  | current Team plugin.</em></p> | 
|  | </td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td> | 
|  | <p>logical (*) <-> (1) physical</p> | 
|  | <p>many logical to one physical</p> | 
|  | </td> | 
|  | <td valign="top"> | 
|  | <p><a name="#2a"></a>(<strong>2a</strong>) Methods in a class map | 
|  | to their containing class file. (JDT)</p> | 
|  | <p><a name="#2b"></a>(<strong>2b</strong>) Archive files (zip, | 
|  | jar) can be seen as a logical and the contents of the archive all map | 
|  | to the same physical.(JTD + all)</p> | 
|  | </td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td> | 
|  | <p>logical (1) <-> (1) physical</p> | 
|  | <p>one logical to one physical</p> | 
|  | </td> | 
|  | <td valign="top"> | 
|  | <p><a name="#3a"></a>(<strong>3a</strong>) A Java Package maps to | 
|  | a folder but a package does not include sub folders (e.g. they are | 
|  | shallow). (JDT)</p> | 
|  | <p><a name="#3b"></a>(<strong>3b</strong>) A UML class maps to a | 
|  | file. For example, in a UML application a class could be stored in a | 
|  | single file called 'x435dsds.umlclass'. The reason it's a logical is | 
|  | that the user of the application will never be concerned about the | 
|  | actual file name or even the folder it's stored in. (XDE)</p> | 
|  | </td> | 
|  | </tr> | 
|  | </tbody> | 
|  | </table> | 
|  | <h1>Complaints<br> | 
|  | </h1> | 
|  | <p>The following complaints are representative of bug reports and | 
|  | requirements received from several Eclipse plug-in developers. <br> | 
|  | </p> | 
|  | <h2>Complaint 1: Not very adaptable</h2> | 
|  | <p>Object contributions and decorators are key mechanisms for providing | 
|  | rich integration between tools. Using object contributions and | 
|  | adaptable objects, any plugin can provide actions and decorators that | 
|  | will show in another plugin's view. </p> | 
|  | <p>Since IResource is the lowest common integration class and is | 
|  | strongly mapped to its physical storage as files and folders, the | 
|  | integration point for actions and decorators cannot be the logical | 
|  | types in the view. The actions will consequently use the adaptable type | 
|  | from the selection to perform the action or the decorator the resource | 
|  | from the getImage request.</p> | 
|  | <p>Here is an example to illustrate the problem with the CVS plugin. | 
|  | When running a CVS commit action in the packages view the action | 
|  | doesn't know that the IFolder is a Java package and is a shallow | 
|  | namespace. It will use the selection and traverse the selected | 
|  | IContainer using IContainer.members() and commit all child resources. | 
|  | This is the same when the CVS outgoing decorator is shown on a package. | 
|  | It will reflect the deep outgoing state of the IContainer. This can | 
|  | lead to unexpected behavior because the user expected the action to run | 
|  | on the model that the action was displayed on.</p> | 
|  | <p>Example object contribution for the CVS commit action:</p> | 
|  | <pre><extension point="org.eclipse.ui.popupMenus"><br> <objectContribution<br>  objectClass="org.eclipse.core.resources.IResource"<br>  adaptable="true"<br>  id="org.eclipse.team.ccvs.ui.IResourceContributions"><br> <filter<br>  name="projectPersistentProperty"<br>  value="org.eclipse.team.core.repository=org.eclipse.team.cvs.core.cvsnature"><br> </filter><br> <action<br>  label="Commit"<br>  tooltip="Commit resource to CVS repository"<br>  class="org.eclipse.team.internal.ccvs.ui.actions.CommitAction"<br>  menubarPath="team.main/group3"<br>  id="org.eclipse.team.ccvs.ui.commit"><br> </action><br> <objectContribution><br></extension><br></pre> | 
|  | <p>Example code run in the commit action to calculate the resources to | 
|  | commit:</p> | 
|  | <pre>public static Object[] getSelectedAdaptables(ISelection selection)    {<br>  ArrayList result = null;<br>  if (!selection.isEmpty()) {<br>    result = new ArrayList();<br>    Iterator elements = ((IStructuredSelection) selection).iterator();<br>    while (elements.hasNext()) {<br>      Object adapter = getAdapter(elements.next(), IResource.class);<br>      if (c.isInstance(adapter)) {<br>        result.add(adapter);<br>      }<br>    }<br>   }<br>   if (result != null && !result.isEmpty()) {<br>   return (Object[])result.toArray((Object[])Array.newInstance(IResource.class, result.size()));<br>  }<br>  return (Object[])Array.newInstance(IResource.class, 0);<br>}</pre> | 
|  | <p>Example code for defining an IResource adaptable decorator:</p> | 
|  | <pre><extension<br>  point="org.eclipse.ui.decorators"><br>    <decorator objectClass="org.eclipse.core.resources.IResource"<br>     adaptable="true"<br>     label="%DecoratorStandard.name"<br>     state="false"<br>     lightweight= "true"<br>     quadrant = "BOTTOM_RIGHT"<br>     class="org.eclipse.team.internal.ccvs.ui.CVSLightweightDecorator"<br>     id="org.eclipse.team.cvs.ui.decorator"><br>    <description><br>      %DecoratorStandard.desc<br>    </description><br>  </decorator><br></extension></pre> | 
|  | <h2>Complaint 2: Decorators</h2> | 
|  | <p>When the CVS decorator decorates a logical container in a view, the | 
|  | desire is to decorate parents with the dirty indicator if one or more | 
|  | of their logical children are dirty. To do this properly, the decorator | 
|  | would need to query the dirty status of each of the logical children of | 
|  | the container. This can be a costly operation as each child may itself | 
|  | be a logical container. We have optimized the dirty decoration by | 
|  | caching folder dirty states. This optimization becomes far more | 
|  | complicated with logical models where the caching must be based on this | 
|  | alternate model (i.e. the state must be cached for each model).</p> | 
|  | <p> In addition, often decorators rely on IResource change events | 
|  | to re-calculate some new state. In the case of a logical elements | 
|  | representing several physical resources there is no easy way of | 
|  | associated a IResource change event to its files and the actual logical | 
|  | element.</p> | 
|  | <h2>Complaint 3: Presentation of mixed logical models<br> | 
|  | </h2> | 
|  | <p>It would be nice to see the Java logical view in the Synchronize | 
|  | view, in the navigator, or in dialogs contributed by other plug-ins | 
|  | besides JDT. However, the entries in these views | 
|  | may not be IResources so an IResource independent mapping mechanism | 
|  | would be required. A workaround for this problem is demonstrated by the | 
|  | Search plug-in which allows for plug-ins to integrate with other tools | 
|  | by contributing domain specific pages. JDT contributes a JDT search | 
|  | page to the view and shows logical Java elements. This solution however | 
|  | doesn't allow showing mixed logical models in the same widget, which is | 
|  | required in the Synchronize View and Navigator.<br> | 
|  | </p> | 
|  | Also if an action prompts the user, for example to add resources to | 
|  | CVS, what icons and labels are used in the dialog? It would be nice to | 
|  | show those that are most familiar to the user. <br> | 
|  | <br> | 
|  | There are two levels of logical model presentation:<br> | 
|  | <ul> | 
|  | <li>Need for full access to a logical model that would allow building | 
|  | a dynamic UI. This would include mapping from an IResource to a logical | 
|  | element.<br> | 
|  | </li> | 
|  | </ul> | 
|  | <ul> | 
|  | <li>Need name and icon for a logical element to display in simple | 
|  | dialogs.<br> | 
|  | </li> | 
|  | </ul> | 
|  | <h2>Complaint 4: Change Sets</h2> | 
|  | <p>Consider a user's action as a logical change, for example, the user | 
|  | renames a class using the JDT refactoring action. In the user's mind he | 
|  | 'renamed a class' and as a result there has been many other file | 
|  | changes. Currently there is not way of capturing these logical actions | 
|  | and associating the set of affected resources. This problem manifests | 
|  | itself more in tools where almost every change to the model has side | 
|  | effects.</p> | 
|  | <h2>Complaint 5: Participating in operations</h2> | 
|  | Some logical models may want to participate and even restrict the kinds | 
|  | of operations are | 
|  | allowed on theirs files. For example, if a logical element is composed | 
|  | of three files, the users should not be allowed to move, or delete them | 
|  | individually. In essence, a way of vetoing the move/rename, copy, or | 
|  | delete would be useful to ensure a coherant logical model.<br> | 
|  | <h2>Complaint 6: IResource based views in the IDE</h2> | 
|  | There are several views in the workbench IDE that could be used by | 
|  | logical models but are currently too tied to resources. For example, | 
|  | the problems and tasks views have a resource column and works uniquely | 
|  | on IResource markers. This means that if a logical model provides | 
|  | problems and tasks the problems and tasks views cannot be used to show | 
|  | the logical element instead of the file.<br> | 
|  | <h2>Complaint 7: Merging can't consider all files related to a logical | 
|  | element</h2> | 
|  | When merging a logical element the repository may find a conflict in | 
|  | one of the files that is part of the logical element. The repository | 
|  | tool will typically fetch the revisions for the conflicting file so | 
|  | that a comparison can be shown to the user. But since the repository | 
|  | tool doesn't know that other files are part of the logical resource, | 
|  | the comparison shown to the user doesn't have access to the correct | 
|  | revisions of the other files. This is a problem because it then becomes | 
|  | impossible to implement a comparison that has access to all the | 
|  | revisions of the logical element's files.<br> | 
|  | <h1>Discussion</h1> | 
|  | <p>The above complaints form the community hint at a missing feature in | 
|  | the Eclipse platform: there is a lack of a data modeling framework that | 
|  | would allow information to be modelled independently from their binary | 
|  | and storage locations. A common discussion in the community is the idea | 
|  | that the resources plug-in should be generalized to become this generic | 
|  | model, but in reality it wasn't designed as such and although it | 
|  | contains common model services such as eventing and threading, it was | 
|  | explicitly designed to model the file system. Changes to the resources | 
|  | plug-in would be a major breaking API change and not acceptable to the | 
|  | community. <br> | 
|  | </p> | 
|  | <p>There are however some alternatives. First, it is possible to solve | 
|  | some of the above complaints without introducing a full featured data | 
|  | model framework. Let's start by grouping the complaints:<br> | 
|  | </p> | 
|  | <span style="font-weight: bold;">Adaptables:<br> | 
|  | </span>Complaint 1: Not very adaptable<br> | 
|  | Complaint 2: Decorators<br> | 
|  | Complaint 7: Merging can't consider files related to a logical element<br> | 
|  | <p><span style="font-weight: bold;">Presentation of logical models:</span><br> | 
|  | Complaint 6: IResource based views in the IDE<br> | 
|  | Complaint 3: Presentation of mixed logical models<br> | 
|  | </p> | 
|  | <p><span style="font-weight: bold;">Logical Model Operations:</span><br> | 
|  | Complaint 4: Change Sets<br> | 
|  | Complaint 5: Participating in operations<br> | 
|  | </p> | 
|  | <h1>Possible Solution Approaches For Adaptables<br> | 
|  | </h1> | 
|  | <p>URL diagram<br> | 
|  | Example logical model provider code<br> | 
|  | Example repository provider actions/objectContribution<br> | 
|  | Example merge case<br> | 
|  | Example decorator<br> | 
|  | Example model context<br> | 
|  | </p> | 
|  | <p>======<br> | 
|  | </p> | 
|  | <p>There are basically two approaches to solving the problems discussed | 
|  | above:</p> | 
|  | <ul> | 
|  | <li>A logical model API that can be used by clients (such as | 
|  | repository providers) in order to determine what physical resources | 
|  | constitute model elements.</li> | 
|  | <li>A repository provider API that would allow model providers to | 
|  | perform repository operations on their constituant resources.</li> | 
|  | </ul> | 
|  | <p>At the present time, the second approach, by itself, is not viable | 
|  | due to its complexity. There is a JSR (JSR 147) that defines such an | 
|  | ineterface but it is not yet finalized and there is not timetable for | 
|  | when it will be. However, to do the first approach properly will | 
|  | require some repository provider API. This is discussed in the | 
|  | following section which propese a solution.</p> | 
|  | <h2> Logical Model Traversal API</h2> | 
|  | <p>One possible solution is to introduce a logical model element API | 
|  | that can be the basis for integration between plugins. This solution | 
|  | attempts to solve the most common uses described in <a href="#table1">Table1</a>, | 
|  | namely examples <a href="#1a">1a</a>, <a href="1b">1b</a> and <a | 
|  | href="3a">3a</a>. The <a | 
|  | href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/navigator-proposal/general_purpose_navigator_proposal.html">generic | 
|  | navigator</a> plan item should address the <a href="2b">2b</a> and <a | 
|  | href="3b">3b</a> examples by providing extensions that would allow a | 
|  | logical model to be available to other plugins for display purposes. | 
|  | Finally, <a href="2a">2a</a> is currently solved with the existing <code>IResource</code> | 
|  | adapter mechanism.</p> | 
|  | <p>Naturally another possible solution would be to change <code>IResource</code> | 
|  | to not be analogous to file system resources. However this scope of | 
|  | change is beyond the 3.0 timeframe and would cause, in my opinion, | 
|  | non-justifiable breaking changes to all plugins.</p> | 
|  | <h3>IlModelElement</h3> | 
|  | <p>This solution involves adding an interface to the Resources plugin | 
|  | that maps logical elements to physical ones. The interface is purposely | 
|  | simple with logical model manipulations ommitted. A client can't use | 
|  | this interface to display logical models or gain any interesting | 
|  | additional knowledge about it. In fact, the only way that a plugin will | 
|  | be able to gain access to the model for those purposes, would be via | 
|  | the navigator extensions proposed in the <a | 
|  | href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/navigator-proposal/general_purpose_navigator_proposal.html">generic | 
|  | nagivator</a> plan item.</p> | 
|  | <p>Current plugins that add object contributions to <code>IResource</code> | 
|  | (CVS, Search, Compare) would have to also add them to <code>IModelElement</code> | 
|  | and honour the biddings provided by the logical resource. Moreover, the | 
|  | plugins that adapted to <code>IResource</code> to these object | 
|  | contributions shown in the context menu should no longer adapt the <code>IResource</code> | 
|  | and instead implement <code>IModelElement</code> (this could be | 
|  | simplified by adding a tag to the objectConribution XML that indicates | 
|  | that it can be used with <code>IResource</code> or <code>IModelElement</code>).</p> | 
|  | <blockquote> | 
|  | <pre>/**<br> * This interface defines an element of an application that models the<br> * data/processes of a particular problem domain. This purpose of this interface<br> * is to support the transformation of the application model into its underlying<br> * file system resources for the purposes of reconciling the model with versions<br> * of the model stored in a repository. Hence, this interface provides the<br> * bridge between a logical element and the physical resource(s) into which it<br> * is stored but does not provide more comprehensive model access or<br> * manipulations.<br> * <br> * @see IResource<br> */<br>public interface IModelElement {<br>     <br>    /**<br>     * Returns the project which contains this model element. This is a resource<br>     * handle operation; neither the element nor the resulting project need<br>     * exist. Model elements may not span multiple projects. In other words, all<br>     * physical resources that constitute a logical resource are located in the<br>     * same project.<br>     * <br>     * @return the project handle<br>     */<br>    public IProject getProject();<br>     <br>    /**<br>     * Returns one or more traversals that can be used to access all the<br>     * physical resources that constitute the logical resource. A traversal is<br>     * simply a set of resources and the depth to which they are to be<br>     * traversed. This method returns an array of traversals in order to provide<br>     * flexibility in describing the traversals that constitute a model element.<br>     * A depth is included to allow the clients of this interface (most likely<br>     * repository providers) an opportunity to optimize the operation and also<br>     * ensure that resources that were or have become members of the model<br>     * element are included in the operation.<br>     * <br>     * Implementors of this interface should ensure, as much as possible, that<br>     * all resources that are or may be members of the model element are<br>     * included. For instance, a model element should return the same list of<br>     * resources regardless of the existance of the files on the file system.<br>     * For example, if a logical resource called "form" maps to "/p1/form.xml"<br>     * and "/p1/form.java" then whether form.xml or form.java existed, they<br>     * should be returned by this method.<br>     * <br>     * In some cases, it may not be possible for a model element to know all the<br>     * resources that may consitite the element without accessing the state of<br>     * the model element in another location (e.g. a repository). This method is<br>     * provided with a context which, when provided, gives access to<br>     * the members of correcponding remote containers and the contenst of<br>     * corresponding remote files. This gives the model element the opportunity<br>     * to deduce what additional resources should be included in the traversal.<br>     * <br>     * @param context gives access to the state of<br>     *            remote resources that correspond to local resources for the<br>     *            purpose of determining traversals that adequately cover the<br>     *            model element resources given the state of the model element<br>     *            in another location. A null may be provided, in<br>     *            which case the implementor can assume that only the local<br>     *            resources are of interest to the client.<br>     * @param monitor a progress monitor<br>     * @return a set of traversals that cover the resources that constitute the<br>     *         model element<br>     */<br>    public ITraversal[] getTraversals(IModelContext context,<br>            IProgressMonitor monitor) throws CoreException;<br>}</pre> | 
|  | </blockquote> | 
|  | <h3>ITraversal</h3> | 
|  | <p>A logical model element can be made up of one or more traversals | 
|  | that define the physical resources that make up the model element. | 
|  | Traversals are used to allow the clients of the traversal to optimize | 
|  | their operations based on the depth of the resources being traversed.</p> | 
|  | <blockquote> | 
|  | <pre>/** <br> * A model element traversal is simply a set of resources and<br> * the depth to which each are to be traversed. A set of traversals<br> * is used to describe the resources that constitute a model element.<br> *<br> * @see org.eclipse.core.resources.IResource<br> * @see org.eclipse.core.resources.model.IModelElement<br> */<br>public interface ITraversal {<br>   <br>    /**<br>     * Returns the project which contains the resources that<br>     * make up this taversal.<br>     * <br>     * @return the project handle<br>     */<br>    public IProject getProject();<br>   <br>    /**<br>     * Returns the file system resource(s) for this traversal. <br>     * The returned resources must be contained within the same project <br>     * and need not exist in the local file system.<br>     * <br>     * The traversal of the returned resources should be done considering<br>     * the flag returned by getDepth. If a resource returned by a <br>     * traversal is a file, it should always be visited. If a resource of a traversal<br>     * is a folder then files contained in the folder can only be visited if the folder is<br>     * IResource.DEPTH_ONE or IResource.DEPTH_INFINITE. <br>     * Child folders should only be visited if the depth is IResource.DEPTH_INFINITE.<br>     */<br>    public IResource[] getResources();<br>    <br>    /**<br>     * Return the depth to which the resources should be traversed.<br>     * @return the depth to which the physical resources are to be traversed<br>     * (one of IResource.DEPTH_ZERO, IResource.DEPTH_ONE or IResource.DEPTH_INFINITE)<br>     */<br>    public int getDepth();<br>}</pre> | 
|  | </blockquote> | 
|  | <p>For some model elements, simple traversals can be used to describe | 
|  | the element. For instance, here is an example traversal that represents | 
|  | a Java package.</p> | 
|  | <blockquote> | 
|  | <pre>/**<br> * An example traversal for a Java package<br> */<br>public class JavaPackageTraversal implements ITraversal {<br>    IContainer javaPackage;<br>    public JavaPackageTraversal(IContainer javaPackage) {<br>        this.javaPackage = javaPackage;<br>    }<br>    public IProject getProject() {<br>        return javaPackage.getProject();<br>    }<br>    public IResource[] getResources() {<br>        return new IResource[] { javaPackage };<br>    }<br>    public int getDepth() {<br>        return IResource.DEPTH_ONE;<br>    }<br>}</pre> | 
|  | </blockquote> | 
|  | <p>The next example class shows a traversal for a fixed set of files. | 
|  | The chosen example is for the data files that define the properties of | 
|  | a plugin in Eclipse. The same files are always returned even if they | 
|  | don't exist locally. It is up to the client of the interface in this | 
|  | case to decide how to handle the files that don't exist locally. If the | 
|  | client is a repository and the operation is an update to fetch the | 
|  | latest contents from the server, then the repository provider would | 
|  | fetch the files from the server if they now esist there or ignore them | 
|  | if they don't exist either locally or remotely.</p> | 
|  | <blockquote> | 
|  | <pre>/**<br> * An example of a fixed traversal that always includes<br> * a certain set of files even if they don't exist <br> * locally<br> */<br>public class PluginDataTraversal implements ITraversal {<br>    IProject pluginProject;<br>    public PluginDataTraversal(IProject project) {<br>        this.pluginProject = project;<br>    }<br>    public IProject getProject() {<br>        return pluginProject;<br>    }<br>    public IResource[] getResources() {<br>        return new IResource[] {<br>                pluginProject.getFile(new Path("plugin.xml")),<br>                pluginProject.getFile(new Path("plugin.properties")),<br>                pluginProject.getFile(new Path("build.properties")),<br>                pluginProject.getFile(new Path("META-INF/MANIFEST.MF"))<br>        };<br>    }<br>    public int getDepth() {<br>        return IResource.DEPTH_ZERO;<br>    }<br>}</pre> | 
|  | </blockquote> | 
|  | <p> Assuming that the plugin data consists of the above mentioned files | 
|  | and the contents of the schema directory, the model element class for a | 
|  | plugin's data model could be the following:</p> | 
|  | <blockquote> | 
|  | <pre>/**<br> * A plugin model element<br> */<br>public class PluginModel implements IModelElement {<br>    IProject pluginProject;<br>    public IProject getProject() {<br>        return pluginProject;<br>    }<br>    public ITraversal[] getTraversals(ITraversalContext context,<br>            IProgressMonitor monitor) throws CoreException {<br>        return new ITraversal[] {<br>            new PluginDataTraversal(pluginProject),<br>            new ITraversal() {<br>                public IProject getProject() {<br>                    return pluginProject;<br>                }<br>                public IResource[] getResources() {<br>                    return new IResource[] {<br>                        pluginProject.getFolder("schema")<br>                    };<br>                }<br>                // Traverse the folder deeply to include all children<br>                public int getDepth() {<br>                    return IResource.DEPTH_INFINITE;<br>                }<br>            }<br>        };<br>    }<br>}</pre> | 
|  | </blockquote> | 
|  | <h3>IModelContext</h3> | 
|  | <p>One of the advantages of a logical model traversal API is that it | 
|  | allows the repository provider to implement any operations they desire | 
|  | in terms of logical resources (e.g. update, commit, tag, dirty | 
|  | decoration, etc.). However, the context of the operation may imply that | 
|  | resources that don't exist locally should be included in the operation. | 
|  | This is not a problem for some logical models. For instance, a java | 
|  | package is a container visited to a depth of one. Also, the plugin | 
|  | example knows all the files that vould potentially be involved, even if | 
|  | they don't exist locally. Given this, a repository provider can easily | 
|  | determine that outgoing deletions should be included when committing or | 
|  | that incoming additions should be included when updating.</p> | 
|  | <p>However, properly determining the set of traversals that adequately | 
|  | cover a model element gets more complicated if the resources that | 
|  | constitute the element depend of the contents of a manifest file (or | 
|  | some other similar mechanism) and may change over time. In this case, | 
|  | it is possible that the model element could access the contents of the | 
|  | manifest file as contained in the remote location. Given this ability, | 
|  | the model element provider is provided with enough context about the | 
|  | operation to the logical model element so a set of traversal can be | 
|  | returned that adequately cover all resources that constitute the model | 
|  | element. </p> | 
|  | <p>This has led to the definition of the following <code>IModelContext</code> | 
|  | interface. </p> | 
|  | <blockquote> | 
|  | <pre>/**<br> * A model context provides a model element with a view of the remote state<br> * of a local resource as it relates to a repository operation that is in<br> * progress. A repository provider can pass an instance of this interface to a<br> * model element when obtaining a set of traversals for a model element. This<br> * allows the model element to query the remote state of a resource in order to<br> * determine if there are resources that exist remotely but do not exist locally<br> * that should be included in the traversal.<br> */<br>public interface IModelContext {<br> <br>    /**<br>     * Return whether the contents of the corresponding remote differs from the<br>     * content of the local file. This can be used by clients to determine if<br>     * they nee to fetch the remote contents in order to determine if the<br>     * resources that constitute the model element are different in another<br>     * location.<br>     * <br>     * @param file the local file<br>     * @param monitor a progress monitor<br>     * @return whether the contents of the corresponding remote differs from the<br>     *         content of the local file<br>     * @throws CoreException if this method fails. Reasons include:<br>     *           - The corresponding remote resource does not exist (status<br>     *             code will be IResourceStatus.REMOTE_DOES_NOT_EXIST).<br>     *           - The corresponding remote resource is not a container<br>     *             (status code will be IResourceStatus.REMOTE_WRONG_TYPE).<br>     *           - The server communications failed (status code will be<br>     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).<br>     */<br>    public boolean contentDiffers(IFile file, IProgressMonitor monitor)<br>            throws CoreException;<br> <br>    /**<br>     * Returns an instance of IStorage in order to allow the<br>     * caller to access the contents of the remote that corresponds to the given<br>     * local resource. The provided local file handle need not exist locally. A<br>     * exception is thrown if the corresponding remote resource does not exist<br>     * or is not a file.<br>     * <br>     * This method may be long running as a server may need to be contacted to<br>     * obtain the contents of the file.<br>     * <br>     * @param file the local file<br>     * @param monitor a progress monitor<br>     * @return a storage that provides access to the contents of the local<br>     *         resource's corresponding remote resource<br>     * @throws CoreException if this method fails. Reasons include:<br>     *           - The corresponding remote resource does not exist (status<br>     *             code will beIResourceStatus.REMOTE_DOES_NOT_EXIST).<br>     *           - The corresponding remote resource is not a file (status<br>     *             code will be IResourceStatus.REMOTE_WRONG_TYPE).<br>     *           - The server communications failed (status code will be<br>     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).<br>     */<br>    public IStorage fetchContents(IFile file, IProgressMonitor monitor)<br>            throws CoreException;<br><br>    /**<br>     * Returns the list of member resources whose corresponding remote resources<br>     * are members of the corresponding remote resource of the given local<br>     * container. The container need not exist locally and the result may<br>     * include entries that do not exist locally and may not include all local<br>     * children. An empty list is returned if the remote resource which<br>     * corresponds to the container is empty. An exception is thrown if the<br>     * corresponding remote does not exist or is not capable of having members.<br>     * <br>     * This method may be long running as a server may need to be contacted to<br>     * obtain the members of the containers corresponding remote resource.<br>     * <br>     * @param container the local container<br>     * @param monitor a progress monitor<br>     * @return a list of member resources whose corresponding remote resources<br>     *         are members of the remote counterpart of the given container<br>     * @throws CoreException if this method fails. Reasons include:       <br>     *           - The corresponding remote resource does not exist (status<br>     *             code will be IResourceStatus.REMOTE_DOES_NOT_EXIST).<br>     *           - The corresponding remote resource is not a container<br>     *             (status code will be IResourceStatus.REMOTE_WRONG_TYPE).<br>     *           - The server communications failed (status code will be<br>     *             IResourceStatus.REMOTE_COMMUNICATION_FAILURE).<br>     */<br>    public IResource[] fetchMembers(IContainer container,<br>            IProgressMonitor monitor) throws CoreException;<br>}</pre> | 
|  | </blockquote> | 
|  | <p>Although this can be thought of as a repository provider API, it | 
|  | bypasses the complexity by allowing the repository provider to | 
|  | implement the interface in a maner specific to the operation being | 
|  | performed. For instance, for a commit, the repository provider would | 
|  | provide the contents of files that define the base of a manifest file. | 
|  | In other words, the contents of the file would match the contents | 
|  | before the user modified the model element. This would allow for the | 
|  | inclusion of any outgoing deletions. For an update, the repository | 
|  | provider would provide access to the contents of the file in the | 
|  | repository.</p> | 
|  | <h3>Issues</h3> | 
|  | <p>This section is devided into two sections. Client isses which | 
|  | indicate what isses the implementators of the above mentioned | 
|  | interfaces face, and Eclipse Platform issues that will need to be | 
|  | addressed when and if the solution is implemented.</p> | 
|  | <h4>Client Issues</h4> | 
|  | <p>There are uncertainties for this solution:</p> | 
|  | <ul> | 
|  | <li>Can all repository providers reasonably implement the | 
|  | ITraversalContext for use by the model elements</li> | 
|  | <li>Can the model elements implement the code that makes use of this | 
|  | context to determine what additional resources make up the model</li> | 
|  | </ul> | 
|  | <p>Either of these efforts may be non-trivial depending on the | 
|  | structure and functionality of the repository provider's or model | 
|  | provider's Eclispse intergration. </p> | 
|  | <h4>Eclipse Platform Issues</h4> | 
|  | <p>The following issues would need to be addressed for this solutions</p> | 
|  | <ol> | 
|  | <li>ObjectContributions have to be duplicated in the plugins that | 
|  | would like to provide both contributions for <code>IResource</code> | 
|  | and <code>ILogicalResource</code>. </li> | 
|  | <ul> | 
|  | <li>This could be simplified by adding support to tag an | 
|  | objectContribution for use with both interfaces</li> | 
|  | </ul> | 
|  | <li>Logical classes (e.g. java model, UML) have to implement the | 
|  | interface instead of adapting to it. This is a limitation of the | 
|  | current objectContribution story in the workbench. </li> | 
|  | <ul> | 
|  | <li>Again, this could be circumvented with support in the UI that | 
|  | does the same magic for <code>ILogicalResource</code> that is done for | 
|  | <code>IResource</code></li> | 
|  | </ul> | 
|  | <li>Plugins that add object contributions will have to modify their | 
|  | actions to handle logical resources. There should be some standard UI | 
|  | components for showing the mappings. For instance you could show the | 
|  | logical model at the top and in a details part the physical | 
|  | files/folders that will be affected by the operation.</li> | 
|  | </ol> | 
|  | </body> | 
|  | </html> |