| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| <head> |
| <title>Logical Model Integration in Eclipse</title> |
| <meta http-equiv="Content-Type" |
| content="text/html; charset=iso-8859-1"> |
| </head> |
| <body> |
| <h1>Proposed Support for Logical Model Integration in Eclipse</h1> |
| <p>Version: 0.3</p> |
| <p>This document contains several sections which describe various aspects of the |
| proposed or potential support for improved logical model integration in the |
| Eclipse Platform (bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=37723">37723</a>). |
| The requirements document can be found <a href="../../source/logical-support.doc">here</a> |
| and a description of the initial worked performed in 3.1 is <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-vcm-home/docs/online/team3.1/logical-physical-mappings.html">here</a>. |
| The following list summarizes each item and provides a brief description of |
| the impact on the Eclipse Platform and it's clients.</p> |
| <ul> |
| <li><a href="#ProblemsView">Problems View</a>: The Problems view needs to be |
| more "logical model" aware. We are still planning on using IResource |
| based markers as the means of managing problems. The logical model integration |
| would affect how problems are presented and filtered. Some example features |
| being considered are: <br> |
| <ul> |
| <li>the ability to filter by selection of model elements that map to resources |
| via the ResourceMapping API</li> |
| <li>generic columns (e.g. Description, Resource, Path, Location) whose displayed |
| values would be model appropriate.</li> |
| <li>Problem type specific affordances |
| <ul> |
| <li>properties view for problem-type specific fields</li> |
| <li>Show In model view support</li> |
| <li>custom filters</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <p> The bulk of the work for this item is in the Problems view itself. Clients |
| would only need to do work if the current filtering was inadequate. The work |
| would involve defining model specific filters and properties display. For |
| JDT, work is probably not required as there is a strong enough relationship |
| between resources and java elements so model specific filters may not be required.</p> |
| <li><a href="#GenericNavigator">Common Navigator</a>: The Common Navigator is |
| being pushed down from WTP into the Platform. This should start happening |
| soon with the hope of having the initial contribution available for 3.2 M2. |
| The view allows model tooling to add a root node to the Navigator and control |
| what appears under that node. Client that wish to plug into the view will |
| need to provide a root element, content provider, label provider, sorter and |
| action set for inclusion in the navigator. Clients with existing Navigator |
| style views can decide whether to keep their view separate or integrate it |
| into the Common Navigator. For JDT, they will need to integrate with the view |
| to remain consistent with the Platform.<br> |
| <br> |
| </li> |
| <li><a href="#OperationParticipation">Maintaining Workspace Consistency</a>: |
| Eclipse has an operation mechanism in the LTK plugin which supports participation |
| in basic refactoring operations (delete, rename, etc). This is currently only |
| used to support participation in Java refactorings but it could also be used |
| for operations on other models. The work that would need to be done for this |
| is: <br> |
| <ul> |
| <li>Add support to retarget operations to the highest level model.</li> |
| <li>Describe how model tooling can make use of the LTK refactoring participant |
| support in order to allow dependant models to participate in refactorings.</li> |
| <li>Modifications may need to be made to the LTK framework itself to handle |
| the characteristics of multi-level models and possibly additional refactoring |
| operations.</li> |
| </ul> |
| <p>Support for retargetting would need to be added to the platform and to |
| any client that anticipates that higher level models could be built on top |
| of their model, including JDT. </p> |
| </li> |
| <li><a href="#ObjectContributionSupport">Team Operations on Model Elements</a>: |
| Provisional support for more than just a one-to-one mapping from resource |
| to model element was added in 3.1. The additional areas that need to be addressed |
| are: <br> |
| <ul> |
| <li>Supporting participation of higher level models on team operations performed |
| on lower level models. That is, a model element may consist of several |
| files that should always be operated on together. Hence an operation performed |
| in the Resource Navigator on one of these files should include all of |
| them.</li> |
| <li>Content providers can be used to make the view of a model differ from |
| the model structure. This means that team operations on the model elements |
| in these views will not match what the user sees. Addressing this issue |
| either requires restricting what content providers do in model views or |
| involving the content provider in the resource mapping determination process.</li> |
| </ul> |
| <p>The work items for this are: |
| <ul> |
| <li>A team participant extension point needs to be created.</li> |
| <li>Team providers need to consult the extension when performing operations |
| on resource mappings. Compare will also need to make use of this mechanism |
| for performing local history compare and replace operations.</li> |
| <li>Model tooling should participate in operations on appropriate elements |
| of lower level models.</li> |
| </ul> |
| <p>There is little work anticipated here for JDT since their model in similar |
| enough to the file model. Model tooling with models that hide the file structure |
| will need to provide a team participant.</p> |
| </li> |
| <li><a href="#DecoratorSupport">Team Decorator Support</a>: Team decorations |
| should appear on any model element on which team operations may be performed. |
| This requires the following: <br> |
| <ul> |
| <li>Improved adaptability of enablement rules for decorators. This has been |
| done and is available in 3.2 M1.</li> |
| <li>Change state determination for model elements contained in files. Model |
| tooling can decide at what depth they want to perform repository operations |
| in their models and need to provide change determination for sub-file |
| elements.</li> |
| <li>Label update propagation in hierarchical model views: This requires |
| change to the decorator mechanism and to views which decorate elements |
| (i.e. changes to the JFace viewers and custom model tooling viewers that |
| handle label updating in custom ways).</li> |
| </ul> |
| <p>JDT has a custom viewer that handles label updates so they will need to |
| adapt any new mechanism for performing label update propagation.</p> |
| </li> |
| <li><a href="#ModelLevelMerging">Model Level Merging</a>: Support for model |
| merges can be broken up into two features: <br> |
| <ul> |
| <li>Support for head-less merging: This will require additional API and |
| support in the Compare component and an extension point to allow model |
| tooling to plug in a head-less merger. </li> |
| <li>Support for manual merge: Compare will also need to provide API which |
| allows model tooling to plug in UI based merged tools that can operate |
| on their model elements. </li> |
| </ul> |
| <p>Compare already has the above mentioned support for models that have a |
| one-to-one mapping between files and model elements so only clients who |
| have more complicated mappings would need to provide this additional support. |
| For JDT, there should not be much work here since they already provide a |
| file-based content viewer. Compare will need to make use of any new API |
| in the local history operations.</p> |
| </li> |
| <li><a href="#DisplayingLogicalModels">Model Display in Team Operations</a>: |
| There are two types of displays that are relevant in team operations: <br> |
| <ul> |
| <li>A model element synchronization state view similar to that of the synchronize |
| view. Model tooling would need to build the model hierarchy they wish |
| to display in this view.</li> |
| <li>A model specific view that can be used in team operation dialogs. This |
| has a lot of similarities with the requirements of the Common Navigator.</li> |
| </ul> |
| <p>The bulk of the work for clients here will be providing the synchronization |
| view. This includes JDT as it would be beneficial to see a structure in |
| the synchronize view that matches what appears in the Packages Explorer.</p> |
| </li> |
| <li><a href="#Bootstrapping">Remote Discovery</a>: There are two aspects to |
| this: browsing models in the repository and transferring models to the local |
| workspace. The bulk of the work for this item would be for the repository |
| tooling as they would have to provide the remote browsing capabilities.The |
| model tooling will have to do some work but the amount will depend on how |
| the remote state of the model is represented.</li> |
| </ul> |
| <p>After presenting proposals for each of these area, we discuss the potential |
| role of <a href="#EMF">EMF</a> and present some generic <a href="#TeamScenarios">Team |
| Scenarios</a> that describe how the functionality we are proposing would play |
| out.</p> |
| <h2><a name="ProblemsView"></a>Problems View</h2> |
| <p>Making the problems view more logical model aware has been broken into several |
| pieces, as described in the following sections.</p> |
| <h3>Filtering</h3> |
| <p>How do we improve the usability of filters in the problems view. Work has started |
| on this is 3.2 and there are several bug reports on the issue (<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=108013">108013</a>, |
| <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=108015">108015</a>, <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=108016">108016</a>). |
| The basic ideas are: </p> |
| <ul> |
| <li>allow the user or a plugin to define filters that can be combined</li> |
| <li>provide a means of enabling filters quickly (i.e. without opening the filter |
| dialog).</li> |
| <li>filter based on model element selected and not just resource or resource |
| mapping (i.e. a file could contain several model objects and selecting one |
| of them should only shows markers associated with that particular element.</li> |
| </ul> |
| <p>An additional requirement identified by clients is the ability to filter on |
| model specific information. We will need to collect some concrete scenarios |
| on this to better understand the requirement.</p> |
| <h3>Properties</h3> |
| <p>Each problem type has different relevant properties. Java errors has a file |
| path and line number. Other models may have other ways of describing a problem |
| (e.g. a resource description and a field name). Ideally each problem would display |
| it's relevant properties. However, the Problems view often contains many different |
| types of problems, each of which may have different relevant properties. Table |
| widgets have a single set of columns, leading to the following possibilities:</p> |
| <ul> |
| <li>A generic set of properties that all problems have are displayed in the |
| table.</li> |
| <li>The table has columns for the relevant properties of all problem types it |
| contains and the columns are empty for problems that do not have that property. |
| This may be acceptable for a small number of types but becomes unmanageable |
| if there are a large number of types with different relevant properties.</li> |
| <li>The table is constrained to show only a single problem type at a time (or |
| a small number of different types to keep the number of columns reasonable).</li> |
| </ul> |
| <p>Given that users may want to see different problem types in the Problems view |
| at the same time, the most practical approach is to provide a generic set of |
| columns (e.g. Severity, Description, Element, Path, Location) and allow the |
| problem type to dictate what values appear in the columns.</p> |
| <h3>Problem Type Specific Behavior</h3> |
| <p>The Problems view currently supports custom Quick Fixes for a problem type. |
| Another useful feature would be the ability to navigate to model specific view. |
| There is currently a Show In Navigator which could be enhanced to support showing |
| the affected model element in a model view (e.g. Show in Packages Explorer for |
| Java problems).</p> |
| <h3>Perspective/Context/Activity</h3> |
| <p>If there was some way of determining what role the user was paying at a particular |
| time, it would be possible to tailor views to that particular task. Such information |
| could be used to enable particular Problems view filters.</p> |
| <h2><a name="GenericNavigator"></a>Common Navigator</h2> |
| <p>The Common Navigator is being pushed down from WTP into the Platform. The view |
| allows model tooling to add a root node to the Navigator and control what appears |
| under that node. Clients that wish to plug into the view will need to provide |
| a root element, content provider, label provider, sorter and action set for |
| inclusion in the navigator. Clients with existing Navigator style views can |
| decide whether to keep their view separate or integrate it into the Common Navigator. |
| For JDT, they will probably want to integrate with the view to remain consistent |
| with the Platform.</p> |
| <p>One aspect of the Common Navigator that is of particular interest to team operations |
| is the ability to obtain a content provider that can show a logical model in |
| a tree viewer. This would allow logical models to appear in team operation views |
| and dialogs. The Common Navigator proposal defines an extension that provides |
| this capability. The class for this extension is the <code>NavigatorContentExtension</code> |
| and it provides the following:</p> |
| <ul> |
| <li>A content provider the view can use to display the model tree</li> |
| <li>A label provider the view can use for getting the icon and text for individual |
| model elements</li> |
| <li>An action provider so the view can present model specific actions in appropriate |
| places (e.g. the context menu)</li> |
| <li>A comparator for sorting model elements</li> |
| </ul> |
| <p>For this API to be useable in Team operations, the <code>NavigatorContentExtension</code> |
| contributed by the model must have access to the context of the team operation. |
| Outside the context of a team operation, the content extension only has the |
| local workspace from which to build its model tree. However, within the context |
| of a team operation, there may be additional resources involved, specifically, |
| resources that exist remotely but not locally (i.e. outgoing deletions or incoming |
| additions). The model's content extension would need access to a team context |
| so that these additional resources could be considered when displaying the model. |
| </p> |
| <p>The following list summarizes the requirements that would be placed on a <code>NavigatorContentExtension</code> |
| when being used to display the model in a team context.</p> |
| <ul> |
| <li>the ability to show model elements that represent the remote state of a |
| model (e.g. incoming changes that exist remotely but not locally).</li> |
| <li>the ability to decorate model elements with there synchronization direction |
| (incoming, outgoing or conflicting) and change type (addition, deletion or |
| change). </li> |
| <li>the ability to filter the view based on repository provider state for the |
| underlying files (e.g. only show outgoing changes).</li> |
| </ul> |
| <p>Support for this can either be integrated with the Common Navigator API or |
| made available as Team specific API (see <a href="#DisplayingLogicalModels">Model |
| Display in Team Operations</a>). Our preference would be integrate the team |
| requirements with the Common Navigator requirements so that model providers |
| only need to implement one API. In the rest of this section we will address |
| the following two questions:</p> |
| <ul> |
| <li>How is the team context communication to a<code> NavigatorContentExtension</code>?</li> |
| <li>What does the team context look like?</li> |
| </ul> |
| <p>The next two sections propose answers to these questions.</p> |
| <h3>Configuring a NavigatorContentExtension with a Team Context</h3> |
| <p>In the Common Navigator API description that was available at the time of writing, |
| the <code>NavigatorContentExtension</code> is instantiated for each viewer and |
| has the ability to have state of the viewer available to it. In the context |
| of a team operation, the team provider would create the viewer that will be |
| used to display the model tree. It could also associate the team context with |
| the viewer so it was available to the context extension.</p> |
| <p>A team operation requires the ability to obtain a content provider that can |
| consider the team context when it builds a model tree. Since the tree is built |
| by the content provider, the following method to <code>NavigatorContentExtension</code> |
| will need to consult the viewer state to see if a team context is available.</p> |
| <blockquote> |
| <p><code>ITreeContentProvider getContentProvider()</code></p> |
| </blockquote> |
| <p>where <code>ISynchronizationContext</code> is the interface that defines the |
| team context. The model would be responsible for displaying a model tree that |
| included relevant model objects that may not exist remotely but as part of the |
| team operation.</p> |
| <p>In addition, the ability to decorate model elements with their team state is |
| required. Adding the following method to <code>NavigatorContentExtension</code> |
| would provide this capability:</p> |
| <blockquote> |
| <p><code>ICommonLabelDecorator getLabelDecorator()</code></p> |
| </blockquote> |
| <p>The provided decorator would need to consult the team context that is available |
| from the viewer state in order to determine the proper decorations for each |
| model element.</p> |
| <p>The other remaining requirement is filtering based on team state. Filtering |
| is not as well defined in the Common Navigator proposal but a similar approach |
| as described for the other two requirements could also be used to provide a |
| filter that filters on team state.</p> |
| <p>The above is more to provide an idea of what is required instead of the exact |
| solution. The final solution will depend on what the final shape of the Common |
| Navigator.</p> |
| <h3>The Team Context API</h3> |
| <p>The <code>ISynchronizationContext</code> API below could be used to provide |
| the team context to a model provider. It makes use of the following API pieces:</p> |
| <ul> |
| <li>A <code>SyncInfo</code> contains a description of the synchronization state |
| of a file system resource. The synchronization state includes a direction |
| (incoming, outgoing or conflicting) and change type (addition, deletion or |
| change). </li> |
| <li>The <code>SyncInfoTree</code> contains a description of all of the resources |
| that are out-of-sync. </li> |
| <li>The scope (<code>ISynchronizeScope</code>) defines the input used to scope |
| the synchronization. It has a set of root resources and a containment check |
| to define whether a resource that is a child of one of the roots is contained |
| in the scope. Particular subclasses may provide additional information (e.g. |
| the set of resource mappings that define the scope).</li> |
| </ul> |
| <p>The model provider can use this information to determine what model tree to |
| build, the synchronization state of model elements and what additional elements |
| need to be displayed.</p> |
| <pre>/** |
| * Allows a model provider to build a view of their model that includes |
| * synchronization information with a remote location (usually a repository). |
| * |
| * The scope of the context is defined when the context is created. The creator |
| * of the scope may affect changes on the scope which will result in property |
| * change events from the scope and may result in sync-info change events from |
| * the sync-info tree. Clients should note that it is possible that a change in |
| * the scope will result in new out-of-sync resources being covered by the scope |
| * but not result in a sync-info change event from the sync-info tree. This can |
| * occur because the set may already have contained the out-of-sync resource |
| * with the understanding that the client would have ignored it. Consequently, |
| * clients should listen to both sources in order to guarantee that they update |
| * any dependent state appropriately. |
| * |
| * This interface is not intended to be implemented by clients. |
| * |
| * @since 3.2 |
| */ |
| public interface ISynchronizationContext { |
| |
| /** |
| * Synchronization type constant that indicates that |
| * context is a two-way synchronization. |
| */ |
| public final static String TWO_WAY = "two-way"; //$NON-NLS-1$ |
| |
| /** |
| * Synchronization type constant that indicates that |
| * context is a three-way synchronization. |
| */ |
| public final static String THREE_WAY = "three-way"; //$NON-NLS-1$ |
| |
| /** |
| * Return the scope of this synchronization context. The scope determines |
| * the set of resources to which the context applies. Changes in the scope |
| * may result in changes to the sync-info available in the tree of this |
| * context. |
| * |
| * @return the set of mappings for which this context applies. |
| */ |
| public ISynchronizeScope getScope(); |
| |
| /** |
| * Return a tree that contains <code>SyncInfo</code> nodes for resources |
| * that are out-of-sync. The tree will contain sync-info for any out-of-sync |
| * resources that are within the scope of this context. The tree |
| * may include additional out-of-sync resources, which should be ignored by |
| * the client. Clients can test for inclusion using the method |
| * {@link ISynchronizeScope#contains(IResource)}. |
| * |
| * @return a tree that contains a <code>SyncInfo</code> node for any |
| * resources that are out-of-sync. |
| */ |
| public SyncInfoTree getSyncInfoTree(); |
| |
| /** |
| * Returns synchronization info for the given resource, or <code>null</code> |
| * if there is no synchronization info because the resource is not a |
| * candidate for synchronization. |
| * |
| * Note that sync info may be returned for non-existing or for resources |
| * which have no corresponding remote resource. |
| * |
| * |
| * This method will be quick. If synchronization calculation requires content from |
| * the server it must be cached when the context is created or refreshed. A client should |
| * call refresh before calling this method to ensure that the latest information |
| * is available for computing the sync state. |
| * |
| * @param resource the resource of interest |
| * @return sync info |
| * @throws CoreException |
| */ |
| public SyncInfo getSyncInfo(IResource resource) throws CoreException; |
| |
| /** |
| * Return the synchronization type. A type of <code>TWO_WAY</code> |
| * indicates that the synchronization information (i.e. |
| * <code>SyncInfo</code>) associated with the context will also be |
| * two-way (i.e. there is only a remote but no base involved in the |
| * comparison used to determine the synchronization state of resources. A |
| * type of <code>THREE_WAY</code> indicates that the synchronization |
| * information will be three-way and include the local, base (or ancestor) |
| * and remote. |
| * |
| * @return the type of merge to take place |
| * |
| * @see org.eclipse.team.core.synchronize.SyncInfo |
| */ |
| public String getType(); |
| |
| /** |
| * Dispose of the synchronization context. This method should be |
| * invoked by clients when the context is no longer needed. |
| */ |
| public void dispose(); |
| |
| /** |
| * Refresh the context in order to update the sync-info to include the |
| * latest remote state. any changes will be reported through the change |
| * listeners registered with the sync-info tree of this context. Changes to |
| * the set may be triggered by a call to this method or by a refresh |
| * triggered by some other source. |
| * |
| * @see SyncInfoSet#addSyncSetChangedListener(ISyncInfoSetChangeListener) |
| * @see org.eclipse.team.core.synchronize.ISyncInfoTreeChangeEvent |
| * |
| * @param traversals the resource traversals which indicate which resources |
| * are to be refreshed |
| * @param flags additional refresh behavior. For instance, if |
| * <code>RemoteResourceMappingContext.FILE_CONTENTS_REQUIRED</code> |
| * is one of the flags, this indicates that the client will be |
| * accessing the contents of the files covered by the traversals. |
| * <code>NONE</code> should be used when no additional behavior |
| * is required |
| * @param monitor a progress monitor, or <code>null</code> if progress |
| * reporting is not desired |
| * @throws CoreException if the refresh fails. Reasons include: |
| * The server could not be contacted for some reason (e.g. |
| * the context in which the operation is being called must be |
| * short running). The status code will be |
| * SERVER_CONTACT_PROHIBITED. |
| */ |
| public void refresh(ResourceTraversal[] traversals, int flags, IProgressMonitor monitor) throws CoreException; |
| |
| }</pre> |
| <p> </p> |
| <h2><a name="OperationParticipation"></a>Maintaining Workspace Consistency</h2> |
| <p>Model tools in Eclipse are typically layered. In the very least, there is the |
| model layer (e.g. Java) and the file-system layer (i.e. IResource). However, |
| in some cases, there may be more than two layers (e.g. J2EE<->Java<->IResource).</p> |
| <h3>Operation Participation</h3> |
| <p>There is already refactoring participant support in Eclipse which appears to |
| meet several of the requirements logical models have. The original proposal |
| for refactoring participation is described <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/jdt-ui-home/r3_0/proposals/refactoring/participants.html">here</a>. |
| The implementation does vary slightly from what is in the proposal but the proposal |
| is still a good description of the concepts involved.</p> |
| <p>Here is the summary of the features taken from the document:</p> |
| <ul> |
| <li>There is one generic action for the refactorings: rename, move, delete, |
| create and copy. This is stated in the proposal but has not yet been implemented.</li> |
| <li>Extensible refactorings are implemented using a processor/participant architecture. |
| Both processors and participants are contributed via XML. </li> |
| <li>There are three types of participants: |
| <ol> |
| <li>Participants that operate on the original element to be modified. </li> |
| <li>Participants that operate on elements derived from the original element. |
| </li> |
| <li>Participants that operate on the corresponding resource modifications. |
| </li> |
| </ol> |
| </li> |
| <li>Participants can't contribute to the UI, although this would be possible |
| for participants of category (1) if required. </li> |
| <li>There is no support to participate in changes done by a participant. Participants |
| can only participate in processor operations. </li> |
| <li>No support will be provided for composite refactorings. </li> |
| <li>Processors can override each other to provide a more specific processor |
| for more specific elements. Again, this has not yet been implemented.</li> |
| <li>The new refactoring UI is wizard/dialog based as the current Java refactoring |
| UI. The relationship between UI and processors is described in XML. Furthermore |
| special error and preview viewers can be contributed. </li> |
| <li>To support undo in an open refactoring architecture some enhanced undo support |
| from platform is needed.</li> |
| </ul> |
| <p>One possibility was to support participation in operations at all levels. That |
| is, JDT could participate in IResource level operations in order to react to |
| resource level changes. For instance, Java could participate in a *.java file |
| rename in the Resource Navigator and update any references appropriately (thus |
| treating the file rename as a Java compilation unit, or CU, rename). This would |
| lead to the following additional requirements:</p> |
| <ul> |
| <li>Any view that surfaces one of the basic operations will need to include |
| participants in the operation if there is any chance of another model needing |
| to control or participate in the change. For instance, the appropriate Resource |
| Navigator operations would need to be changed to include participants.</li> |
| <li>Higher level models (e.g. JDT) must participate in operations performed |
| on lower level models (e.g. files). As stated in the refactoring proposal, |
| operations on higher level model must also include participants from lower |
| level models. This must be done in such a way that a model layer does not |
| participate in the operation more than once.</li> |
| <li>Rendering in the refactoring preview would need to be model aware. That |
| is, the comparison view would need to show a test compare for text models |
| (such as Java) but a graphical compare for diagrams changes, etc.</li> |
| <li>Transitive model relationships must be handled. For example, if there is |
| a higher-level model that participates in class renames and the Java model |
| participates in a file rename and treats it as a class rename, than the higher-level |
| model participants should be included by the Java participant when a file |
| rename results in a class rename.</li> |
| </ul> |
| <p>Experiments were done by JDT in Eclipse 3.0 and the following observations |
| were made for a package rename vs. a folder rename in which Java participates:</p> |
| <ul> |
| <li>the generated deltas will not be the same. An example is renaming a folder |
| which is a source folder in the Java model. A folder participant that fixes |
| up the Java model triggers the following deltas: |
| <ul> |
| <li>a resource delta notifying about the folder rename.</li> |
| <li>a Java model delta notifying about the build path changes.</li> |
| <li>a Java model delta notifying about the source folder rename without |
| build path updates. This delta occurs since the Java model listens to |
| resource deltas and tries to map them back to Java model deltas.</li> |
| </ul> |
| </li> |
| <li>whereas a rename of the source folder triggers the following delta: |
| <ul> |
| <li>a Java model delta notifying about the source folder rename and the |
| build path update.</li> |
| <li>a resource delta notifying the folder rename.</li> |
| </ul> |
| Clients listening to Java model changes will expect the second delta on a |
| source folder rename. Getting the first deltas might result in some misreaction |
| of clients listening to deltas especially since they will receive two Java |
| model deltas.</li> |
| <li>the framework has to support participating in operations triggered by participants |
| (this is currently not supported in LTK). Consider the case of renaming a |
| *.java file. In this case the participant fixing up the references and the |
| type name of the CU has to load all participants interested in a type rename |
| since a WEB plug-in might want to fix up all references in JSP files.</li> |
| <li>higher level models can be in an inconsistent state when inspected by participants. |
| Again, consider the case of renaming a A.java file in the resource navigator. |
| If JDT reacts to this and wants to fix up the type name inside of A.java, |
| accessing A.java in the Java model would result in an exception since the |
| underlying file already got renamed, but the Java model doesn't know about |
| this since the resource delta hasn't broadcasted yet.</li> |
| </ul> |
| <p>The next section addresses these issues by combining operation retargeting |
| with participation in order to address these issues.</p> |
| <h3>Operation Retargeting</h3> |
| <p>To ensure that participants access models in a consistent state all operations |
| have to be executed on the highest level model and the operation has to describe |
| what happens in the lower level models to load corresponding lower level participants. |
| For example when renaming a CU the rename refactoring also loads participants |
| interested in file renames since a CU rename renames the file in the underlying |
| resource model. However the system should help the user to keep higher level |
| models consistent when manipulating lower level models. One approach would be |
| that the systems informs about those situations and allows the triggering of |
| the higher level operation instead. For example a rename of a *.java file in |
| the resource navigator could show a dialog telling the user that for model consistency |
| the file is better renamed using the Java Rename refactoring and if the users |
| wants to execute this action instead. Doing so has the other nice side effect |
| that models are not forced to use the LTK participant infrastructure. The way |
| how to participate could be left open for the plug-in providing the model operations.</p> |
| <p>One potential complication arises when multiple models want to "own" |
| or "control" a resource. This is less of an issue if one is a higher |
| level model built on top of a lower level one. For instance, a J2EE model may |
| override the Java model and assume ownership of any Java files that are J2EE |
| artifacts, such as EJBs. However, problems arise if the two models are peers. |
| For instance, there may be several models that are generated from a WSDL (web |
| services) descriptor file. The user may need to pick which model gets control |
| for operations performed directly on the resource.</p> |
| <p>Note that this feature area has a great deal of overlap with the <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/R3_1/contributions-proposal/requestForComments.html">Improve |
| Action Contributions </a>work being proposed by the UI team.</p> |
| <h3>Operation Veto</h3> |
| <p>It is not clear the operation retargeting is desirable. That is, if a user |
| performs a delete on a file, it may be disconcerting if the delete is actually |
| performed on an EJB that consists of several files. An alternate approach is |
| to detect when an operation on a lower level model may have an effect on a higher |
| level model and ask the user to confirm that they really do want to perform |
| the operation on the lower level model.</p> |
| <h2><a name="ObjectContributionSupport"></a>Team Operations on Model Elements</h2> |
| <p>The support for having Team operations appear in the context menu of logical |
| elements is based on <code>ResourceMappings</code>. This support was available |
| as non-API in 3.1 and the is described in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-vcm-home/docs/online/team3.1/logical-physical-mappings.html">Support |
| Logical Resources - Resource Mappings</a> document. Here is a summary of what |
| is required for this:</p> |
| <ul> |
| <li>Repository tooling needs to be able to provide a <code>RemoteResourceMappingContext</code> |
| that gives the model access to the remote state and contents of the files |
| involved in the operation.</li> |
| <li>Model tooling needs to be able to determine which files are relevant for |
| its model elements given a <code>RemoteResourceMappingContext</code>. In many |
| cases, this is straight forward and doesn't require the context at all. In |
| others, the model may need to be able to query the file structure or file |
| contents from the context in order to determine which files need to be included.</li> |
| </ul> |
| <p>A <code>RemoteResourceMappingContext</code> is a means to allow the model to |
| see the state of the repository at a particular point in time. There are many |
| different terms used by different repository tools to identify this type of |
| view of the repository including version, branch, configuration, view, snapshot, |
| or baseline. The type of operation being performed dictates what files states |
| are accessible from the <code>RemoteResourceMappingContext</code>. For example, |
| when updating the local workspace to match the latest contents on the server, |
| the context would need to allow the client to access the latest contents for |
| remote files whose content differs from their local counterparts in order to |
| allow the model to determine if there are additional files that should be included |
| in the update. When committing, the context would need to provide the ancestor |
| state of any locally modified files so that the model could ascertain if there |
| are any outgoing deletions.</p> |
| <p>There are still some outstanding issues that need to be solved in this area.</p> |
| <ul> |
| <li>Team operations on model elements may need to include other model elements. |
| For instance, an operation on the plugin.xml file may need to include the |
| plugin.properties file as they are both part of the plug-in manifest object. |
| Also, operations on a sub-element of a file, will need to convey to the user |
| that all sub-elements of that file will be operated on.</li> |
| <li>Team operations have a life cycle that needs to be communicated to the model |
| provider. This will allow the model provider to efficiently manage the caching |
| of model state associated with a remote resource mapping context.</li> |
| <li>The model structure being displayed to the user may differ from the structure |
| of the model. This arises from the use of content providers in JFace which |
| allow a tree view to display a model in an arbitrary structure. A concrete |
| example of this is he Java Packages Explorer. It can display packages in either |
| flat or hierarchy mode. The flat mode matches the underlying model structure |
| whereas the hierarchy mode actually matches the file system structure (i.e. |
| packages are deep). Users will tend to associate the target of a team operation |
| as what is being displayed and not necessarily what the actual model structure |
| is.</li> |
| </ul> |
| <p>The following sections describe proposed solutions to these issues</p> |
| <h3><a name="TeamOperation"></a>Team Operation Input Determination</h3> |
| <p>In order to ensure that the proper resources are included as the input to a |
| team operation, we introduce the concept of a model provider. A model provider |
| has the following:</p> |
| <ul> |
| <li>An id that uniquely identifies the model provider</li> |
| <li>A set of lower-level model providers that the model provider extends. For |
| example, the Java model provider would extend the Resources model provider |
| while the J2EE model provider would extend both the Java and Resources model |
| provider.</li> |
| <li>An enablement rule that determines which resources the model provider applies |
| to.</li> |
| </ul> |
| <p>Model providers would be used in the following way to ensure that the proper |
| resources were included in a team operation.</p> |
| <ul> |
| <li>Model tooling would plug into the modelProvider extension point and provide |
| an enablement rule to match on resources of interest.</li> |
| <li>When a Team operation is performed, the repository plug-in uses the selection |
| to obtain all the applicable model providers.</li> |
| <li>The model providers are given a chance to add addition model elements, and |
| hence files, the the Team operation.</li> |
| <li>The operation is performed</li> |
| </ul> |
| <p>This mechanism can be used to ensure that operations performed directly on |
| files include all the files that constitute a model and also will ensure that |
| the effects can be displayed to the user in a form consistent with the higher |
| level models that are effected. This will be covered separately in the <a href="#DisplayingLogicalModels">Displaying |
| Model Elements in Team Operations</a> section.</p> |
| <h3>Team Operation Lifecycle</h3> |
| <p>Most Team operations have multiple steps. To illustrate this, consider an update |
| operation. The steps of the operation, considering the inclusion of resource |
| mappings and other facilities described in this proposal are:</p> |
| <ol> |
| <li>Determine the complete set of resource mappings that are potentially being |
| updated.</li> |
| <li>Display this to the user in a model specific way so they can confirm the |
| operation.</li> |
| <li>If the operation is confirmed, delegate the merge to the model so it can |
| attempt to automatically merge the model elements being updated using model |
| semantics to aid in the merging.</li> |
| <li>If automatic merge of one or more model elements is not possible, perform |
| a manual merge on these elements by obtaining appropriate compare editor inputs |
| from the model provider.</li> |
| </ol> |
| <p>Each of these steps may involve separate calls from the repository tooling |
| to the model tooling. The model would not want to recompute the remote model |
| state during each step but instead would rather cache any computed state until |
| the entire operation was completed. One means of supporting this is to add listener |
| support to the team context associated with the operation and have an event |
| fired when the operation using the context is completed). </p> |
| <h3>View Structure vs. Model Structure</h3> |
| <p>The contents of views in Eclipse are determined by a content provider. In most |
| cases, the structure of what is displayed matches the model structure but in |
| some cases it does not. One such example is the package explorer when it is |
| in hierarchy mode. In this mode, the children of a package are its files and |
| its subpackages. When the user performs an operation on a package in this view, |
| they may reasonably expect the operation to be performed on the package and |
| its subpackage. However, the package adapts to a resource mapping that only |
| includes the files and not the subpackages.</p> |
| <p>The simplest solution to this problem is to require that the content providers |
| wrap objects when they need adaptation to resource mappings and are displayed |
| in a way that does not match the model structure. In our Java example, this |
| would mean creating a new model object (e.g. DeepJavaPackage) whose children |
| were the java classes and subpackages. The advantage of this approach is that |
| the process of converting a model object to a resource mapping can be performed |
| by the model without any knowledge of the view configuration. Some of the concerns |
| of this approach are:</p> |
| <ul> |
| <li>Views that display different representations of a model would not be able |
| to do so by simply implementing a custom content provider. In essence, they |
| would need to create new model objects to get the display structure they desired.</li> |
| <li>The introduction of new model objects means that any menus need to handle |
| these new model objects. This is simplified somewhat by the support for adaptability |
| but is still an issue that needs to be addressed by the model tooling.</li> |
| </ul> |
| <p>Another solution to this problem would be to:</p> |
| <ul> |
| <li>Include the content provider of a view in the selection (i.e. the selection |
| include the context of where it originated).</li> |
| <li>Add a method to the content provider that will return a resource mapping |
| for an object that matches what the view is showing.</li> |
| <li>Add a method to content providers for getting a resource mapping for an |
| object.</li> |
| <li>Change the adaptation code in the IDE plug-in to check with the content |
| provider before adapting the resource directly</li> |
| </ul> |
| <p>The advantage of this approach is that model tooling can still use content |
| providers to provide alternate views of their model without wrapping model objects |
| or providing new model objects. The disadvantages are:</p> |
| <ul> |
| <li>The resource mapping determination process becomes more complicated.</li> |
| <li>Content providers would need to become more than just viewer configuration. |
| They would need to be included in the objectContributions for use in popup |
| menus and decorations and any other place where objects were adapted to resource |
| mappings.</li> |
| <li>There is no longer a one-to-one correspondence between a model object and |
| its resource mapping. In other words, clients could not assume tat they could |
| get the model object out of a resource mapping and then reobtain the same |
| resource mapping from that object.</li> |
| </ul> |
| <p>Given the complexity of the second solution, the first is preferable from an |
| implementation standpoint. However, we need to determine if clients can accept |
| this solution.</p> |
| <h2><a name="DecoratorSupport"></a>Team Decorator Support</h2> |
| <p>This section describes the support that is proposed to be added in Eclipse |
| 3.2 to support the decoration of logical model elements. In Eclipse 3.1 and |
| prior, logical model elements could still be decorated. However, the only inter-model |
| adaptability support was for models whose elements had a one-to-one mapping |
| to file system resources (i.e. <code>IResource</code>). Here is a summary of |
| the issues that we are hoping to address in 3.2.</p> |
| <ol> |
| <li>General adaptability of lightweight decorators. In other words, an element |
| of one model can be adapted to the element of another for the purpose of determining |
| the label decorations for the original element. This is available in 3.2 M1 |
| (see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=86159">bug 86159</a>).</li> |
| <li>Additional support for the decoration of model elements that adapt to <code>ResourceMapping</code>. |
| ResourceMapping decoration makes use of the general adaptability mechanism |
| but also requires support for triggering label updates for any logical element |
| whose decoration depends on the state of one or more resources (see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=86493">bug |
| 86493</a>).</li> |
| <li>Support for the proper dirty decoration of elements that are contained in |
| a file but whose state depends on the contents of the file. An example of |
| this is Java methods in a file. If you make a change in a Java file that is |
| mapped to CVS, the file is decorated as dirty. It would be beneficial if the |
| dirty decoration could also be placed on those particular methods or class |
| members that are dirty. This is much more important for models where the user |
| may not be as directly aware of the relationship between a model element and |
| the file in which it is persisted.</li> |
| </ol> |
| <p>As stated above, point one has already been completed. The following sections |
| describe potential solutions to the remaining two problems. The first two sections |
| describe potential solutions using the existing architecture while the third |
| presents a unified solution that makes use of the team context described in |
| the Common Navigator section.</p> |
| <h3>Updating of Model Element Labels</h3> |
| <p>Some repository decorations are propagated to the root of any views that display |
| elements shared in the repository. This is done in order to provide useful information |
| to the user. For instance, the "shared with CVS" decoration (by default, |
| the <img src="version_controlled.gif" width="7" height="8"> icon) should appear |
| on any object on which a CVS operation can be performed. Similarly, the dirty |
| decoration (by default, a ">" prefix) should appear on any views |
| items containing a dirty child in order to help the user find dirty items. For |
| the purpose of discussion, we will use dirty decoration when describing our |
| proposal but the same will hold true for other decorations that require propagation.</p> |
| <p>When a file becomes dirty, a label change must be issued for any items visible |
| to the user whose dirty state has change or that is a direct or indirect parent |
| of such an item. When we are dealing strictly with file system resources, this |
| is straight forward. When a file becomes dirty, a label change is issued for |
| the file and the folders and project containing the file. Any views that are |
| displaying these items will then update their labels. It is the responsibility |
| of models that have a one-to-one mapping from files to model elements to update |
| the labels of the corresponding model elements as well. For instance, JDT maps |
| the file, folder and project label changes to label changes on Java model elements |
| such as Compilation Units, Packages and Java Projects so that decorations in |
| the Packages Explorer get updated properly.</p> |
| <p>However, problems arise for logical models elements that do not have a one-to-one |
| mapping to file resources. For instance, consider a working set that contains |
| several project. The repository provider does not know that the working set |
| is being displayed to the user so does not issue a label update for it. The |
| view displaying the working set does not know when the state of the children |
| impact the label of the parent. It could try to fake it by updating the working |
| set label whenever the label of any children are updated but this could result |
| in many unnecessary and potentially costly updates.</p> |
| <p>The following points summarize the aspects of the problem that should be considered |
| when showing repository decorations in a model view:</p> |
| <ol> |
| <li>The repository deals with changes at the file system level so repository |
| decoration changes occur on files or folders.</li> |
| <li>The model views deal with decoration on model elements so label changes |
| are issued on model elements. A means to translate file changes to model element |
| changes is required.</li> |
| <li>The repository may have some decorated properties, such as the dirty state, |
| that are derived from the model view structure and not the file structure |
| (i.e. all parents of a dirty item in a view should be decorated as dirty).</li> |
| <li>Recalculating the label for a model element may be costly so, if possible, |
| label changes should only be issued if there is an actually change in the |
| state that determines the label.</li> |
| </ol> |
| <p>It is interesting to note that the requirement in point 2 can be solved using |
| the <a href="#TeamOperation">Team Operation Participation</a> mechanism described |
| previously. However, addressing the last two points will require additional |
| support. The next two sections describe a potential solution. It is useful to |
| note that any solution we come up with must consider the broader context of |
| the direction decoration support in Eclipse will go. We have tried to consider |
| this when drafting this proposal.</p> |
| <h4>Decoration Change Notification</h4> |
| <p>Currently, a decoration change is broadcast implicitly by issuing label change |
| events for the elements that need redecoration. From a repository tooling standpoint, |
| this means generating a label change on any changed file resources (and there |
| ancestor resources if the decorator that represents the changed state is propagated |
| to parents). It is then up to the model tooling to translate these label changes |
| of file resources to label changes on the appropriate model elements.</p> |
| <p>An alternative approach would be to make the decoration change notification |
| explicit. Thus, the repository tooling could issue a decoration change event |
| that contains the resources that needs redecoration. It would then be up to |
| any views that are displaying a repository decoration to update the label of |
| any elements appropriately. This would mean determining the set of elements |
| that correspond to the given resources.</p> |
| <p>As stated in point 4 above, a possible optimization is to only issue the label |
| change if the state of the decoration has changed. This can be accomplished |
| by including, as part of the change notification event, a property evaluator |
| that evaluates and caches the properties for each element it is provided and |
| indicates whether a change has occurred which requires the item to be redecorated.</p> |
| <h4>Decoration Propagation</h4> |
| <p>In the previous section we mentioned the possibility of having a property evaluator |
| that indicated whether a label change was required. This evaluator could also |
| indicate whether a reevaluation for the parent of the element is required. That |
| is, if the evaluator calculated that the dirty state of the element had changed, |
| it could indicate that the label update was required and that the evaluator |
| should be executed with the parent element as input in order to determine if |
| a label change was required for the parent and if the process should be repeated |
| for the parent element's parent.</p> |
| <p>This calculation could be long running. Thus, it should be performed in a background |
| job with minimal use of the UI thread. This may be a bit tricky as JFace viewers |
| are not threadsafe (i.e. they are mostly invoked from the UI thread). The current |
| JFace viewers persist the tree of elements in the SWT tree items so accessing |
| them needs to be run in the UI thread. Also, label changes need to be run in |
| the UI thread. These factors must be considered when designing a solution.</p> |
| <h3>Sub-File Level Dirty Decorations</h3> |
| <p>In this section we present API on <code>ResourceMapping</code> that supports |
| change determination on logical model elements. With this API, the algorithm |
| used by the decorator would be this:</p> |
| <ul> |
| <li>When asked to decorate a resource mapping, the team provider would invoke |
| the <code>getChangeState</code> method on the resource mapping to provide |
| a change state given a remote mapping context that does not allow contact |
| to the server.</li> |
| <li>The mapping will return the change state or <em>MAY_HAVE_DIFFERENCES</em> |
| if the change state cannot be determined without contacting the server.</li> |
| <li>If server contact is required, the decorator should use a background job |
| to query the change state. It can then cache this result and re-issue a label |
| update.</li> |
| </ul> |
| <p>In addition to the API on ResourceMapping, it would also be beneficial to provide |
| an abstract lightweight decorator that team providers can use to get the above |
| described behavior.</p> |
| <h4>ResourceMapping Changes</h4> |
| <p>Here are the proposed API additions to the <code>ResourceMapping</code> class. |
| Note that there would be additional API added to <code>ResourceMapping</code> |
| and <code>RemoteResourceMappingContext</code> to aid models in their calculation |
| of the change state.</p> |
| <pre> |
| public abstract class ResourceMapping { |
| |
| /** |
| * Constant returned by <code>calculateChangeState</code> to indicate that |
| * the model object of this resource mapping does not differ from the |
| * corresponding object in the remote location. |
| */ |
| public static final int NO_DIFFERENCE = 0; |
| |
| /** |
| * Constant returned by <code>calculateChangeState</code> to indicate that |
| * the model object of this resource mapping differs from the corresponding |
| * object in the remote location. |
| */ |
| public static final int HAS_DIFFERENCE = 1; |
| |
| /** |
| * Constant returned by <code>calculateChangeState</code> to indicate that |
| * the model object of this resource mapping may differ from the |
| * corresponding object in the remote location. This is returned when |
| * getChangeState was not provided with a progress monitor and the remote |
| * state of the object was not cached. |
| */ |
| public static final int MAY_HAVE_DIFFERENCE = 2; |
| |
| /** |
| * Calculate the change state of the local object when compared to it's |
| * remote representation. If server contact is required to properly |
| * calculate the state but is not allowed (as indicated by an exception with |
| * the code |
| * <code>RemoteResouceMappingContext.SERVER_CONTACT_PROHIBITED</code>), |
| * <code>MAY_HAVE_DIFFERENCE</code> should be returned. Otherwise |
| * <code>HAS_DIFFERENCE</code> or <code>NO_DIFFERENCE</code> should be |
| * returned as appropriate. Subclasses may override this method. |
| * |
| * It is assumed that, when <code>canContactServer</code> is |
| * <code>false</code>, the methods |
| * <code>RemoteResourceMappingContext#contentDiffers</code> and |
| * <code>RemoteResourceMappingContext#fetchMembers</code> of the context |
| * provided to this method can be called without contacting the server. |
| * Clients should ensure that this is how the context they provide behaves. |
| * |
| * @param context a resource mapping context |
| * @param monitor a progress monitor or <code>null</code>. If |
| * <code>null</code> is provided, the server will not be |
| * contacted and <code>MAY_HAVE_DIFFERENCE</code> will be |
| * returned if the change state could not be properly determined |
| * without contacting the server. |
| * @return the calculated change state of <code>HAS_DIFFERENCE</code> if |
| * the object differs, <code>NO_DIFFERENCE</code> if it does not |
| * or <code>MAY_HAVE_DIFFERENCE</code> if server contact is |
| * required to calculate the state. |
| * @throws CoreException |
| */ |
| public int calculateChangeState( |
| RemoteResourceMappingContext context, |
| IProgressMonitor monitor) |
| throws CoreException { |
| try { |
| int changeState = ... |
| return changeState; |
| } catch (CoreException e) { |
| if (e.getStatus().getCode() == RemoteResourceMappingContext.SERVER_CONTACT_PROHIBITED) |
| return MAY_HAVE_DIFFERENCE; |
| throw e; |
| } |
| } |
| |
| }</pre> |
| <h3>Team Aware Model Views</h3> |
| <p>The complexities described in the previous sections arise because of the separation |
| of models and decorators. An alternate approach would be to use the team context |
| discussed in the <a href="#GenericNavigator">Common Navigator</a> section for |
| any model view. Such support would work something like this.</p> |
| <ul> |
| <li>The team provider would make one or more team contexts globally available.</li> |
| <li>Model tooling could allow the user to pick which context they wanted available |
| in a particular view.</li> |
| </ul> |
| <p>The details would be the same as those discussed in the Common Navigator section. |
| This would simplify the decorator update story as the view would then listen |
| to both resource deltas and team deltas and update model elements and labels |
| appropriately. The model will have enough information available from the tam |
| context to make the decisions about propagation in any way they deal appropriate. |
| The models will also be able to determine the change state of their model elements |
| for themselves so no additional API on <code>ResourceMapping</code> would be |
| required.</p> |
| <h2><a name="ModelLevelMerging"></a>Model Level Merging</h2> |
| <p>There are two types of merges that can take place: automatic and manual. Automatic |
| merges (or auto-merges) are merges the either do not contain file level conflicts |
| or whose file level conflicts can be resolved without user intervention. Manual |
| merges require the user to inspect the conflicting changes and decide how to |
| resolve them. In either case, involvement of the model in these two types of |
| merges is beneficial. For auto-merges, model knowledge can increase the likelihood |
| of a manual merge being possible and for manual merges, model involvement can |
| enhance how the merges are displayed and performed.</p> |
| <p>In this section we describe the API we propose to add to support model merging:</p> |
| <ul> |
| <li><code>IResourceMappingMerger</code>: an interface that model tooling implements |
| to allow repository tooling to perform head-less merges when possible on resource |
| mappings. The merge will also indicate when head-less merges are not possible.</li> |
| <li><code>IResourceMappingEditorInputFactory</code>: an interface that model |
| tooling implements to allow resource mappings to be merged manually.</li> |
| <li><code>MergeContext</code>: an API which allows the model tooling to interact |
| with the repository tooling in order to perform model level merges.</li> |
| </ul> |
| <p>Given a set of resource mappings, the repository tooling needs to be able to |
| obtain the model tooling support classes which will perform the merging. This |
| will require: </p> |
| <ul> |
| <li>A <code>getModelId</code> method on <code>ResourceMapping</code> to associate |
| a model id with each resource mapping.</li> |
| <li>An extension point for associating implementations of the above described |
| merge support classes with a model id.</li> |
| </ul> |
| <p>The steps for performing an optimistic merge would then look something like |
| this:</p> |
| <ul> |
| <li>A merge operation is performed on a set of resource mappings.</li> |
| <li>The Team participants are consulted to ensure that all the relevant resource |
| mappings are included in the operation.</li> |
| <li>The mappings are grouped by model id and the <code>IResourceMappingMerger</code> |
| is obtained and invoked for each group.</li> |
| <li>The results from the merges are accumulated including the list of mappings |
| that could not be auto-merged.</li> |
| <li>The failed mappings are again grouped by model id and the registered <code>IResourceMappingEditorInputFactory |
| </code>is used to obtain a set of editor inputs for these elements.</li> |
| <li>Editors are opened on these mappings so that they can be manually merged.</li> |
| </ul> |
| <p>When the model is asked to merge elements, either automatically or manually, |
| it will need access to the remote state of the model. API for this is also being |
| proposed. </p> |
| <h3>Auto-merging API</h3> |
| <p>In this section, we propose some API that will allow for model based auto-merging. |
| Before we do that, we should first mention that Eclipse has a pluggable <code>IStreamMerger</code> |
| (introduced in 3.0) for supporting model based merges when there is a one-to-one |
| based correspondence between a file and a model object. However, this is not |
| currently used by CVS (or any other repository provider as far as we know) but |
| this can be part of the solution we propose here.</p> |
| <p>The proposed API to support model level merges consists of the following:</p> |
| <ul> |
| <li><code>IResourceMappingMerger</code>: This is similar to the <code>IStreamMerger</code> |
| but is obtained from resource mappings and is provided a <code>MergeContext</code> |
| form which the model can obtain any ancestor and remote file contents that |
| it requires.</li> |
| <li><code>MergeContext</code>: Provides access to the ancestor and remote file |
| contents using <code>RemoteResourceMappingContexts</code> and also has helper |
| methods for performing file merges and for signaling the context that a file |
| has been merged so that the file can be marked up-to-date.</li> |
| </ul> |
| <h4>Resource Mapping Merger</h4> |
| <p>Below is what <code>IResourceMappingMerger</code> the would look like. It contains |
| a <code>merge</code> whose semantics differ depending on the type of the merge |
| context. A merge is performed for three-way synchronizations and the replace |
| occurs for two-way contexts. The model can determine which model elements need |
| to be merged by consulting the merge context which is presented in the next |
| section. </p> |
| |
| <pre>/** |
| * The purpose of this interface is to provide support to clients (e.g. |
| * repository providers) for model level auto-merging. It is helpful in the |
| * cases where a file may contain multiple model elements or a model element |
| * consists of multiple files. It can also be used for cases where there is a |
| * one-to-one mapping between model elements and files, although |
| * <code>IStreamMerger</code> can also be used in that case. |
| * |
| * Clients should determine if a merger is available for a resource mapping |
| * using the adaptable mechanism as follows: |
| * |
| * Object o = mapping.getModelProvider().getAdapter(IResourceMappingMerger.class); |
| * if (o instanceof IResourceMappingMerger.class) { |
| * IResourceMappingMerger merger = (IResourceMappingMerger)o; |
| * ... |
| * } |
| * |
| * Clients should group mappings by model provider when performing merges. |
| * This will give the merge context an opportunity to perform the |
| * merges optimally. |
| * |
| * @see org.eclipse.compare.IStreamMerger |
| * @see org.eclipse.team.internal.ui.mapping.IResourceMappingManualMerger |
| * @since 3.2 |
| */ |
| public interface IResourceMappingMerger { |
| |
| /** |
| * Attempt to automatically merge the mappings of the merge context(<code>MergeContext#getMappings()</code>). |
| * The merge context provides access to the out-of-sync resources (<code>MergeContext#getSyncInfoTree()</code>) |
| * associated with the mappings to be merged. However, the set of resources |
| * may contain additional resources that are not part of the mappings being |
| * merged. Implementors of this interface should use the mappings to |
| * determine which resources to merge and what additional semantics can be |
| * used to attempt the merge. |
| * |
| * The type of merge to be performed depends on what is returned by the |
| * <code>MergeContext#getType()</code> method. If the type is |
| * <code>MergeContext.TWO_WAY</code> the merge will replace the local |
| * contents with the remote contents, ignoring any local changes. For |
| * <code>THREE_WAY</code>, the base is used to attempt to merge remote |
| * changes with local changes. |
| * |
| * Auto-merges should be performed for as many of the context's resource |
| * mappings as possible. If merging was not possible for one or more |
| * mappings, these mappings should be returned in an |
| * <code>MergeStatus</code> whose code is |
| * <code>MergeStatus.CONFLICTS</code> and which provides access to the |
| * mappings which could not be merged. Note that it is up to the model to |
| * decide whether it wants to break one of the provided resource mappings |
| * into several sub-mappings and attempt auto-merging at that level. |
| * |
| * @param mappings the set of resource mappings being merged |
| * @param mergeContext a context that provides access to the resources |
| * involved in the merge. The context must not be |
| * <code>null</code>. |
| * @param monitor a progress monitor |
| * @return a status indicating the results of the operation. A code of |
| * <code>MergeStatus.CONFLICTS</code> indicates that some or all |
| * of the resource mappings could not be merged. The mappings that |
| * were not merged are available using |
| * <code>MergeStatus#getConflictingMappings()</code> |
| * @throws CoreException if errors occurred |
| */ |
| public IStatus merge(IMergeContext mergeContext, |
| IProgressMonitor monitor) throws CoreException; |
| |
| }</pre> |
| |
| <p>It is interesting to note that partial merges are possible. In such a case, |
| the <code>merge</code> method must be sure to return a <code>MergeStatus</code> |
| that contains any resource mappings for which the merge failed. These mappings |
| could match some of the mappings passed in or could be mappings of sub-components |
| of the larger mapping for which the merge was attempted, at the discretion of |
| the implementer.</p> |
| <h4>Merge Context</h4> |
| <p>In order for repository tooling to support model level merging, they must be |
| able to provide an <code>IMergeContext</code>. The merge context provides:</p> |
| <ul> |
| <li>a team synchronization context (i.e. <code>IMergeContext</code> extends |
| the <code>ISynchronizationContext</code> introduced in the Common Navigator |
| section). </li> |
| <li> the ability to mark a file as merged. This is provided in order to allow |
| the model tooling to signal when they have completed the merge so that the |
| repository tooling can then update the synchronization meta-data of the file |
| so it can be checked-in or committed. </li> |
| <li>merge methods which allow the model tooling to delegate the merge of one |
| or more files back to the repository tooling (i.e. the model does not need |
| to do any special handling to aid the merge).</li> |
| <li>the scope of a merge context is a <code>ResourceMappingScope</code> that |
| provides access to the resource mappings involved in the merge.</li> |
| </ul> |
| <p>The following is the proposed API methods of the merge context.</p> |
| <pre>/** |
| * Provides the context for an <code>IResourceMappingMerger</code> |
| * or a model specific synchronization view that supports merging. |
| * |
| * TODO: Need to have a story for folder merging |
| * |
| * This interface is not intended to be implemented by clients. |
| * |
| * @see IResourceMappingMerger |
| * @since 3.2 |
| */ |
| public interface IMergeContext extends ISynchronizationContext { |
| |
| /** |
| * Method that allows the model merger to signal that the file in question |
| * has been completely merged. Model mergers can call this method if they |
| * have transferred all changes from a remote file to a local file and wish |
| * to signal that the merge is done.This will allow repository providers to |
| * update the synchronization state of the file to reflect that the file is |
| * up-to-date with the repository. |
| * |
| * Clients should not implement this interface but should instead subclass |
| * MergeContext. |
| * |
| * @see MergeContext |
| * |
| * @param file the file that has been merged |
| * @param monitor a progress monitor |
| * @return a status indicating the results of the operation |
| */ |
| public abstract IStatus markAsMerged(IFile file, IProgressMonitor monitor); |
| |
| /** |
| * Method that can be called by the model merger to attempt a file-system |
| * level merge. This is useful for cases where the model merger does not |
| * need to do any special processing to perform the merge. By default, this |
| * method attempts to use an appropriate <code>IStreamMerger</code> to |
| * merge the files covered by the provided traversals. If a stream merger |
| * cannot be found, the text merger is used. If this behavior is not |
| * desired, sub-classes may override this method. |
| * |
| * This method does a best-effort attempt to merge all the files covered |
| * by the provided traversals. Files that could not be merged will be |
| * indicated in the returned status. If the status returned has the code |
| * <code>MergeStatus.CONFLICTS</code>, the list of failed files can be |
| * obtained by calling the <code>MergeStatus#getConflictingFiles()</code> |
| * method. |
| * |
| * Any resource changes triggered by this merge will be reported through the |
| * resource delta mechanism and the sync-info tree associated with this context. |
| * |
| * TODO: How do we handle folder removals generically? |
| * |
| * @see SyncInfoSet#addSyncSetChangedListener(ISyncInfoSetChangeListener) |
| * @see org.eclipse.core.resources.IWorkspace#addResourceChangeListener(IResourceChangeListener) |
| * |
| * @param infos |
| * the sync infos to be merged |
| * @param monitor |
| * a progress monitor |
| * @return a status indicating success or failure. A code of |
| * <code>MergeStatus.CONFLICTS</code> indicates that the file |
| * contain non-mergable conflicts and must be merged manually. |
| * @throws CoreException if an error occurs |
| */ |
| public IStatus merge(SyncInfoSet infos, IProgressMonitor monitor) throws CoreException; |
| |
| /** |
| * Method that can be called by the model merger to attempt a file level |
| * merge. This is useful for cases where the model merger does not need to |
| * do any special processing to perform the merge. By default, this method |
| * attempts to use an appropriate <code>IStreamMerger</code> to perform the |
| * merge. If a stream merger cannot be found, the text merger is used. If this behavior |
| * is not desired, sub-classes may override this method. |
| * |
| * @param file the file to be merged |
| * @param monitor a progress monitor |
| * @return a status indicating success or failure. A code of |
| * <code>MergeStatus.CONFLICTS</code> indicates that the file contain |
| * non-mergable conflicts and must be merged manually. |
| * @see org.eclipse.team.ui.mapping.IMergeContext#merge(org.eclipse.core.resources.IFile, org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public IStatus merge(SyncInfo info, IProgressMonitor monitor); |
| |
| }</pre> |
| <h3>Manual Merging</h3> |
| <p>Providing the capability to manually merge a set of model elements require |
| two things:</p> |
| <ul> |
| <li>the ability to display a high level view of the model </li> |
| <li>the ability to merge individual model elements manually</li> |
| </ul> |
| <p>The first requirement is met by the team context proposal outlined in the <a href="#GenericNavigator">Common |
| Navigator</a> section. The second can be met by giving such a view access to |
| the merge context discussed in the <a href="#ModelLevelMerging">Model Level |
| Merging</a> section. This context provides enough state and functionality to |
| display a two-way or three-way comparison and perform the merge.</p> |
| <h2><a name="DisplayingLogicalModels"></a>Displaying Model Elements in Team Operations</h2> |
| <p>There are two types of displays that a Team operation may need:</p> |
| <ul> |
| <li>Display the local model elements in a tree. For instance, a team operation |
| may need to indicate what set of local elements that will take part in a versioning |
| operation. This is similar to what the Common Navigator would require in the |
| sense that the team operation will need a content provider, label provider, |
| etc. for displaying logical model elements.</li> |
| <li>Display the synchronization state between the local model elements and their |
| remote counterparts. This is more complicated as it requires the display of |
| model elements that may not exists remotely and also requires that decorators |
| be calculated based on the comparison of the local, remote and possibly ancestor |
| file contents.</li> |
| </ul> |
| <p>Both these requirements are met by the team context proposal outlined in the |
| <a href="#GenericNavigator">Common Navigator</a> section.</p> |
| <h2><a name="Bootstrapping"></a>Remote Discovery</h2> |
| <p>There are two aspects to consider for this feature:</p> |
| <ul> |
| <li>How does the user see what is available in the repository? </li> |
| <li>How does the user transfer models from the repository to their local workspace? |
| </li> |
| </ul> |
| <p>In the following sections we outline some specific scenarios and describe what |
| would be required to support them.</p> |
| <h3>Remote Browsing</h3> |
| <p>Logical model browsing in the repository would need to be rooted at the project |
| as that is where the associations between the resources and the model providers |
| is persisted. This leads to the following two requirements:</p> |
| <ul> |
| <li>The repository must be able to provide the relevant slice of the repository |
| history for that project. That is, the repository must be able to provide |
| the file states and contents for a particular repository branch or version |
| (or some other means of getting a repository time slice). Another way of thinking |
| of this is that the repository must be able to provide a virtual file system |
| whose contents match what they would be if the branch or version being browsed |
| were loaded from the repository onto the local disk. This requirement is almost |
| identical to what is required to support a RemoteResourceMappingContext so, |
| if a repository is able to provide a context, it should be able to meet this |
| requirement. </li> |
| <li>The model provider must be able to interpret the contents of the remote |
| project in order to build the model corresponding to the contents of the files |
| in the project.</li> |
| <li>The remote model must be displayed in a view so the user can browse it.</li> |
| </ul> |
| <p>There are two options for providing the remote project contents to the model |
| provider.</p> |
| <ol> |
| <li>Provide a new API, potentially similar in form to the RemoteResourceMappingContext, |
| and require model providers to reimplement their model building code in terms |
| of this API.</li> |
| <li>Provide a means to present the remote project as an IProject to the model |
| provider. In this case, the model provider could reuse the code it currently |
| has for building its model.</li> |
| </ol> |
| <p>The second option is definitely preferable from a model provider standpoint |
| because of the potential to reuse existing code. There are, however, a few things |
| to consider:</p> |
| <ul> |
| <li>Providing the remote project as an <code>IProject</code> does allow the |
| reuse of model building code. However, that code may have been written with |
| the assumption that the file contents are all local. Having an <code>IProject</code> |
| that is a view of remote state may introduce some performance problems.</li> |
| <li>The model code could not assume that a local file system object (i.e. <code>java.io.File</code>) |
| could be obtained from an <code>IFile</code> using <code>getLocation().toFile()</code>.</li> |
| <li>The remote <code>IProject</code> will be read-only. The model code will |
| need to handle this. Ideally, this would be identified up from so the model |
| provider could indicate to the user which operations were not available. In |
| the absence of this, the model provider would need to fail gracefully on failed |
| writes.</li> |
| <li>It is possible that building the models requires builders to run and generate |
| output file. If this is the case, an appropriate place to put the output must |
| be determined. As mentioned in the previous point, the project would be read-only. |
| Special handling may be needed to allow the project builder to create build |
| output in a local cache associated with the project.</li> |
| <li>It is also possible that building the model requires information from related |
| projects. This would require either |
| <ul> |
| <li>a means of identifying those projects in such a way that they could |
| also be located and interpreted by the model.</li> |
| <li>a means of dealing with the lack of access to the referenced projects</li> |
| </ul> |
| </li> |
| <li>In essence, this could lead to the different versions of the same model |
| being built in a single workspace. It is equivalent to checking out different |
| versions of the same project into a single workspace. This may cause problems |
| for model providers that have a single model for the whole workspace. PDE |
| is an example of a model provider that does this.</li> |
| <li>Having the project as the point of interpretation implies that the entire |
| project needs to be interpreted, even if the user only wants to view a single |
| element. </li> |
| </ul> |
| <p>Several of the issues mentioned above would benefit from having an explicit |
| distinction between projects that are remote views of a project state and those |
| that are locally loaded in order to perform modifications. </p> |
| <h3>Comparing Remote Versions</h3> |
| <p>When browsing a remote logical model version, the user may then want to compare |
| what they see with another version. If the browsing is done using a remote <code>IProject</code>, |
| then the comparison is no different that if it were performed between a local |
| copy of the model and a remote resource mapping context.</p> |
| <h3>Viewing Logical Model Element History</h3> |
| <p>The user want to see the change history of a particular model element. In order |
| to do that, we need the following.</p> |
| <ul> |
| <li>The repository must be able to produce an ordered list of time slices (what |
| is a time slice. Is there a better term?)</li> |
| <li>The model must interpret each time slice in order to determine if the element |
| of interest change</li> |
| <li>The model provider must display a history of changes for the model element |
| and be able to open the state of the model at each point in its history for |
| the purposes of display or comparison. The list of changes could simply be |
| a list of timestamps indicating when the model element was changed (similar |
| to what is shown in the local history) although it would be reasonable to |
| expect additional information such as the commit comment associated with the |
| change to also appear.</li> |
| </ul> |
| <p>The above is straight forward if there is a one-to-one mapping between files |
| and model elements. Repositories can typically provide the history for a particular |
| file efficiently. The model could then interpret each file revision as a model |
| change (i.e. the model provider could show a list of model element changes using |
| the timestamp of file changes as the timestamps for the model element changes). |
| If a user opened a particular change, the model provider would then load and |
| interpret the contents of the file in order to display it in an appropriate |
| way.</p> |
| <p>In the case where there are multiple model objects in a single file (many-to-one), |
| the model provider would need to interpret the contents of the file in order |
| to determine if the model element of interest actually changed in any particular |
| file change. This could result in potentially many file content fetches in a |
| way for which repository tooling is not optimized (i.e. repository tooling is |
| optimized to give you a time slice not to retrieve all the revisions of the |
| same file). One way to deal with this would be to have the model provider use |
| the file history as the change history for the model element with the understanding |
| that the element may not have changed between entries. Another possibility would |
| be to do the computation once and cache the result (i.e. the points at which |
| each element in the file changed) to be used in the future. As new revisions |
| of a file are released, the cache could be updated to contain the latest change |
| history. This would only need to consider the newest revision as he history |
| doesn't change. It may even be possible to share this history description in |
| the project.</p> |
| <p>The final case to consider is when a model element spans multiple files (one-to-many). |
| If the files that make up a model element never change, then it is simply case |
| of looking at the history of each file involved and building the element history |
| from that. However, it becomes more complicated if the number or location of |
| the files that make up a model element can change. The calculation of the change |
| history can then become quite expensive depending on how the files that make |
| up a model element are determined. For example, determining what files make |
| up a model element may require the contents of one of more files to be read. |
| Thus, you end up in the same situation as the many-to-one case. The same solutions |
| proposed for that case could also be used here.</p> |
| <p>The one-to-many case is interesting for another reason. Different repositories |
| provide different types of history. For instance, CVS only provides file based |
| history. In the UI, the history based CVS operations are only available for |
| files but not for folders or projects. That's not to say that the history couldn't |
| be obtained for a folder or project, it is just that it can be expensive to |
| determine (i.e. would require transferring large amounts of information from |
| the server). Other repositories could potentially provide higher level histories. |
| For instance, Subversion treats commits atomically so the history of a project |
| could be determined by obtaining the set of all commits that intersected with |
| the project.</p> |
| <p>This is important because supporting Team operations on logical model elements |
| blurs the distinction between files and folders. That is, logical model elements |
| adapt to ResourceMappings which could be a part of a file, a complete file, |
| a set of files, a single folder, a set of folders, etc. The question is whether |
| the ability to see the history of a model element should be available for all |
| model elements or for only some.</p> |
| <ul> |
| <li>One possibility would be to allow the repository tooling to decide, based |
| on the structure of a resource mapping, whether change history should be available. |
| For instance, CVS may only make history available for model elements that |
| adapt to one file (or a small number of files). It then becomes a repository |
| restriction as to what model elements history is available on.</li> |
| <li>Another is to have the repository tooling provide the ability for the model |
| tooling to calculate the history of arbitrarily large model elements with |
| the understanding that it might take a long time. The model tooling would |
| need to consider ways to improve the efficiency of how changes are determined |
| for this to be practical.</li> |
| <li>A hybrid approach would be to have the model tooling decide which elements |
| should have history based on a capability description of the repository. This |
| difficult part here is defining the capability description.</li> |
| <li>Another hybrid approach would be to have the model flag those elements for |
| which it must have history. The repository would do the best it could for |
| those and for others would decide on a case by case basis which should have |
| history. </li> |
| </ul> |
| <p>Supporting history on arbitrary model elements requires the repository to be |
| able to produce a time slice for each interesting change. This may be possible |
| for some repositories, such as Subversion since it supports atomic commits. |
| However, for others like CVS, there is no built in way to determine all the |
| files that belong to a single commit. This could potentially be deduced by looking |
| at a set of file histories and grouping the changes by timestamp but this would |
| be a prohibitively expensive operation. Another possibility would be to present |
| a reduced set of time slices based on version tags but this has it's own potential |
| failings (i.e. tags are done at the file level as well so there are no guarantees |
| that a tag represents the complete time slice of a project).</p> |
| <h3>Loading Logical Models</h3> |
| <p>Ideally, users would be able to browse their model structure in the repository |
| and pick those items which they wish to transfer to their workspace (i.e. checkout). |
| In Eclipse, projects are the unit of transfer between the repository and the |
| local workspace. This has the following implications:</p> |
| <ul> |
| <li>Multi-project models (i.e. models that span projects) would require additional |
| support to identify the relationship between the projects.</li> |
| <li>Partial project loading (i.e. the ability to load a subset of the model |
| elements persisted in a project) would require additional repository tooling |
| support.</li> |
| </ul> |
| <p>The majority of the work here would need to be done by the repository tooling. |
| That is, they would need to provide remote browsing capabilities and support |
| partial project loading if appropriate. The ability to support cross-project |
| references would also need additional API in Team that allowed these relationships |
| to be stated in such a way that they could be shared and converted back to a |
| project.</p> |
| <h2><a name="EMF"></a>The Potential Role of EMF</h2> |
| <p>Although not part of the Platform, it is worth while to mention the potential |
| role of EMF in a lot of the areas touched by this proposal. For EMF models, |
| much of the required implementation could be done at the EMF level thus simplifying |
| what models would need to do. Some possibilities are:</p> |
| <ul> |
| <li> An EMF Resource Mapping that provides the mapping of the model object to |
| files and also could provide the change determination code. </li> |
| <li>At least partial implementations of the synchronize, compare and merge API</li> |
| </ul> |
| <p>The following sections mention some of the issues we've come across when prototyping |
| using EMF.</p> |
| <h3>Identifying Model Objects</h3> |
| <p>One of the requirements for supporting team operations on logical models is |
| to be able to identify and compare model elements. By default, EMF uses object |
| identity to indicate that two model elements are the same element. This works |
| when you only have one copy of the model. However, for team operations, there |
| can be multiple copies of the model (i.e. local, ancestor and remote). EMF does |
| support the use of GUIDs (i.e. when XMI is used) but it is not the default.</p> |
| <p>This brings rise to another issue. Team operations can involve up to 3 copies |
| of a model. Putting and keeping all 3 models in memory has performance implications. |
| A means of identifying a model element without requiring that the entire model |
| be loaded would be helpful. </p> |
| <h3>IAdaptable</h3> |
| <p>Another issue is that EMF objects do not implement <code>IAdaptable</code> |
| but any objects that adapts to a <code>ResourceMapping</code> must. One solution |
| would be to have <code>EObject</code> implement IAdaptable but this is not possible |
| since EObject cannot have dependencies on Eclipse. This means that the owner |
| of the model must ensure that each of their model objects that adapt to <code>ResourceMapping</code> |
| implement <code>IAdaptable</code> and their <code>getAdapter</code> method match |
| that found in <code>org.eclipse.runtime.PlatformObject</code>. Another option |
| is to remove the assumption made by clients that only objects that implement |
| <code>IAdaptable</code> can be adapted. This is tricky since anyone can be a |
| client of the adaptable mechanism. We can ensure that the SDK gets updated but |
| can make no guarantees about other clients.</p> |
| <h2><a name="TeamScenarios"></a>Team Scenarios</h2> |
| <p>In this section, we describe what some Team scenarios might look like with |
| the logical model integration enhancement we have discussed in previous sections. |
| We will describe the scenarios in terms of CVS. </p> |
| <h3>Updating the Workspace</h3> |
| <p>In this scenario, the user selects one or more model elements and chooses Team>Update. |
| Currently what happens is each file that is updated will get it's new contents |
| from the server. For files that have both local and remote modifications, the |
| server attempts a clean merge but if that is not possible, the file will end |
| up containing CVS specific markup identifying the conflicting sections. For |
| binary files, no merge is attempted. Instead, the old file is moved and the |
| new file downloaded. In both these cases, it is the users responsibility to |
| resolve the conflicts by editing the file in order to remove any obsolete lines |
| and the CVS conflict markup or decide which version of the binary file to keep, |
| respectively. It should be noted that this "after-the-fact" conflict |
| resolution will not be acceptable for many higher level models.</p> |
| <p>The goal of a Team>Update is to do an auto-merge if possible and only involve |
| the user if there are conflicts that need to be resolved. For operations in |
| the file model space, this can be done on a file by file basis. That is, an |
| auto-merge can be attempted on each file individually and only those files for |
| which the auto-merge is not possible would require user intervention. This should |
| be fairly straight forward to implement for CVS. The <code>IStreamMerger</code> |
| interface that was added in Eclipse 3.0 can be used to determine whether an |
| auto-merge is possible and perform the merge if it is. The files for which an |
| auto-merge is not possible could then be displayed in a dialog, compare editor |
| or even the sync view in order to allow the user to resolve any conflicts.</p> |
| <p>It is not clear that this file-by-file approach would be adequate for merges |
| involving higher level model elements. The reason for this is that it is possible |
| for a model element to span files. Auto-merging one of those files while leaving |
| another unmerged may corrupt the model of disk. The decision about when auto-merge |
| is possible and when it is not can only be made by the model tooling. Therefore, |
| some portion of the merge will need to be delegated to the model. </p> |
| <p>There are several sub-scenarios to consider:</p> |
| <ul> |
| <li><strong>Update of one or more files, folder or projects</strong>: the update |
| should only happen at the file level if there are no models participating |
| in Team operations on those files. If there are participants, then you will |
| end up in one of the next two scenarios depending on whether their are multiple |
| participants that match the selected files, folders or projects.</li> |
| <li><strong>Update of one or more model elements, all from the same model</strong>: |
| If the model has registered an <code>IResourceMappingMerger</code> with the |
| platform, then the merge of the model elements belonging to that model will |
| be delegated to the merger. The model merger will attempt an auto-merge at |
| the model level thus ensuring that the model on local disk is not corrupted. |
| If an auto-merge of one or more elements, is not possible, these will be returned |
| back to the Team operation for user intervention. The mechanics of this are |
| described in more detail below.</li> |
| <li><strong>Update of one or more model elements from different models</strong>: |
| In this scenario, each model would be given a chance to merge their model |
| elements in sequence. This is not really different than the previous case |
| except that it is conceivable that the merges made by one model may have a |
| negative effect on another model before it has a chance to perform it's merges. |
| This may be acceptable as it is hard to conceptualize how two independent |
| model providers could co-exist peacefully with that kind of overlap. </li> |
| </ul> |
| <h4>Auto-Merging</h4> |
| <p>When updating a model element, it may be possible that the merge is possible |
| at the model level. In other words, if an <code>IResourceMappingMerger</code> |
| is available for one or more resource mappings, the merge can be performed by |
| the model without ever dropping down to a lower level merge (e.g. file level |
| merge). This makes the assumption that the model doing the merge will not do |
| anything that corrupts lower level models. However, it does not ensure that |
| higher level models will not be corrupted. Hence, ideally, the Team operation |
| would still need to check for participants at the model level to ensure that |
| higher level models in order to include other resource mappings in the merge |
| if required.</p> |
| <p>If no model level merge is available, the update will need to be performed |
| at the file level. This means that participants at the file level must be queried |
| for additional resource mappings and then the merges can then be performed on |
| these files using the appropriate <code>IStreamMerger</code>.</p> |
| <p><strong>Manual Merging</strong></p> |
| <p>Model objects that cannot be merged automatically need to be merged manually. |
| There are two main pieces required to create a UI to allow the user to perform |
| the manual merge:</p> |
| <ul> |
| <li>A view (most likely a tree) that displays the model elements to be merged. |
| Ideally, this view should show the synchronization state of each element and |
| should also show the relationship between the files and model elements being |
| merged. It may be possible to extend the Team synchronization framework to |
| provide this functionality.</li> |
| <li>From each separately mergable element, it should be possible to open a compare |
| editor that supports the merging of that model element. It is not necessary |
| for each visible element to be mergable as some elements may act simply as |
| organizational elements. These elements would appear near the top of the tree. |
| Lower level elements (leaves but possibly others) should be openable (although |
| the merge editor that is opened may contain other elements if that was how |
| the model deemed that they should be merged at the same time.</li> |
| </ul> |
| <p>Both of these pieces must be available given a set of resource mappings. The |
| adaptable mechanism should be adequate to provide these in whatever form they |
| take. If either are absent, the manual merges can still be performed at the |
| file level.</p> |
| <h3>Committing or Checking In Changes</h3> |
| <p>For repositories, check-ins or commits happen at the file level. Here are some |
| considerations when supporting commits on logical model elements.</p> |
| <ul> |
| <li>The user must be made aware of any additional model elements that will be |
| included in the commit due to there relationship to the files being committed. |
| For example committing an element that is persisted in a file with other elements |
| will also result in the committing of all the other elements in that file.</li> |
| <li>The elements being committed should be displayed in a model appropriate |
| way.</li> |
| <li>Appropriate feedback should be provided to the user if the commit cannot |
| proceed to to conflicts.</li> |
| </ul> |
| <p>Ideally, what the user would like to see is all the files and model elements |
| being committed arranged in such a way that the relationships between them are |
| obvious. If additional elements to those that were originally selected are included |
| in the commit, these should be highlighted in some manner.</p> |
| <h3>Tagging Elements</h3> |
| <p>Tagging in repositories happens at the file level and, at least in CVS, can |
| only be applied to content that is in the repository. This leads to the following |
| two considerations when tagging:</p> |
| <ul> |
| <li>The user needs to be made aware of any outgoing changes that will not be |
| tagged.</li> |
| <li>Tagging a model element that is persisted in a file with other model elements |
| may also result in those elements being tagged (i.e. the tag is applied to |
| the file and, hence, any elements contained in the file.</li> |
| </ul> |
| <p>The above two points really require two different views. The first is much |
| like the view used for committing where the user sees any outgoing changes but |
| this time with a message indicating that it is the ancestor state of these elements |
| that will be tagged. The second is just a model based view that highlights those |
| elements that will be tagged but were not in the original selection.</p> |
| <h3>Replacing Elements</h3> |
| <p>Replacing is similar to Update but is not as complicated as the local changes |
| are discarded and replaced by the remote contents (i.e. no merging is required). |
| However, there are the following considerations:</p> |
| <ul> |
| <li>The user needs to be made aware of any outgoing changes that will be lost.</li> |
| <li>Replacing a model element that is persisted in a file with other model elements |
| may also affect those elements.</li> |
| </ul> |
| <p>The requirements here are similar to tagging except that the determination |
| of additional elements is based on what the incoming changes are and, hence |
| could be displayed in a synchronization type view. There are similarities with |
| update in the sense that the existence of an <code>IResourceMappingMerger</code> |
| may mean that extra elements need not be affected at all.</p> |
| <p>As with Update, Replacing could be performed at the model level if the model |
| has an associated <code>IResourceMappingMerger</code>. The mechanics would be |
| similar to Update except that no manual merge phase would be required. Also, |
| the model merger would either need a separate method (<code>replace</code>) |
| or a flag on the <code>merge</code> method (<code>ignoreLocalChanges</code>) |
| to indicate that a replace was occurring. When performing a replace, the ancestor |
| context is not required.</p> |
| <h3>Synchronizing and Comparing</h3> |
| <p>The ability to provide model support in the synchronize view would be a natural |
| byproduct of several of the requirements discussed above. To summarize, what |
| would be required is:</p> |
| <ul> |
| <li>The ability to display the synchronization state of model elements.</li> |
| <li>The ability to trigger auto-merges on selected model elements.</li> |
| <li>The ability to open a compare editor in order to perform a manual merge.</li> |
| </ul> |
| <p>These are all included as requirements for previously mentioned operations. |
| The only additional requirement for Synchronize view integration is that the |
| synchronization state display must keep itself up-to-date with local file system |
| changes and remote changes. The synchronize view already has infrastructure |
| for this at the file level which the model provider could use to ensure that |
| the model elements in the view were kept up-to-date.</p> |
| <h2>Summary of Requirements</h2> |
| <p>This section presents the requirements on various parties for this proposal. |
| The parties we consider are the Eclipse Platform, Model Providers and Repository |
| Providers.</p> |
| <h3>Eclipse Platform</h3> |
| <p>The 3.2 Eclipse Platform release schedule is:</p> |
| <ul> |
| <li>Friday Aug. 12, 2005 - Milestone 1 (3.2 M1) - stable build </li> |
| <li>Friday Sep. 23, 2005 - Milestone 2 (3.2 M2) - stable build </li> |
| <li>Friday Nov. 4, 2005 - Milestone 3 (3.2 M3) - stable build </li> |
| <li>Friday Dec. 16, 2005 - Milestone 4 (3.2 M4) - stable build </li> |
| </ul> |
| <p>The Platform work for the items is this proposal and their target availably |
| dates are:</p> |
| <ul> |
| <li>Model Aware Problems View |
| <ul> |
| <li>Improve filtering (available in 3.2 M2)</li> |
| <li>Generic problem fields (3.2 M3: bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=111058">111058</a>)</li> |
| <li>Model aware selection filter (3.2 M3: bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=111054">111054</a>)</li> |
| <li>Problem type specific Show in (3.2. M3: bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=111057">111057</a>)</li> |
| <li>Problem type specific details pane (investigate for 3.2 M3 bug <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=111059">111059</a>)</li> |
| <li>Context aware filtering (investigate in 3.2 M3 and target 3.2 M4)</li> |
| <li>Model specific filters (investigate in 3.2 M3 and target 3.2 M4)</li> |
| </ul> |
| </li> |
| <li>Context Awareness |
| <ul> |
| <li>Perspective/window level control over view filtering (investigate in |
| 3.2 M3 and target 3.2 M4)</li> |
| <li>Out-of-context operation participation (investigate in 3.2 M3 and target |
| 3.2 M4)</li> |
| </ul> |
| </li> |
| <li>Common Navigator |
| <ul> |
| <li>Accept contribution from WTP (should happen in 3.2 M3)</li> |
| <li>Team Contexts (gated by Common Navigator: target 3.2 M4) |
| <ul> |
| <li>Provide helper classes to ease implementation and use of the API</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li>Model Level Merging |
| <ul> |
| <li>Define the API (3.2 M3)</li> |
| <li>Provide CVS implementation (3.2 M3)</li> |
| <li>Provide helper classes to ease implementation and use of the API (3.2 |
| M4) </li> |
| </ul> |
| </li> |
| <li>Remote Discovery (investigate in 3.2 M3, too early in investigation to commit |
| to a target date)</li> |
| </ul> |
| <p>Target dates are given for all items but this may be subject to change, especially |
| for those items currently under investigation. For Remote Discovery, we are |
| too early in our investigation to commit to a delivery date.</p> |
| <h3>Model Providers</h3> |
| <p>The model providers will need to do the following work to make full use of |
| the support outlined in this proposal.</p> |
| <ul> |
| <li>Adapt model elements to <code>ResourceMapping</code>.</li> |
| <li>Define a <code>ModelProvider</code> for determining team operation participation.</li> |
| <li>Provide an <code>IResourceMappingMerger</code> for performing model level |
| merges</li> |
| <li>Provide a <code>NavigatorContentExtension</code> for the Common Navigator. |
| <ul> |
| <li>include support for team contexts |
| <ul> |
| <li>dynamic update based on resource and team changes</li> |
| <li>decoration using resource synchronization states</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li>Provide context specific configuration information to configure views that |
| appear in the model provider's perspective (the nature of which is to be determined). |
| Some potential configuration points are: |
| <ul> |
| <li>Problems view filters</li> |
| <li>Navigator filters</li> |
| <li>Operation participation/veto</li> |
| </ul> |
| </li> |
| </ul> |
| <p>The model can chose whether to provide any, all or some of the above facilities. |
| If they do not, then a suitable resource-based default implementation will be |
| used.</p> |
| <h3>Repository Providers</h3> |
| <p>Repository providers will need to provide the following:</p> |
| <ul> |
| <li><code>RemoteResourceMappingContext</code> that allows the model to view |
| the ancestor or remote state of the repository.</li> |
| <li><code>ISynchronizationContext</code> that allows the model to query the |
| synchronization state of the local resources with respect to the ancestor |
| and remote repository state.</li> |
| <li><code>IMergeContext</code> which supports programmatic invocation of merge |
| operations</li> |
| <li>Remote Discovery API the nature of which has yet to be determined</li> |
| </ul> |
| <p>The repository provider can decide which model provider facilities to make |
| use and only using a subset may reduce the amount of work a repository provider |
| must do. However, to achieve rich integration requires the repository provider |
| to implement everything.</p> |
| <h2>Open Issues</h2> |
| <p>Here are some open issues and questions</p> |
| <ul> |
| <li>One of the issues presented in this document is that of model structure |
| vs. tree view structure. Often times these are the same but in some instances |
| they differ due to the use of content providers. When they differ, should |
| team operations and item decoration correspond to the model structure or the |
| view structure? I think it is safe to say that which ever approach is deemed |
| more suitable, the same approach should be used for both decoration and team |
| operations so that a consistent message is shown to the user. That is, clicking |
| on a dirty item in a view and choosing to commit or check-in the item should |
| always result in something being checked-in.</li> |
| <li>A related issue is that of view filter. If a view is filtering out particular |
| elements, should a Team operation on a parent of that element include the |
| element or not? Currently it does. That is, if you filter elements out of |
| the Navigator or Packages Explorer they will still be included in Team operations |
| on their parent. Whatever the chosen approach is, it should be applied to |
| both Team operations and decorations.</li> |
| <li>Another question that remains is whether repository providers and model |
| providers can implement these interfaces. We are confident that we can make |
| this work for CVS but other repository providers are still a question mark. |
| The Platform lacks any complex models so it is hard for us to judge how hard |
| this would be to do for such models.</li> |
| </ul> |
| <h3>Assumptions and Limitations</h3> |
| <p>Here are some assumptions we have made or limitations that may exist.</p> |
| <ul> |
| <li>We have attempted to address the issue of model overlap by allowing participants |
| to include additional resource mappings in a tam operation. However, this |
| mechanism will only ensure that the additional resource mappings are included. |
| The presentation and operation on these separate models will happen independently. |
| If there are implicit dependencies between these models, it is possible that |
| an operation on one will corrupt the other. The proposed solutions currently |
| do not address this issue.</li> |
| <li>Currently, resource mappings are provided by the model objects (using the |
| adapter mechanism). This assumes that all the elements in the same view with |
| that element come from the same model. It is conceivable that a view could |
| be showing elements from multiple models. This is not addressed by this proposal.</li> |
| </ul> |
| <h2>Change History</h2> |
| <p>Changes in Version 0.3</p> |
| <ul> |
| <li>Expanded Common Navigator section to include description of the relationship |
| between the context of a team operation and the Navigator content extension.</li> |
| <li>Added Operation Veto subsection to Maintaining Workspace Consistency section.</li> |
| <li>Changed Team Operation Input Determination section to use of Model Providers |
| instead of Team Participants.</li> |
| <li>Added Team Aware Model Views subsection of the Decorations section which |
| describes an alternate approach to providing team decorations.</li> |
| <li>Updated the Model Level Merging section to incorporate the team context |
| concept.</li> |
| <li>Updated the Displaying Model Elements in Team Operations sections to reflect |
| that these requirements can be met using team contexts.</li> |
| <li>Added Summary of Requirements section</li> |
| </ul> |
| <p>Changes in Version 0.2</p> |
| <ul> |
| <li>Added Scenario descriptions to Remote Discovery section.</li> |
| <li>Reworded EMF section to more accurately reflect the issues.</li> |
| <li>Added reference and link to the <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/platform-ui-home/R3_1/contributions-proposal/requestForComments.html">Improve |
| Object Contributions</a> proposal from the Maintaining Workspace Consistency |
| section.</li> |
| <li>Added statement of repository/model requirements to Team Operations on Model |
| Elements section.</li> |
| <li>Added explicit lifecycle description to Team Operations section</li> |
| </ul> |
| <p> </p> |
| <p> </p> |
| </body> |
| </html> |