| <title>Support Logical Resources</title> |
| <table border="0" cellspacing="5" cellpadding="2" width="100%"> |
| |
| <tr> |
| |
| <td align="left" valign="top" bgcolor="#0080c0"> <b><font color="#ffffff" face="Arial,Helvetica"> |
| Eclipse 3.1 - Plan item</font></b> </td> |
| </tr> |
| </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-team-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: August 12th, 2004</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 the logical model. What Eclipse really doesn't |
| support is integrating tools at the logical model level. It's simple: to integrate |
| two plugins in Eclipse either one plugin must know about the other (through |
| a plugin reference), or both plugins must 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, consider the Eclipse SDK itself. |
| In the SDK, the Resources plugin acts as the common plugin that other plugins |
| use as a point of intergration (e.g. Team, Search, Compare, JDT). Thus, the |
| common model between these plugins is the resource model defined by the Resources |
| plugin.This model is basically the same as the physical file system model and |
| does not provide integration for any other logical models.</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 2.1. </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</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 width="100%" border="1"> |
| <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> |
| </table> |
| <h2>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> |
| <objectContribution> |
| </extension> |
| </pre> |
| <p>Example code run in the commit action to calculate the resources to commit:</p> |
| <pre>public static Object[] getSelectedAdaptables(ISelection selection) { |
| ArrayList result = null; |
| if (!selection.isEmpty()) { |
| result = new ArrayList(); |
| Iterator elements = ((IStructuredSelection) selection).iterator(); |
| while (elements.hasNext()) { |
| Object adapter = getAdapter(elements.next(), IResource.class); |
| if (c.isInstance(adapter)) { |
| result.add(adapter); |
| } |
| } |
| } |
| if (result != null && !result.isEmpty()) { |
| return (Object[])result.toArray((Object[])Array.newInstance(IResource.class, result.size())); |
| } |
| return (Object[])Array.newInstance(IResource.class, 0); |
| }</pre> |
| <p>Example code for defining an IResource adaptable decorator:</p> |
| <pre><extension |
| point="org.eclipse.ui.decorators"> |
| <decorator objectClass="org.eclipse.core.resources.IResource" |
| adaptable="true" |
| label="%DecoratorStandard.name" |
| state="false" |
| lightweight= "true" |
| quadrant = "BOTTOM_RIGHT" |
| class="org.eclipse.team.internal.ccvs.ui.CVSLightweightDecorator" |
| id="org.eclipse.team.cvs.ui.decorator"> |
| <description> |
| %DecoratorStandard.desc |
| </description> |
| </decorator> |
| </extension></pre> |
| <h2> 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>Views</h2> |
| <p>It would be nice to see the Java logical view in the Synchronize view or the |
| CVS Repositories View. However, the entries in these views may not be IResources |
| so an IResource independent mapping mechanism would be required. This could |
| be a considerable amount if work for anyone providing a logical model. This |
| problem is partly being addressed by the introduction of customizable content |
| providers as described in 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> item.</p> |
| <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. </p> |
| <h2>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>File based tools</h2> |
| <p>Some tools that integrate into Eclipse are file based and don't use IResources. |
| And thus wouldn't be able to operation logical elements.</p> |
| <h1>Possible Solution Approaches</h1> |
| <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> |
| <h1>Proposed Solution</h1> |
| <p>In this section, we propose a soluton that is centered on API for traversing |
| logical model elements with a minimal amout of repository provider API.</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>/** |
| * This interface defines an element of an application that models the |
| * data/processes of a particular problem domain. This purpose of this interface |
| * is to support the transformation of the application model into its underlying |
| * file system resources for the purposes of reconciling the model with versions |
| * of the model stored in a repository. Hence, this interface provides the |
| * bridge between a logical element and the physical resource(s) into which it |
| * is stored but does not provide more comprehensive model access or |
| * manipulations. |
| * |
| * @see IResource |
| */ |
| public interface IModelElement { |
| |
| /** |
| * Returns the project which contains this model element. This is a resource |
| * handle operation; neither the element nor the resulting project need |
| * exist. Model elements may not span multiple projects. In other words, all |
| * physical resources that constitute a logical resource are located in the |
| * same project. |
| * |
| * @return the project handle |
| */ |
| public IProject getProject(); |
| |
| /** |
| * Returns one or more traversals that can be used to access all the |
| * physical resources that constitute the logical resource. A traversal is |
| * simply a set of resources and the depth to which they are to be |
| * traversed. This method returns an array of traversals in order to provide |
| * flexibility in describing the traversals that constitute a model element. |
| * A depth is included to allow the clients of this interface (most likely |
| * repository providers) an opportunity to optimize the operation and also |
| * ensure that resources that were or have become members of the model |
| * element are included in the operation. |
| * |
| * Implementors of this interface should ensure, as much as possible, that |
| * all resources that are or may be members of the model element are |
| * included. For instance, a model element should return the same list of |
| * resources regardless of the existance of the files on the file system. |
| * For example, if a logical resource called "form" maps to "/p1/form.xml" |
| * and "/p1/form.java" then whether form.xml or form.java existed, they |
| * should be returned by this method. |
| * |
| * In some cases, it may not be possible for a model element to know all the |
| * resources that may consitite the element without accessing the state of |
| * the model element in another location (e.g. a repository). This method is |
| * provided with a context which, when provided, gives access to |
| * the members of correcponding remote containers and the contenst of |
| * corresponding remote files. This gives the model element the opportunity |
| * to deduce what additional resources should be included in the traversal. |
| * |
| * @param context gives access to the state of |
| * remote resources that correspond to local resources for the |
| * purpose of determining traversals that adequately cover the |
| * model element resources given the state of the model element |
| * in another location. A null may be provided, in |
| * which case the implementor can assume that only the local |
| * resources are of interest to the client. |
| * @param monitor a progress monitor |
| * @return a set of traversals that cover the resources that constitute the |
| * model element |
| */ |
| public ITraversal[] getTraversals(IModelContext context, |
| IProgressMonitor monitor) throws CoreException; |
| }</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>/** |
| * A model element traversal is simply a set of resources and |
| * the depth to which each are to be traversed. A set of traversals |
| * is used to describe the resources that constitute a model element. |
| * |
| * @see org.eclipse.core.resources.IResource |
| * @see org.eclipse.core.resources.model.IModelElement |
| */ |
| public interface ITraversal { |
| |
| /** |
| * Returns the project which contains the resources that |
| * make up this taversal. |
| * |
| * @return the project handle |
| */ |
| public IProject getProject(); |
| |
| /** |
| * Returns the file system resource(s) for this traversal. |
| * The returned resources must be contained within the same project |
| * and need not exist in the local file system. |
| * |
| * The traversal of the returned resources should be done considering |
| * the flag returned by getDepth. If a resource returned by a |
| * traversal is a file, it should always be visited. If a resource of a traversal |
| * is a folder then files contained in the folder can only be visited if the folder is |
| * IResource.DEPTH_ONE or IResource.DEPTH_INFINITE. |
| * Child folders should only be visited if the depth is IResource.DEPTH_INFINITE. |
| */ |
| public IResource[] getResources(); |
| |
| /** |
| * Return the depth to which the resources should be traversed. |
| * @return the depth to which the physical resources are to be traversed |
| * (one of IResource.DEPTH_ZERO, IResource.DEPTH_ONE or IResource.DEPTH_INFINITE) |
| */ |
| public int getDepth(); |
| }</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>/** |
| * An example traversal for a Java package |
| */ |
| public class JavaPackageTraversal implements ITraversal { |
| IContainer javaPackage; |
| public JavaPackageTraversal(IContainer javaPackage) { |
| this.javaPackage = javaPackage; |
| } |
| public IProject getProject() { |
| return javaPackage.getProject(); |
| } |
| public IResource[] getResources() { |
| return new IResource[] { javaPackage }; |
| } |
| public int getDepth() { |
| return IResource.DEPTH_ONE; |
| } |
| }</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 mdel element class for a plugin's data |
| model could be the following:</p> |
| <blockquote> |
| <pre>/** |
| * A plugin model element |
| */ |
| public class PluginModel implements IModelElement { |
| IProject pluginProject; |
| public IProject getProject() { |
| return pluginProject; |
| } |
| public ITraversal[] getTraversals(ITraversalContext context, |
| IProgressMonitor monitor) throws CoreException { |
| return new ITraversal[] { |
| new PluginDataTraversal(pluginProject), |
| new ITraversal() { |
| public IProject getProject() { |
| return pluginProject; |
| } |
| public IResource[] getResources() { |
| return new IResource[] { |
| pluginProject.getFolder("schema") |
| }; |
| } |
| // Traverse the folder deeply to include all children |
| public int getDepth() { |
| return IResource.DEPTH_INFINITE; |
| } |
| } |
| }; |
| } |
| }</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>/** |
| * A model context provides a model element with a view of the remote state |
| * of a local resource as it relates to a repository operation that is in |
| * progress. A repository provider can pass an instance of this interface to a |
| * model element when obtaining a set of traversals for a model element. This |
| * allows the model element to query the remote state of a resource in order to |
| * determine if there are resources that exist remotely but do not exist locally |
| * that should be included in the traversal. |
| */ |
| public interface IModelContext { |
| |
| /** |
| * Return whether the contents of the corresponding remote differs from the |
| * content of the local file. This can be used by clients to determine if |
| * they nee to fetch the remote contents in order to determine if the |
| * resources that constitute the model element are different in another |
| * location. |
| * |
| * @param file the local file |
| * @param monitor a progress monitor |
| * @return whether the contents of the corresponding remote differs from the |
| * content of the local file |
| * @throws CoreException if this method fails. Reasons include: |
| * - The corresponding remote resource does not exist (status |
| * code will be IResourceStatus.REMOTE_DOES_NOT_EXIST). |
| * - The corresponding remote resource is not a container |
| * (status code will be IResourceStatus.REMOTE_WRONG_TYPE). |
| * - The server communications failed (status code will be |
| * IResourceStatus.REMOTE_COMMUNICATION_FAILURE). |
| */ |
| public boolean contentDiffers(IFile file, IProgressMonitor monitor) |
| throws CoreException; |
| |
| /** |
| * Returns an instance of IStorage in order to allow the |
| * caller to access the contents of the remote that corresponds to the given |
| * local resource. The provided local file handle need not exist locally. A |
| * exception is thrown if the corresponding remote resource does not exist |
| * or is not a file. |
| * |
| * This method may be long running as a server may need to be contacted to |
| * obtain the contents of the file. |
| * |
| * @param file the local file |
| * @param monitor a progress monitor |
| * @return a storage that provides access to the contents of the local |
| * resource's corresponding remote resource |
| * @throws CoreException if this method fails. Reasons include: |
| * - The corresponding remote resource does not exist (status |
| * code will beIResourceStatus.REMOTE_DOES_NOT_EXIST). |
| * - The corresponding remote resource is not a file (status |
| * code will be IResourceStatus.REMOTE_WRONG_TYPE). |
| * - The server communications failed (status code will be |
| * IResourceStatus.REMOTE_COMMUNICATION_FAILURE). |
| */ |
| public IStorage fetchContents(IFile file, IProgressMonitor monitor) |
| throws CoreException; |
| |
| /** |
| * Returns the list of member resources whose corresponding remote resources |
| * are members of the corresponding remote resource of the given local |
| * container. The container need not exist locally and the result may |
| * include entries that do not exist locally and may not include all local |
| * children. An empty list is returned if the remote resource which |
| * corresponds to the container is empty. An exception is thrown if the |
| * corresponding remote does not exist or is not capable of having members. |
| * |
| * This method may be long running as a server may need to be contacted to |
| * obtain the members of the containers corresponding remote resource. |
| * |
| * @param container the local container |
| * @param monitor a progress monitor |
| * @return a list of member resources whose corresponding remote resources |
| * are members of the remote counterpart of the given container |
| * @throws CoreException if this method fails. Reasons include: |
| * - The corresponding remote resource does not exist (status |
| * code will be IResourceStatus.REMOTE_DOES_NOT_EXIST). |
| * - The corresponding remote resource is not a container |
| * (status code will be IResourceStatus.REMOTE_WRONG_TYPE). |
| * - The server communications failed (status code will be |
| * IResourceStatus.REMOTE_COMMUNICATION_FAILURE). |
| */ |
| public IResource[] fetchMembers(IContainer container, |
| IProgressMonitor monitor) throws CoreException; |
| }</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> |
| <h2>Synchronizing, Comparing and Merging Model Elements</h2> |
| <p>One aspect that is not covered by logic element traversal but is related to |
| repository operations is the ability to synchronize, compare and merge model |
| elements at the model level as opposed to the file system resource level.</p> |
| <h3>Synchronize View</h3> |
| <p>The Synchronize view in Eclipse 3.0 supports an infrastructure for choosing |
| the presentation that is used by the view. However, the types of presentations |
| are limited and are resource based. It is possible, however, to allow the presentation |
| to be determined by the provider of a logical model. Here is a summary of what |
| this would involve:</p> |
| <ul> |
| <li>The Synchronize view presentation is determined using a content provider |
| that is defined by the implementor of the synchronize participant. When synchronizing |
| a logical model element, it would be possible to obtain the content provider |
| to be used from the logical model provider. This would require that all the |
| model elements involved in a sychronize belong to the same model provider |
| (this is probably a requirement we would want anyway).</li> |
| <li>The elements in the view would be special model element which we will refer |
| to as synchronize model element (or sync element for short). This element |
| would provide access to an instance of <code>IModelElement</code> that could |
| be used by the repository provider to determine the state of the sync element |
| and the resources to be considered when performing an operation. The repository |
| provider would make use of an <code>IModelContext</code> to obtain the remote |
| version of the model element (and a different context to determine the base |
| for a 3-way compare).</li> |
| </ul> |
| <p>This is fairly straightforward given the current structure of the synchronze |
| view (and assuming that the logical model traversal API is in place).</p> |
| <h3>Compare/Merge Editor</h3> |
| <p>Just as the logical model provider would be responsible for providing the content |
| provider to be used in the Synchronize view, they would also be reponsible for |
| providing a compare editor that is suitable for comparing and merging a model |
| elements. Input to the compare editor would be the model elements involved and |
| the model contexts for the remote and the base (for a 3-way compare). The logical |
| model provider would be responsible fro generating, comparing and merging the |
| model changes into the local copy of the model.</p> |
| <p>Another input to the compare editor could be a set of actions so that , for |
| instance, during an update that involves conflicting changes, a "done" |
| action could be provided by the repository provider to indicate that a merge |
| is complete and the local resources should no longer be considered conflicts.</p> |
| <h3>Issues</h3> |
| <p>Here are some of the issues for the synchronize view and compare editors:</p> |
| <ul> |
| <li>Again, the main issue here is the ability for the repository provider to |
| provide the context for the base and remote model elements and for the model |
| provider to use this information to generate the proper traversals. If eitehr |
| of these is not provided, then the synchronize view and compare would need |
| to fall back to a straight resource-based presentation.</li> |
| <li>Most of the work in this proposal falls on the logical model providers.We |
| would want to provide as much support as possible in the Synchronize and Compare |
| frameworks. We will also provide whatever support possible to repository providers |
| although this will probably be most documentation and examples.</li> |
| <li>It may be desirable to show mixed presentations in the synchronize view. |
| For instance, the user may wish the see there logical model vie separated |
| by change set. This is a desirable feature but is not a necessity.</li> |
| </ul> |
| </BODY> |
| </html> |