blob: 283245d82fa7d98b5114288ba1cb7d7b848c23a9 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Enabling Logical Model Integration in the Eclipse Platform</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
</head>
<body>
<h1>Enabling Logical Model Integration in the Eclipse Platform</h1>
<p>This document tries to capture the issues that are related to
integrating logical models into the Eclipse Platform. This is a
reiteration of what was captured <a href="logical-physical-public.html">here</a>
but tries to present the set of model characteristics of interest along
with related scenarios. The focus is not on defining a general API for
logical models. Instead, the focus is on identifying those points in
the Platform that degrade the user experience when working with logical
models and identifying possible solutions to these issues. The focus is
also on those issues that involve maintaining model consistency both
locally and remotely in a repository.</p>
<p>First we will describe some of the different model characteristics that we
have seen in various modeling tools built on top of Eclipse. Then we will describe
several scenarios and how they relate to these model characteristics. The scenarios
contain descriptions of what the ideal workflows could be without considering
the viability of making these a reality.</p>
<h2>Model Characteristics</h2>
<p>This section describes several different model characteristics that
are common in model tooling. This list is general and it is most likely
that real models will have a combination of these characteristics.</p>
<h3><a name="m1"></a>M.1 Model Element Maps to a Single File (One-to-One)</h3>
<p>The most straightforward relationship between model elements and file system
resources is a one-to-one mapping. That is, a model element maps directly to
a file system resources. An example of this is a Java class (or compilation
unit) which maps directly to the file that contains the class. </p>
<h3><a name="m2"></a>M.2 Multiple Model Elements in a Single File (Many-to-One)</h3>
<p>It is often the case that a single file will contain multiple model elements.
A simple example of this is a Java file that contains multiple compilation units
or classes. Usually, a file contains a single class but multiple classes in
the same file is supported. In this case, classes that appear in Java views
will still correspond to a single file but performing operations that are resource
based, such as repository operations, on the class will include all classes
contained in the file in the operation.</p>
<h3><a name="m3"></a>M.3 Model Contains Fixed Set of Files (Fixed Relationship)</h3>
<p>In some models, a model element may consist of a fixed set of files. We will
use an example from the Eclipse plug-in structure. When developing plug-ins,
</p>
<ul>
<li>a <em>plugin.xml</em> file is used to determine certain
characteristics of the plug-in</li>
<li>a <em>plugin.properties</em> file is used to contain human
readable strings that appear in the plugin.xml. This is done to support
internationalization. Keys in the plugin.xml file reference entries in
the plugin.properties file.</li>
</ul>
<p>These two files are tied together in the sense that they are really
one entity that is stored in two files (in reality, there are other
files that are thus linked to the plugin.xml file but we'll only use
two files to keep it simple).</p>
<p>Another example of a fixed relationship is a Java package which consists of
all the direct file children of the package folder. That is, sub-folders of
the package folder (which model sub-packages) and the files that are contained
in those sub-folders are <span
style="font-weight: bold;">not</span> part of the Java package.</p>
<h3><a name="m4"></a>M.4 Model Contains Variable Set of Files (Variable Relationship)</h3>
<p>In some tools, several files are related to a single model object
through a map file or interfile references. For a simple case, consider</p>
<ul>
<li><em>A.map</em>: a map file that identifies (i.e. contains
references to) the files which make up a model element</li>
<li><em>AClass.java</em>: a java file contained in the model element</li>
<li><em>APage.jsp</em>: a JSP contained in the model element</li>
<li>potentially additional files referenced from the map file</li>
</ul>
<p>An additional restriction may be that the names of some or all of
the files have a common string in the file name (e.g. <em>A</em>).</p>
<h3><a name="m5"></a>M.5 Model Contains Strong References</h3>
<p> In some cases, it is possible to have a model that doesn't necessarily contain
certain files but cannot be reasonably rendered without them. An example of
this is a diagram that described the relationship between a set a Java classes.
The diagram will contain layout information and perhaps even some class relationship
information but will not likely duplicate information found in the classes themselves,
such as method signatures. If one or more of the classes in the diagram were
not available, it may not be possible to render portions of the diagram.</p>
<h3><a name="m6"></a>M.6 Multi-File Model is Atomic</h3>
<p> In some cases, a model may be persisted in several file system resources where
each file is meaningless on its own. An example would be a large diagram that
is divided into files but cannot be rendered if one of the files is missing.
This is similar to the fixed or variable relationship cases but has the added
characteristic that operations should never be performed on the file-system
resources individually. </p>
<h3><a name="m7"></a>M.7 Layered Models</h3>
<p>It is often the case that there are many model layers involved in a product.
Consider this layering:</p>
<ol>
<li>Platform resource model</li>
<li>Java model</li>
<li>J2EE</li>
<li>WSDL</li>
</ol>
<p>Each of these models is built on top of the lower layer (i.e. layer 2 is built
on top of layer 1, etc.). It is also true that the higher layers may be built
on top of several lower level model layers. We commonly refer to the mapping
of model elements to files as <em>logical-to-physical</em> mapping. We will
refer to mapping from one logical model to another as <em>logical-to-logical</em>
mapping.</p>
<h3><a name="m8"></a>M.8 Model Not Contained In Files</h3>
<p> It is worth mentioning the case where a model is not persisted in local files
but is instead persisted in some other location (e.g. a database). Some of the
scenarios that will be mentioned below are still relevant to this case (e.g.
problem reporting).</p>
<h2>Scenarios for Maintaining Model Consistency</h2>
<p>This section covers various scenarios, work flows or use cases that can potentially
have an effect on the consistency of a model. There are basically two methods
of maintaining model consistency:</p>
<ul>
<li>Ensure that operations performed on model elements do so in a manner that
preserves model consistency. This applies to both local operations (file content
modification, delete, rename, etc.) and remote operations (check-out, check-in,
update, tag as version, etc.).</li>
<li>Report any model inconsistencies to the user. Ideally, this should be done
in such a way as to point towards a solution. This could be done by linking
problems to editors or even providing QuickFixes for fixing the problem.</li>
</ul>
<p>Ensuring that all the operations performed on a model will maintain
model consistency is fairly straight forward when operations are
launched from the tooling associated with the model in question.
However, it is often the case that operations are performed on the
elements of lower level models directly. For instance, a user who edits
the <em>plugin.properties</em> file directly may remove an entry that
is still referenced by the <em>plugin.xml</em> file. Or, in the
layered model case, a user may delete a Java file that is contained in
a model element of a higher level model. These types of changes lead to
a greater chance of models becoming inconsistent.</p>
<p>The work flows in the section are related back to the model characteristics
described previously with descriptions of what currently occurs as well as what
would be the desirable behavior. The statement of the desirable behavior is
by no means a statement of the viability of such a solution. It is only something
to shoot for.</p>
<h3><a name="s1"></a>S.1 Problem Reporting</h3>
<p>Currently in Eclipse, dealing with model inconsistencies is mainly
done using problem reporting. However, the mechanisms provided by
Eclipse (build, markers, Problems view) are highly file system centric.
This makes the reporting of problems difficult as they are always
associated with file system resources. This has several shortcomings:</p>
<ul>
<li>The relationship between a model and the underlying file system representation
may not be obvious to the user. </li>
<li>It is often the case that multiple problem markers are associated with a
single problem. In the current Problems view, there is no mechanism for displaying
this type of relationship to the user.</li>
</ul>
<p>Ideally, the Problems view should display problems that are associated with
any model element, whether it be a file-system resource or an element of a higher
level model. Furthermore, the ability to group related problems together using
a tree view or some other type of grouping mechanism would be helpful when the
user is presented with a lot of problems that are really all symptoms of one
larger problem.</p>
<p>The following sub-sections present specific problem reporting scenarios.</p>
<h4>Parse Errors</h4>
<p>Consider the case where a model element is persisted in at least one file which
is XML. If that file cannot be parsed, the XML parser will create a problem
marker that contains a description of the parse error. Here are some scenarios
related to this type of problem:</p>
<ul>
<li>In the many-to-one case (<a href="#m2">M.2</a>), the file may contain several
logical model elements, none of which can be recognized by the model tooling
due to the parse error. In this case, there may be no logical model element
to associate the error with. However, the model tooling may still which to
either annotate the problem representing the parse error with a more understandable
description or associate another problem with the file and have it wrap or
in some other way override the lower level problem. That's not to say that
the lower level problem would be entirely hidden from the user but instead
that it would be somehow grouped with the higher-level problem description.
This problem could also occur in the one-to-one or one-to-many cases if the
parse error prevented the model element from being recognized by the model
tooling.</li>
<li>In the one-to-many cases (<a href="#m3">M.3</a>, <a href="#m4">M.4</a>,
<a href="#m5">M.5</a>, <a href="#m6">M.6</a>), it is possible that the contents
of the unparsable file only constitute part of a model element. In this case,
the model tooling may wish to associate a problem with this logical model
element. The following should be considered:
<ul>
<li>The logical model element may or may not map to a file system resource.
In either case, it should be possible to have a problem appear in the
Problems view that is associated with the model element and contain a
description that makes sense in the model space.</li>
<li>The problem associated with the logical element should take precedence
over the lower level problem. Again, it could either override or parent
the lower level problem.</li>
</ul>
</li>
</ul>
<h4>Stale References</h4>
<p>Another case to consider is when model elements contain references to other
model elements (<a href="#m4">M.4</a>, <a href="#m5">M.5</a>). Changes to a
model element may cause references to become stale. That is, a referenced element
could be removed or modified in such a way as to make any references to the
element no longer valid. With the current Problems view, a problem could be
associated with the location in the file where the reference appears. If the
stale reference appears multiple times, then multiple markers could be created.
However, providing a link to the position in the file where the link appears
may not be enough to help the user to decide how to fix the problem. Also, the
user would need to fix the problem in each location it appeared. </p>
<p>Ideally, a single problem item should identify the existence of the stale reference.
This would allow the user to see the single cause of the multiple stale references.
It may still be desirable to associate problems with each of the elements that
contain stale references and also with each particular occurrence of a stale
reference but the user should only need to see the specific locations if they
decided to deal with each occurrence individually.</p>
<h4>Problems in Logical Models that Don't Map to Files</h4>
<p>Models that are not persisted in files (<a href="#m8">M.8</a>) may still have
model consistencies problem that should appear in the problems view. Currently,
problems cannot be associated with logical model elements that do not have a
corresponding resource unless the model tooling has it's own problems view.
Having multiple views that serve the same purpose is confusing for users.</p>
<h4>Filtering Problems By Selection</h4>
<p>The Problems view currently has the ability to filter by selection. This only
works when the items in the selection have a one-to-one mapping to file system
resources. Ideally, the following would be supported:</p>
<ul>
<li>Support one-to-many mappings (all problems associated with any resource
in the mapping should be shown).</li>
<li>Support many-to-one mappings (i.e. only those problem associated with a
portion of the file would be shown).</li>
<li>Support logical element containment filter (i.e. if a logical model element
is selected, show any problems that reference that model element).</li>
<li>Support logical-to-logical mappings (i.e. if a logical model element at
a higher level is selected, display problems for lower levels model elements
contained by the higher level element).</li>
</ul>
<p>With this support, the user could select any element in the UI and see what
problems existed for that element.</p>
<h4>Model Layering</h4>
<p>Many of the scenarios presented previously involve layered models. However,
it is worthwhile to mention specific instances of how model layering affects
problem reporting. The user will often work at a particular model level and
will therefore like to see problems stated in such a way that is consistent
with that layer. Thus is would be desirable to be able to:</p>
<ul>
<li>arrange problems by model layer: i.e. group problems associated with lower
level problems as children of a problem entry associated with the model layer
at which the user is working.</li>
<li>filter problems by model layer: i.e. hide errors of lower level models unless
the model level at which the user is working explicitly includes problems
from the lower layer.</li>
</ul>
<h3><a name="s2"></a>S.2 Operation Participation</h3>
<p>In this section we look at various operations and their effect on model consistency.</p>
<h4>File Rename and Deletion</h4>
<p>First, lets look at what happens when a file that is part of a model element
is renamed. The following conditions will result in model inconsistencies that
need to be corrected.</p>
<ul>
<li>The file may be referenced by a model element. This can happen in cases
<a href="#m4">M.4</a> and <a href="#m5">M.5</a></li>
<li>Other files may have a name that is linked to the name of the file as described
in <a href="#m4">M.4</a></li>
<li>The file is part of a fixed relationship as in <a href="#m3">M.3</a> or
is part of a model whose files should not be modified individually as in M.6.</li>
</ul>
<p>The currently supported solution for all these cases is for a builder to recognize
the inconsistency and place a problem marker on an appropriate file. The model
tooling could associate a QuickFix with the problem that would allow the user
to correct the problem in a single operation (as opposed to renaming all the
necessary files one-by-one) but that is the best they could do. </p>
<p>Ideally, the model tooling would want some or all of these abilities:</p>
<ul>
<li>The ability to augment the current operation with additional modifications.
For instance, any references could be updated and linked files renamed in
the same operation as the original file rename.</li>
<li>The ability to describe the augmentation that will take place to the user
as part of the UI of the original operation. The user will want to know of
any additional modifications that will take place, as well as any conditions
that will result in model inconsistency (i.e. the model tooling may not be
able to determine the proper augmentation that will preserve model integrity).</li>
<li>The ability to prevent the rename in the case where the model will be compromised
in such a way that recovery is not possible.</li>
</ul>
<p>File deletion is similar to the rename case with some additional considerations:</p>
<ul>
<li>Deleting a file may have a larger impact on containing model elements. For
example, for a diagram, removing a class may also invalidate several relationships
in the diagram. It may be desirable to make the user aware of the repercussions
before performing the delete.</li>
<li>Deleting a file that is an important part of a model element, as in <a href="#m6">M.6</a>,
could offer to delete the containing model element.</li>
</ul>
<h4>Folder Rename or Deletion</h4>
<p>The effects on model consistency are harder to determine on folder (or project)
deletion, simply because there are potentially many files being renamed or deleted.
It is possible that many file references may become stale upon folder deletion
but it is just as likely that all the files contained in or referenced by the
model were all contained in the same folder so deleting that folder may introduce
no inconsistencies.</p>
<h4>Content Modification</h4>
<p>There are two cases of interest when looking at file content modification.</p>
<ul>
<li>A model may be made up of multiple files that should never be modified directly
(as in case <a href="#m6">M.6</a>). In this case, any external modifications
should be prevented (or, at least, strongly discouraged).</li>
<li>File contents can be modified directly but may contain references embedded
by higher level model tooling. An example of this could be Java annotations
that are used by a diagram. Removing an annotation may have an adverse affect
on the diagram. The user should be made aware of what may occur.</li>
</ul>
<h4>The Effects of Model Layering</h4>
<p>For operation participation, the following list of issues arise when model
layering is considered:</p>
<ul>
<li>Each model layer may have it's own set of operations that could potentially
be participated in. For instance, a Java rename is different from a Resource
Navigator rename. Higher level models would need to be able to participate
in any operations of lower level models that may affect their model consistency.
For instance, for a file rename, model tooling that is build on top of Java
would want to participate in both the Java and Platform Resource rename operations.</li>
<li>Operations of higher levels may make use of those from lower levels. However,
the model tooling would only want to participate at one level (the highest
possible). A mechanism to disable participation at lower levels when higher
level participation takes place would be needed.</li>
<li>In those cases where participation at a higher level is not possible, the
model tooling may still want to participate at the lowest level (i.e. file
content modification, rename or delete). The types of operation augmentation
that occur at this level may be reduced due to the lack of knowledge of the
overall context of the operation, but the model may still wish to notify the
user of any model inconsistencies that are introduced.</li>
<li>Multiple models may be participating in a particular operation and may each
augment the operation with additional modification. A further complication
is that some may participate at higher levels while others may only participate
at lower levels.</li>
</ul>
<p>Some things to consider here are:</p>
<ul>
<li>One crucial aspect of any such participation mechanism is that it does not
have a significant performance impact. This is especially important if participation
at the lowest levels is supported as this path will be hit by most, if not
all, tools built on top of Eclipse.
<ul>
<li>Another aspect of performance is plug-in loading. Operations on lower
level models may be performed before the plug-ins of the higher level
models are even loaded. Declarative filtering may be needed to efficiently
prune the list of interested participants.</li>
</ul>
</li>
<li>There are a set of standard operations (create, delete, move and rename)
that apply across models. Operation participation would be simplified if these
standard operations were defined by the platform in some form.</li>
</ul>
<p>It is also interesting to note that Java refactorings support certain types
of participation (create, delete, move and rename).</p>
<h4>Working with Editors</h4>
<p>Although not technically a model consistency issue, opening an editor is similar
to performing other operations. Here are a few cases involving logical models
that impact the opening of editors.</p>
<ul>
<li>Each resource and/or element usually has a default editor associated with
it. For instance, clicking on a Java file will open a Java editor on that
file. However, if this file is part of a higher level model and is actually
generated by that model (case <a href="#m6">M.6</a>), the model tooling may
not want the user to edit the file directly. In this case, it may be more
appropriate for the default editor for such a Java file to be the editor of
the model used to generate the file.</li>
<li>Eclipse strives to have only one editor open on a particular resource, be
it a file system resource or a logical model element. Hence, opening an editor
on an element searches through the open editors to find a match before opening
a new one.
<ul>
<li>For model elements that contain one or more resources, this means that
opening up an editor on a file contained in the model element should match
an open editor on that model element.</li>
<li>In the case where a file may contain multiple editable model elements,
the user would not necessarily want the file to match with open editors
on the file sub-elements.</li>
</ul>
</li>
<li>Problems are linked to a location (i.e. line number) is a file. Eclipse
provides the capability of opening and editor on the problem and showing the
location of the problem. This is straightforward if the mapping from model
element to resource is one-to-one but has some complications in other cases:
<ul>
<li>If the editor that is opened is on a model element that contains multiple
files, some means of translating the file location to the appropriate
Area of the editor is needed. As an example, consider the plug-in model
in <a href="#m3">M.3</a>. A problem marker on a key in the plugin.properties
file should not only open the plug-in manifest editor but show the page
that deals with the NLS keys and highlight the offending key.</li>
<li>If the file contains multiple editable model elements, a means of opening
an editor on the appropriate model element is needed. This is less of
an issue if problems can be associated directly with model elements.</li>
</ul>
</li>
</ul>
<h3><a name="s4"></a>S.3 Working with Repositories</h3>
<p>When working with logical models, the user would like to be able to select
logical model elements that appear in Eclipse and perform repository operations
on them. However, repository tooling tends to be file based so a conversion
from the model space to the file system resource space is required. We have
introduced <a href="logical-physical-mappings.html">API in 3.1 M5</a> that supports
the mapping of logical elements to their underlying file system resources. As
of 3.1 M5, the following is support:</p>
<ul>
<li>Model elements with one-to-one mappings to resources have always
been supported.</li>
<li>Model elements with one-to-many mappings, can now be the input to
repository operations.
<ul>
<li>Fixed relationships are the easiest as the remote state of
the model is not required</li>
<li>For variable relationships, additional API is specified to
allow the model to query the remote state in order to determine if
there are additional resources in the remote copy of the model.</li>
</ul>
</li>
<li>Model elements with many model elements in a single file can still be input
to a repository operation. However, the set of model elements being affected
may be greater than the set the operation was performed on. For instance,
if a *.java files contains multiple classes, performing a repository operation
on any of the contained classes will perform the operation on all the contained
classes. </li>
</ul>
<p>The following sections highlight issues that still exist.</p>
<h4>Model Participation in Repository Operations</h4>
<p>There are some cases where a model may want to participate in repository operations
for the purpose of augmenting the list of model elements or file system resources
that are being operated on. Examples of when this may be necessary are:</p>
<ul>
<li>If a repository operation is performed on a single model element that is
contained in the same file with other model elements (case <a href="#m2">M.2</a>),
the user will need to be made aware of the additional model elements that
will be included in the operation.</li>
<li>If the file being operated on is part of a model that should be treated
as an atomic unit (case <a href="#m6">M.6</a>), then any operations on the
file itself should instead be performed on the entire model.</li>
<li>If multiple model layers are involved, repository operations on elements
in lower layers may have a corrupting affect if the higher layers are not
involved. Some means of making the user aware of this and potentially including
additional resources in the operation may be helpful.</li>
</ul>
<p>The repository tooling may also need to obtain additional input from the user.
Although the operation is being performed on file system resources, the relationship
between the resources and the originating model should be made obvious to the
user.</p>
<h4>Model Participation in Merging</h4>
<p>One of the more complicated scenarios involving repository operations is that
of merging remote changes with local changes. Eclipse has API which supports
model based merging for the one-to-one case (<a href="#m1">M.1</a>). This API
could also be used to handle the many-to-one case (<a href="#m2">M.2</a>). However,
there is currently no mechanism for performing an atomic merge on a model element
that contains multiple files. What would be required in this case is API between
the model tooling and repository provider in order to reconcile the logical
model to the physical model when performing repository operations such as merging.
</p>
<p>One potential complication is that a merge operation may involve model elements
form different model layers or from different model tooling. Either there would
need to be a single merge mechanisms that was capable of performing merges on
multiple models simultaneously or the merges would need to be sequences. The
former case is more desirable than the later from a usability standpoint.</p>
<h4>Decorations</h4>
<p>Decorating elements that appear in the UI with their state relative to the
repository provides valuable feedback to the user in some cases. One such case
is a dirty decorator that, when present, indicates that the element has changed
locally since the time it was loaded from the repository. </p>
<ul>
<li>For the one-to-one and one-to-many case, showing the dirty decoration is
straightforward in the sense that the element is dirty if any of it's contained
files are dirty. </li>
<li>For the many-to-one, if the file is dirty, it is impossible to determine
which particular element is dirty without the ability to compare the new file
contents with the contents in the repository. Fetching the contents from the
repository is not something that should be done when calculating decorations.</li>
</ul>
<h4>Bootstrapping</h4>
<p>A related issue is that of bootstrapping. In other words, how does a
user load model elements that were created by other users. To do this,
a root access point is required. In Eclipse, the project acts as this
root. Therefore, the user must first load a project and can then access
the model elements it contains. In the cases where models span
projects, Team projects sets can be used to bootstrap a workspace.</p>
<p>There are a couple of issues involving the use of project sets in
this way:</p>
<ul>
<li>Project set creation is separate from repository operations. This means
that the user that shares a model must also remember to create a project set.
If the model spans projects, they must understand which projects are to be
included. </li>
<li>Projects sets are just files. If projects are added to or removed from a
project set, the project set file must be regenerated and redistributed.</li>
<li>A project set just contains a set of projects. There is no statement of
relationships between other project sets.</li>
</ul>
<p>One simple means of addressing this may be to support the grouping projects
together in a way that ensured that if one got loaded from a repository, they
all got loaded.</p>
<h2>Summary</h2>
<p>The required support for the scenarios presented in this document can be broken
down into three separate features:</p>
<ol>
<li>Generic views</li>
<ul>
<li>the main view of interest for model consistency issues is the Problems
view </li>
</ul>
<li>Repository operations available on logical models</li>
<ul>
<li>repository provider operations available on model elements that
appear in the UI</li>
<li>while performing an operation, repository provider should show
information in a form consistent with the originating model</li>
</ul>
<li>Operation Participation
<ul>
<li>The ability for model tooling to participate in the
operations of lower level models (e.g. Java or the Platform resource
model) in order to ensure model consistency</li>
</ul>
</li>
</ol>
<p>Although there is some overlap between these features, they can each be addressed
as separate issues.</p>
</body>
</html>