Skip to main content
Jump to: navigation, search

Difference between revisions of "Mylyn/Integrator Reference"

(Commons UI)
(Commons API)
Line 53: Line 53:
 
'''Mylyn 3.0 only'''
 
'''Mylyn 3.0 only'''
  
The Mylyn Commons API provides common facilities that are used by the other Mylyn components.  The Commons facilities can be reused without biringing in any other Mylyn dependencies.  Note that some of the Commons components provide tentative API that is identified with a <code>provisional</code> segment in the package name.  While the corresponding classes are being used by Mylyn components, we are still seeking integrator input on them and as such they are subject to change, and will move out of the <code>provisional</code> package once their API has been hardened.
+
The Mylyn Commons API provides common facilities that are used by the other Mylyn components.  The Commons facilities can be reused without biringing in any other Mylyn dependencies and have very limited set of Eclipse Platform dependencies.  Note that some of the Commons components provide tentative API that is identified with a <code>provisional</code> segment in the package name.  While the corresponding classes are being used by Mylyn components, we are still seeking integrator input on them and as such they are subject to change, and will move out of the <code>provisional</code> package once their API has been hardened.
  
 
== Commons Core ==
 
== Commons Core ==

Revision as of 21:47, 30 April 2008

link title

Also see: Mylyn Architecture, Mylyn Contributor Reference

We recommend that those interested in integrating Mylyn email mylyn-dev@eclipse.org regarding for pointers to examples and guidance on upcoming changes. We encourage integrators to take the "better to ask for forgiveness than permission" approach to adding and updating wiki documentation. Committers review all changes and will update them as needed. Evolving the documentation with integrator contributions works well because it ensures that the documentation takes the perspective of newcomers. It also helps committers dedicate more time to responding to requests for improving the corresponding APIs.

Building on Mylyn

Also see: Mylyn Porting Guide for porting from Mylyn 1.0 to the 2.0 stream.

Feature configuration

When integrating Mylyn with an existing tool, we recommend creating a new feature that declares a dependency on both the corresponding Mylyn feature and on the plug-ins and features of the tool. The new feature can then be deployed on the integrators' update site, and the update manager will require that the correct version of Mylyn is installed before allowing the new feature. The Subversive can be used as an example of this.

Workspace setup

The recommended workspace setup for integrators is check out the projects to be extended from CVS. Instructions and project sets are available on in the Workspace Setup documentation. If you would like a downloadable distribution that is not available on the download page please submit a bug report.

In order to detect and protect yourself from API misuse, we highly recommend using the Eclipse API Tools.

Deciding on a version

We suggest targeting the Mylyn 2.x stream because we will be encouraging all users to update to the milestones and will not be destabilizing. So check out the HEAD project set. The main cost of building against the 2.0 stream is that the APIs will be evolving so you will want to periodically check the Mylyn Porting Guide. Note that if you build against the HEAD stream your plug-in will most likely support both Eclipse 3.3 and 3.2 because our APIs generally insulate the connector from the Platform internals that we use. But you will want to verify this yourself by building against 3.2 before you deploy.

Watching API changes

If you are developing against the Mylyn 2.0 stream, you can watch for breaking API changes by creating a query for all Mylyn bugs tagged [api]. Major API changes will be announced on the mylyn-dev mailing list.

Also see: Mylyn Porting Guide

Innovating and Experimenting

One of the key challenges with building innovative or experimental tools and solutions is to get the UI friction low enough to get enough people to try it, without investing a ton of time into the UI work since that can take time away from the core work and evaluation. Some tips:

  • Decide and communicate whether you want the plug-in to be something that people experiment with, or something that they use for their daily development.
  • If the plug-in is to be used for daily development, it should have a very low performance footprint. What's most important is that it does not slow down the user's Eclipse when it is not being used, otherwise many users will quickly disable it.
  • When your plug-in is doing any background work, make sure to have that indicated in the Progress view (via the Jobs API). This will help people trust the tool, since their Eclipse could be getting slowed down by something else.
  • Decide carefully on the UI that's needed to enable early adopters to make use of your tool. Eclipse users tend to have a very high expectation of UI polish, and UI work can dominate implementation time. Try to reuse existing UIs as much as possible. When adding new UI, it can help to follow the Eclipse UI guidelines (either the document or by example) since this will make it easier for people to use your tool without needing to read documentation.
  • Eat your own dogfood as much as possible. If you expect others to be able to use the tool you should be able to use it yourself (as long as you are representative of the target audience). One of the key benefits of consuming what you produce is that it will help you prioritize both the performance and the UI work.
  • Provide people with a public forum for feedback, since open discussion is important to many of the open source contributors who may try it. If you do not have a forum available you can start a discussion thread on the Mylyn newsgroup.
  • In order to get support specific to your tool from the Mylyn committers create a Mylyn bug called "support integration with MyCoolTool".

Commons API

Mylyn 3.0 only

The Mylyn Commons API provides common facilities that are used by the other Mylyn components. The Commons facilities can be reused without biringing in any other Mylyn dependencies and have very limited set of Eclipse Platform dependencies. Note that some of the Commons components provide tentative API that is identified with a provisional segment in the package name. While the corresponding classes are being used by Mylyn components, we are still seeking integrator input on them and as such they are subject to change, and will move out of the provisional package once their API has been hardened.

Commons Core

Provides the StatusHandler API for handling errors, as well as additional utility classes.

Commons Net

Provides an API for the Apache HttpClient connections that Mylyn Tasks API Connectors use for web service connectivity.

Commons UI

Provides common widgets and workbench extensions used by other Mylyn components. Entry points include:

  • AbstractFilteredTree: a filtered tree that provides an adaptive refresh policy, useful for tress with thousands of nodes or more
  • AbstractNotification: desktop notification popups bug 177974
  • CommonColors: color constants used through the Mylyn UI
  • CommonFonts: fonts used by Mylyn
  • CommonThemes: theme extensions used by Mylyn
  • DatePicker: date selection widget, a dialog class is also available
  • ScreenshotCreationPage: a wizard page that lows the user to capture the desktop and premits markup of screenshots bug 214379

Tasks API

A tutorial with screenshots is available here: http://jvliet.blogspot.com/2007/02/creating-mylar-connector-plugin-for.html.

Use Cases

See http://www.ibm.com/developerworks/java/library/j-mylyn1

Accessing the Task List

Get the Task List: TaskList taskList = TasksUiPlugin.getTaskListManager().getTaskList();

Retrieve all categories: Set<AbstractTaskCategory> categories = taskList.getCategories();

Retrieve all queries: Set<AbstractRepositoryQuery> queries = taskList.getQueries();

Call getChildren() on these returned types to get all AbstractTask objects contained within.

Task repository requirements

Mylyn can be extended to any task/bug/issue/story repository or tracker by creating a repository Connector that links Mylyn's task management facilities with the repository. Connection to the task repository is handled by the Connector (e.g. via HTTP/REST for the Bugzilla Connector, via SOAP for the JIRA Connector). The following are required to support task list integration:

  • Identifying tasks: must be uniquely identifiable by a per-repository integer or string handle (e.g. repository: bugs.eclipse.org/bugs, id 138144). ID must be robust to task renames, moves within components and categories, etc.
  • Retrieving tasks: mechanism for retrieving the attributes for a task given an ID. Attributes can typically include the description, priority, assignee and comment thread. For example, REST is the mechanism used by the Bugzilla Connector (POST request asks for bug ID, and XML as the return format, example), and SOAP is the mechanism used by the JIRA Connector.
  • Performing queries: mechanism for executing a string-based query and returning all of the matching task IDs. Preferrably encoded as a URL to allow interoperability with the web UI. For example, the Bugzilla Connector issues a POST request with the query URL, and specifies that the return format should be RDF, example.

The following additional mechanisms enable rich editing:

  • Retrieving all of the operations possible on a task given login credentials (e.g. ability to reassign, change priority)
  • Accessing all of the repository attributes (e.g. lists of products, components, versions), example
  • Setting any of the task's attributes (e.g. changing components, reassigning)
  • Adding and retrieving attachments (e.g. posting patches, screenshots)

The following are optional:

  • Notification of changes (e.g. RSS-based notification of an update made via that web UI)
  • Retrieving a user's saved queries (e.g. searches or filters saved via the web UI)

Dynamic repositories with user configurable attributes per task:

The case may be that most of the attributes for your particular repository are highly customizable and user defined. A connector can be written for this scenario but will require a bit more plumbing. At the very least, you will need to map the id and summary of your repository artifacts to Mylyn task data attributes. These fields are the minimal requirements to give your 'task' representation in the task list. Depending on when you retrieve the set of possible attributes and values, you will likely either store it in your connector specific repository configuration (see how the Bugzilla Connector does this for an example) or on a per ticket basis with the RepositoryTaskData (note that RepositoryTaskAttribute held within RepositoryTaskData has a meta data facility that can be used to store arbitrary key,value pairs and can be very useful in this case).

The rich editor support will also require extra effort since you will need to provide custom implementations for most of the editor sections to handle your dynamic attributes. You may just opt to to have a single custom attributes section and eliminate the other sections of AbstractRepositoryTaskEditor.

Integrating with Mylyn's Task List vs. using a custom view

The Mylyn Task List has a considerable amount of functionality that is related to working with queries and to rich editing. For example, it shows notifications of incoming changes, and indicates when a query synchronization failed. It is also the anchor for managing the offline support, since only the tasks that the user has read are stored offline, only changed tasks are synchronized, and all of this state is maintained in the Task List. Our architecture does provide a loosely-coupled architecture so you can use the TaskList (in ..mylyn.tasks.core) without using any of its UI or having your users install the corresponding view. But for most cases we believe that the better approach is to integrate with Mylyn's Task List rather than providing an separate view. Most developers work with three kinds of tasks:

  • The issues and tasks that make up their project (i.e. in MKS integrity).
  • Bug reports and enhancement requests that they watch and create for the other frameworks that they use (e.g. bugs against Eclipse, JEE, Spring).
  • Personal tasks and todos they need to make for themselves (via Mylyn's Task List).

For this reason a fundamental part of our approach is to give developers a single view for managing all of their tasks, and to make it easy for vendors to customize the content of the Task List and rich editors to meet their needs (e.g. as JIRA does with custom task icon type overlays). There are substantial benefits to providing developers with a single unified task management view, similar to those benefits of providing them with a unified resource management view (i.e., Eclipse's Project Explorer). Rather than bloating the user experience by involving one or more disparate bug/task/issue/ticket management views, developers can provide a single Task List that is seamlessly integrated with Eclipse. For an overview of the benefits refer to the following article: http://www-128.ibm.com/developerworks/java/library/j-mylyn1/

The other thing to consider is integration with Mylyn's automatic context management facilities. Again, this is possible to integrate with a custom view, but the Task List has been streamlined around the interaction needed to make task activation easy. For an overview of task context management refer to this article: http://www-128.ibm.com/developerworks/java/library/j-mylyn2

Creating connector projects

The Trac connector is a good example, because it is a nearly-full featured implementation, but does not contain as much customization as Bugzilla. Start by creating two plug-in projects using the following suggested naming convention:

  • com.mycompany.mytracker.core: Java API for connecting to the task repository. This project should not make contributions to the Eclipse UI and hence does not need a plugin.xml file.
  • com.mycompany.mytracker.ui: Eclipse and Mylyn UI for the connector which does make contributions to the UI, so this will need a plugin.xml (created by PDE wizard).
  • com.mycompany.mytracker.tests: unit tests for both core and UI parts, should have JUnit on its classpath.

Implementing core extension points

Your connector should extend AbstractRepositoryConnector (org.eclipse.mylyn.provisional.tasklist). For basic operation you should first implement importing existing tasks from the repository. Therefore you need to implement the methods getConnectorKind, canCreateTaskFromKey, and createTaskFromExistingId. You need to implement a custom task (which should inherit from AbstractTask). Use the Trac connector as an example. After creating a stub repository connector, you have to connect to the extension point "org.eclipse.mylyn.tasklist.repositories". You can just omit an externalizer specification for now. If your first basic plugin works, you should handle synchronization. Please note that the method for synchronization is called updateOfflineState (AbstractRepositoryConnector) instead of just synchronize(). The next step is to write a TaskExternalizer (extend DelegatingTaskExternalizer and add the declaration to your plugin.xml). (Note that DelegatingTaskExternalizer is in an internal package in 2.3.0. Perhaps we should be extending AbstractTaskListFactory instead, following the model of the Trac connector.)

Here are some classes you should create for your connector:

  • MytrackerCorePlugin extends Plugin
  • MytrackerRepositoryConnector extends AbstractRepositoryConnector
  • MytrackerTask extends AbstractTask

Tips on adding external library JARs:

  • To add external jar, create a lib directory in the ...core plugin and place the jar(s) in the lib directory. Then, in the plugin's MANIFEST.MF, add the lib/...jar(s) to the Bundle-ClassPath property. If you do not do that, you will get ClassNotFoundException even if the jar(s) are in your Eclipse build path.
  • Add the same library path to the bin.includes property of build.properties file. Make sure that the . (dot) path is also included in both Bundle-ClassPath and bin.includes properties, otherwise you will get ClassNotFoundException when debugging and deploying the connector.

Implementing UI extension points

You have to create following list of Extensions from Plug-in Manifest Editor tab. Create extension org.eclipse.mylyn.tasks.ui.repositories and add:

  • MytrackerRepositoryConnector
  • MytrackerConnectorUi
  • MytrackerTaskListFactory

Create extension org.eclipse.mylyn.task.core.templates and add:

  • Your connector template(s)

Create extension org.eclipse.mylyn.task.ui.editors and add:

  • MyTrackerTaskEditorFactory

Adding Connector Repository specific data

  • Note, that repository url has to be unique.
  • Create UI for the custom specific data in MyTrackerRepositorySettingPage
  • Override/implement createAdditionalControls()
  • Override/implement updateProperties() to store the data in TaskRepository properties so they can be retrieved and used later

Adding persistence support

Your TaskListFactory needs to implement/override the following methods:

  • getTaskElementName()

returns the tag name for Mytracker-tasks to be used in the saved xml

  • getQueryElementNames()

return a Set() of tag names for all supported query-types

  • getQueryElementName(AbstractRepositoryQuery)

return the element name for the provided query

  • canCreate(AbstractTask)
  • canCreate(AbstractRepositoryQuery)

return true for the task/queries this factory can create

  • setAdditionalAttributes(AbstractTask task, Element node)
  • setAdditionalAttributes(AbstractRepositoryQuery query, Element node)

Store additional values on the xml node

  • createTask(String repositoryUrl, String id, String label, Element node)
  • createQuery(String repositoryUrl, String queryString, String label, Element node)

recreate persisted tasks/queries from the xml node

Query support

To create new queries, you have to implement the AbstractRepositoryConnector.performQuery() method. This requires the creation of subclasses for:

  • AbstractTask
  • AbstractRepositoryConnectorUi
    • Specify your subclass in the connectorUi element of extension point org.eclipse.mylyn.tasks.ui.repositories
    • getQueryWizard() must return a Wizard instance (or null if queries are not supported)
  • AbstractRepositoryQuery
    • Extend this with a container to hold your connector-specific search criteria (e.g. create corresponding fields or separate class)
  • AbstractTaskListFactory
    • Specify your subclass in the taskListFactory element of extension point org.eclipse.mylyn.tasks.ui.repositories
    • In addition to the abstract methods (used for tasks) the following methods need to be overriden:
      • canCreate(query): Returns true if the connector can create a query of the given type.
      • getQueryElementName(query): The returned String must be unique between connectors and is used for persistently storing query data
      • getQueryElementNames(): Returns a set containing a query element name for each query type the connector supports (e.g. in Bugzilla there are two query types: URL based and form based queries)
      • createQuery(...): Restores the query. The Element object is only needed if additional data has been stored with setAdditionalAttributes(...).
  • AbstractRepositoryQueryPage
    • Override createControl() to create your widgets
    • In getQuery() return an instance of your query class populated with the search criteria entered in the page

In the performFinish() method of your wizard:

  • Add your query to the task list: TasksUiPlugin.getTaskListManager().getTaskList().addQuery(yourQuery)
  • Perform initial synchronization so that all matching tasks are downloaded from the server. Use something like TasksUiPlugin.getSynchronizationManager().synchronize(yourConnector, yourQuery, null, true).

Synchronization will trigger performQuery() in your connector. Fetch all matching tasks and call resultCollector.accept(matchingTask) for each.

To modify the default label and description of your implementation of AbstractQueryHit, which encapsulates the repository task displayed in the query category, you should override methods getIdLabel() and/or getSummary().

Task editor

What is required to add an editor for my connector?

Each connector must supply an editor for their task type unless they are displaying their task via a web page. A simple yet full featured editor can be made easily:

1) Create a MyTaskEditor class that extends AbstractRepositoryTaskEditor. For an example of how simple the editor code can be see the TracTaskEditor.

2) Create a task factory specific to your task type which extends AbstractTaskEditorFactory To continue with Steffen's Trac connector as an example see the TracTaskEditorFactory

The factory you are building will be used by Mylyn's TaskEditor (a multi page editor) to load your particular editor and display it along with the other pages (i.e. Planning and Context). The TracTaskEditorFactory also shows how to return a web page as an editor in order to display the task as a web resource (using a BrowserFormPage) (TODO: improve documentation for simple web page display of tasks).

3) Declare your task factory in your plugin.xml using the org.eclipse.mylyn.tasks.ui.editors extension point. Mylyn's TaskEditor gets a reference to your custom task editor factory via this extension point. Here is the corresponding definition for TracTaskEditorFactory which is found in the trac.ui plugin.xml:

  <extension
        point="org.eclipse.mylyn.tasks.ui.editors">
     <editorFactory class="org.eclipse.mylyn.internal.trac.ui.editor.TracTaskEditorFactory"/>
  </extension>

Customizing existing connector editors

  • Customization of existing editors is currently very limited. The only means of extending existing editors is via a contribution to the popup menu.
  • To add a dynamic popup action to the popup menu, have your plugin extend the org.eclipse.mylyn.tasks.ui.actions extension point. Then add a "dynamic popup" action. For the action you will need to specify a class that implements the IDynamicSubMenuContributor interface which will add a submenu to the popup menu containing your desired action(s). See org.eclipse.mylyn.internal.tasks.ui.TaskStatusMenuContributor for an example.

Creating a NewMyTrackerTaskEditor

  • Used for creating new tasks, similar to above (extend AbstractNewRepositoryTaskEditor).

Task Editor Attributes

  • Task Editor uses RepositoryTaskAttribute class to pass repository task attributes between the UI and the connector. Most of the connectors have their own attributes class. The class MyTrackerTaskAttributeFactory (extends AbstractAttributeFactory) method mapCommonAttributeKey() is used to map the RepositoryTaskAttribute attributes to the connector attributes.
  • implement setupNewBugAttributes() in ...MyTracker and create RepositoryTaskAttribute a = MyTrackerClient.makeNewAttribute()
  • implement enum ...ReportElement class and define attributes there
  • implement attribute mapping in MyTrackerTaskAttributeFactory
  • Hint: To display an attribute in a combo box (e.g. bug status) call RepositoryTaskAttribute.addOption for each possible value, and RepositoryTaskAttribute.setValue to set the current value.

Adding content assist to a task editor

Adding content assist for fields basically requires the creation of 3 classes and registering them properly in Mylyn:

1. Create the classes:

  • MyFieldProposalProvider implements IContentProposalProvider
    • getProposals(): Responsible to create all proposals given the field's current content and cursor position (this is where all the logic resides)
  • MyFieldProposal implements IContentProposal: Encapsulates a single proposal for MyField selectable by the user
  • MyFieldLabelProvider extends LabelProvider: Use getText() and getImage() for display in the UI.

2. The following methods (from AbstractRepositoryTaskEditor or AbstractNewRepositoryTaskEditor depending on your editor type) have to be overriden:

  • hasContentAssist(attribute): Tells Mylyn whether content assist is available for the given attribute or not
  • createContentProposalProvider(attribute): Return an instance of MyFieldProposalProvider if the attribute matches yours
  • createProposalLabelProvider(attribute): Return an instance of MyFieldLabelProvider if the attribute matches yours

Note: Mylyn uses ContentProposalAdapter.PROPOSAL_REPLACE which means that the entire content of the field will be replaced by the selected proposal.

Offline data handling

Mylyn's offline data handling supports a number of features including: incoming/outgoing notification, rich offline editing, instant open of issues. All of these capabilities can be extended to your connector through implementation of a few interfaces. By this point you may have already implemented a task type for your connector, for example MyConnectorTask that extends AbstractTask. This task object holds most of the information necessary for display in Mylyn's task list but little more. In general, the bulk of the information related to a task (i.e. long description, comments, and various attributes) are held in another class, RepositoryTaskData. The framework manages the RepositoryTaskData on behalf of the connectors. For offline support to work, each connector is responsible for retrieving and sending task data to and from the remote repository. (note that RepositoryTaskData is to be used directly, not extended)

To add offline support for your connector:

  • Extend AbstractTaskDataHandler (i.e. MyConnectorTaskDataHandler) - the interface through which RepositoryTaskData is sent to/from your repository. Behind this interface you will do the marshaling necessary to present your native repository data in RepositoryTaskData form.
  • Return your connector's data handler in MyRepositoryConnector.getTaskDataHandler() method.
  • Implement MyRepositoryConnector.updateTaskFromTaskData() - this is where you populate the AbstractTask with information from the RepositoryTaskData
  • Extend AbstractAttributeFactory (i.e. MyConnectorAttributeFactory) - this class does the work of mapping your repository's native attribute ids to ids understood by Mylyn (along with a few other utility functions) (see BugzillaAttributeFactory as an example) (TODO: expand explanation of attribute factory)
  • Note: Methods getTaskData and postData of the task data handler will always be called regardless of the offline state of the repository (see bug#202210). A CoreException (with a CANCEL status) should be thrown if the repository is not available.

RepositoryTaskData (TODO: Expand with further explanation)

RepositoryOperation (to be deprecated as part of bug#150680) Defines the valid operations for this particular task (resolve, close, etc.).

Task comments (TaskComment) are also stored in the RepositoryTaskData. Each comment should have the following attributes set:

  • RepositoryTaskAttribute.COMMENT_DATE
  • RepositoryTaskAttribute.USER_OWNER
  • RepositoryTaskAttribute.COMMENT_TEXT
  • RepositoryTaskAttribute.DESCRIPTION ( this needs to be set to "mylyn/context/zip" in order for the attachment to be recognized as a Mylyn context)

Attachments

RepositoryAttachment are held by the RepositoryTaskData object. Your connector's task data handler is responsible for creating the appropriate RepositoryAttachment objects of the given report and adding them to the ReositoryTaskData before returning it to the framework (i.e. within AbstractTaskDataHandler.getTaskData() ...

Attachment support

Please contribute

Deployment tips

  • Use Plug-in Editor to open META-INF/MANIFEST.MF
  • From Overview page click on Export Wizard and generate .jar for both core and ui plugin.
  • You have to generate the plugin jars with appropriate Eclipse version, for example check out your connector plugins for Eclipse 3.2.1 and generate 3.2 version of connector plugins, then checkout your connector plugins for Eclipse 3.3 and generate 3.3 version of connector plugins.
  • Exit Eclipse copy the jars into eclipse/plugins directory and start eclipse with -clean option the first time
  • Open Task Repositories view and try to add new repository with your connector
  • If you do not see your connector, check Error Logs view for any errors

Note, that generating valid version of the plugins can be frustrating experience. Be patient and explore Error Logs view if your connector does not appear in the Task Repositories view Add Task Repository dialog.

Here are few things to check if your connector fails to appear in the Add Task Repository dialog (usually the error is ClassNotFound exception):

  • Make sure you have . (dot) in the bin.includes, source.includes of your build.properties file of both connector plugins
  • Make sure you have . (dot) in the Bundle-ClassPath property of the META-INF/MANIFEST.MF file of both connector plugins
  • Check the generated .jar files with unzip tool (7-Zip and others) to make sure that your libraries and classes are present in the jar
  • Do not rely on Eclipse Plugin Manifest Editor, check the both build.properties and META-INF/MANIFEST.MF in Text Editor
  • Start Eclipse with -clean option the first time after you deploy your connector.


Duplicate Detectors

Mylyn provides an extension point that allows contributors to create duplicate detectors. Each duplicate detector can use its own algorithm to determine if any similar bugs exist in the bug repository. Duplicate detection can happen in one of two ways:

  1. Client-side: detectors that can rely entirely on the task repository's search facilities to issue a query that returns a set of potentially relevant tasks, then do client-side analysis of the contents of the results. For example, a Java stack trace detector can search for all tasks that refer to a type name, and then use heuristics to identify and rank the most relevant ones (e.g. based on where it appears in the stack trace).
  2. Server-side: some detectors require access to the all of the task data in the repository and are best implemented server-side. For example, a natural language matcher that checks every comment would be too cumbersome and could require too much network traffic to implement client-side. Such detectors can be integrated with Mylyn via a web service API.

Refer to org.eclipse.mylyn.internal.bugzilla.ide.StackTraceDuplicateDetector can be used as a reference implementation.

When you create a duplicate detector, you need to specify the extension in the plugin.xml file. Below is the entry from the org.eclipse.mylyn.internal.bugzilla.ide plugin.xml file, as an example.

   <extension point="org.eclipse.mylyn.tasks.ui.duplicateDetectors">
       <detector class="org.eclipse.mylyn.internal.bugzilla.ide.StackTraceDuplicateDetector"
                 name="Stack Trace">
       </detector>       
   </extension>

The class attribute of the detector extension is required and must be a subclass of org.eclipse.mylyn.tasks.ui.AbstractDuplicateDetector. The name is also required and must be a string. The name attribute will be displayed on the New Repository Task editor, so make sure it is short but descriptive. There is also an optional kind attribute - this attribute allows you to specify what kind of repository your duplicate detector works with. If you leave the kind attribute blank, your duplicate detector may be displayed in the duplicate detector list for every repository (i.e., users could choose to use your detector regardless of the type of repository that they are using)

The default behaviour is for every editor that inherits from org.eclipse.mylyn.tasks.ui.editors.AbstractNewRepositoryTaskEditor to display all of the duplicate detectors that are available. If you want to modify the list of duplicate detectors that are shown, you should override AbstractNewRepositoryTaskEditor's getDuplicateSearchCollectorsList() method and return only the List of AbstractDuplicateDetectors that you want to be displayed. This is where the kind attribute could be useful - for example, the org.eclipse.mylyn.internal.bugzilla.ui.editor.NewBugzillaTaskEditor could override getDuplicateSearchCollectorList() and return a list that contains only the duplicate detectors where the kind was specific as Bugzilla.

EK: It doesn't seem like the above paragraph describes the actual implementation, which has the AbstractRepositoryTaskEditor with getDuplicateSearchCollector(name) and getDuplicateSearchCollectorsList() both return null and only BugzillaTaskEditor and NewBugzillaTaskEditor override these methods. I would think that AbstractRepositoryTaskEditor (not the AbstractNewRepositoryTaskEditor) should provide default implementation, but patch on bug 195079 been turned down

To create a duplicate detector you should:

  • Create your duplicate detector class that subclasses org.eclipse.mylyn.tasks.ui.AbstractDuplicateDetector
  • Create a subclass SearchHitCollector to query the repository for duplicates
  • Within your duplicate detector class, override the public SearchHitCollector getSearchHitCollector(TaskRepository repository, RepositoryTaskData taskData) method to use your new SearchHitCollector
  • Specify the extension (as shown above) in the plugin.xml file in the same plugin as your duplicate detector class and your subclass of SearchHitCollector.

Adding presentations to the Task List view

Mylyn provides an extension point to contribute custom presentations for the Task List view. Contributed presentations will appear in the drop down list on the Task List toolbar. Each presentation must specify a means of creating a content provider for a particular instance of the TaskListView, as specified by the AbstractTaskListPresentation, a subtype of which must be provided.

     <presentation
           class="org.eclipse.mylyn.internal.tasks.ui.CategorizedPresentation"
           icon="icons/etool16/category.gif"
           id="org.eclipse.mylyn.tasks.ui.categorized"
           name="Categorized"/>

Content provider implementation should be a subclass of the AbstractTaskListContentProvider or one of its subclasses.

Context API

Mylyn relies on Bridges to integrate the context model with the structure and UI features of domain-specific tools. There are two kinds of bridges:

  • Structure Bridge: maps domain-specific elements and relationships to the generic handleIdentifiers understood by the structure model.
    • Extension point is: org.eclipse.mylyn.context.core.bridges: structureBridge
  • UI Bridges: integrate Mylyn facilities, such as the Focus on Active Task button, with editors and views.
    • Extension point is: "org.eclipse.mylyn.context.ui.bridges: uiBridge

The core set of Bridges supports the Eclipse SDK:

  • Resources (i.e. files and folders)
  • Java and JUnit
  • PDE and Ant XML editing

How it works: Generic workbench UI monitoring facilities (org.eclipse.mylyn.monitor), translate interaction with domain-specific elements (e.g. Java methods) into an interaction history. The context manager (org.eclipse.mylyn.context.core) relies on a structure bridge to create a context model from these elements and from the relations between the elements. The structure bridge is also used by the Focused UI facilities to map elements that show in views and editors to the context model, in order to determine their interest rank. This ranking is then used for filtering and folding elements.

Resource Bridge

The generic ResourceStructureBridge provides a basic level of interoperability with other tools that use files (e.g. .php, .cpp), and enables Mylyn filtering to work for generic views that shows those files (i.e. the Project Explorer, Navigator) and any corresponding markers (i.e. the Problems and Tasks views). This is only the most basic context model integration, and does not offer the benefits of a specialized structure bridge, such as making declarations part of the context and providing Active Search facilities. Without a bridge Mylyn also can not be applied to tool-specific views.

To extend Mylyn to other kinds of structure and tools create a new structure bridge and model it on the one in org.eclipse.mylyn.java.

Excluding Elements

If an element should not participate in the task context, but can be interacted with by the user, the AbstractContextStructureBridge.getHandleIdentifier(Object) method should return null for the element. For example, in the case of Java null could be returned for implicitly uninteresting elements such as import statements.

Excluding Resources

Resource patterns can be excluded manually by the user via the Mylyn -> Resources preference page. To add defaults to this page use the following extension point:

   <extension
        point="org.eclipse.mylyn.resources.ui.changeMonitoring">
               <exclude
               pattern=".*"/>
   </extension>

Note that file URIs are supported (e.g. file:/foo/bar). Resource patterns can be programatically added via:

 ResourcesUiPreferenceInitializeraddForcedExclusionPattern(..)

Task-Focused UI

Editor Management

To exclude an editor from being automatically closed when a task is deactivated have the editor extend the IContextAwareEditor class, e.g.:

 public class MyEditor extends FormEditor implements IContextAwareEditor {
    public boolean canClose() {
        retrun false;
    }
    ...
 }

Viewer Management

When existing viewers are focused, the Context UI does not affect their contents in any way, but instead affects the visibility of elements and the refresh and expansion policy:

  • Adds a ViewerFilter (class is org.eclipse.mylyn.context.ui.InterestFilter) that determines visibility of elements based on whether or not they are in the task context.
  • Manages the refresh of viewers and refresh+expansion of tree viewers to ensure that when the context model changes the viewer is refreshed.

Processing interaction

The context model is a transformation of an interaction history. The only way to change or affect the model is to issue InteractionEvents. For an example of how to translate interaction with UI facilities such as views and editors, see:

  • AbstractUserInterctionMonitor
  • JavaEditingMonitor

Direct manipulation

The model can be mainpulated directly by issuing special kinds of InteractionEvents. For an example see:

  • AbstractInterestManipulationAction and subclasses.

Team API

Mylyn provides several key features that facilitate working with version control systems.

Change set management

Automatic change set management (see Mylyn User Guide#Team Support) creates change sets for tasks on the user's behalf, and enables automatic commit messages. There are two ways to implement this support.

Relying on the Platform/Team ActiveChangeSetManager

This is the way that the current CVS and SVN providers do it, and involves providing the following extension point as shown with this example of how it works for CVS:

 <extension point="org.eclipse.mylyn.team.changeSets">
   <activeChangeSetProvider 
      class="org.eclipse.mylyn.internal.team.ccvs.CvsActiveChangeSetProvider"/>
 </extension>

Where the CvsActiveChangeSetProvider is a subclass of AbstractActiveChangeSetProvider.

This will result in Mylyn's org.eclipse.mylyn.internal.team.ContextActiveChangeSetManager bridging between the Platform/Team change sets and the task context model.

Note that the change set manager must be a subtype of org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager. 'This means relying on an internal class, and as such is not guaranteed to be backwards compatible. Consider voting to make this class API for Eclipse 3.3 (bug 116084).

Re-implementing change set management

It is possible to provide an alternate change set bridge in order to avoid extending the internal class as above, or if a different change set management mechanism is used. Do this via the contextChangeSetManager extension point, and as an example implementation you can use ContextActiveChangeSetManager which provides the bridging for the Platform/Team change sets described above.

 <extension point="org.eclipse.mylyn.team.changeSets">
   <contextChangeSetManager
      class="org.eclipse.mylyn.internal.team.ContextActiveChangeSetManager"/>
 </extension>

Mapping from comments to tasks

The Open Corresponding Task action allows the user to navigate from change sets in "Synchronize" view or from History view to the task (e.g. bug report).

To support for Open Corresponding Task action in "Synchronize" and "History" views, the team provider should register IAdapterFactory that should adapt to ILinkedTaskInfo. This way, proprietary artifacts shown in these views won't have hard dependency on Mylyn's classes. If hard dependency on Mylyn classes is acceptable, you can also make your artifacts implement IAdaptable interface and directly adapt to ILinkedTaskInfo.

This factory should return adapter as quick as possible to not slow down the UI because adapter will be queried and created for nearly every popup menu.

Mapping from projects to Task Repositories

Mylyn allows contribution of a project link provider which maps from workspace projects to task repositories. ProjectPreferencesLinkProvider is contributed by the org.eclipse.mylyn.tasks.ui plugin and stores the required information in the project settings. Custom link providers can use metadata from other sources, such as version control system (i.e. Subversion properties) or Maven POM. Use org.eclipse.mylyn.tasks.ui.projectLinkProviders extension point to register link provider. For example:

 <extension
       point="org.eclipse.mylyn.tasks.ui.projectLinkProviders">
    <linkProvider
          class="org.tigris.subversion.subclipse.mylyn.SubclipseTaskRepositoryLinkProvider"
          id="org.tigris.subversion.subclipse.mylyn.taskRepositoryLinkProvider"
          name="Subclipse Link Provider"
          order="100">
    </linkProvider>
 </extension>

Important attribute is order. Recommended values are:

  • 1000 for generic or custom metadata
  • 100 for metadata from the version control systems
  • 10 for metadata from the project or build management systems

Implementation class should extend org.eclipse.mylyn.tasks.ui.AbstractTaskRepositoryLinkProvider and provide at least getTaskRepository() method.

Distributing your extension

We recommend using one of the following options:

  • Have a separate plug-in for the Mylyn integration and create an optional feature with dependencies on Mylyn's features
  • Make Mylyn an optional dependency of your plug-in. This can be done via

Require-Bundle: org.eclipse.mylyn.team;resolution:=optional

If you would like your update site linked from the Mylyn update site please send an email to the mylyn-dev mailing list.

Monitor API

Resources

Examples

The UI Usage Report wizard can be used as an example of how to report on usage activity. The main class for this is currently UsageSummaryReportEditorPart and the project of interest is org.eclipse.mylyn.monitor.usage

For a user study example checkout: sandbox/org.eclipse.mylyn.examples.monitor.study

Note that this project relies on upload scripts that are currently disabled. Send questions about reusing it to mylyn-dev.

Overview

The Mylyn Monitor is a separately installable component that collects information about a user’s activity in Eclipse. Clients of the monitor include the Context UI, which transforms interaction into a degree-of-interest model, and user study plug-ins, which can report on Eclipse usage trends. The org.eclipse.mylyn.monitor plug-in is structured to accept listeners to different Eclipse events, currently including preference changes, perspective changes, window events, selections, commands invoked through menus or key bindings and URLs viewed through the embedded Eclipse browser. The InteractionEvent class used by the monitor encapsulates a user or tool interaction.

The org.eclipse.mylyn.monitor.usage plug-in supports the transparent capture of these events into a local file and the upload of these events to an http server. The uploading mechanism includes functionality to track anonymous IDs for users, to obfuscate the handles of targets of selections and other such user data that may be collected, and to prompt the user to view and send the log to an http server. The Monitor also detects and reports in the trace when there has been a period of inactivity with Eclipse. Extension points in org.eclipse.mylyn.monitor.usage allow user study plug-ins to use the monitoring facilities. The Usage Monitor manages the size of traces produced by the Mylyn Monitor through compression, using a zipped format that significantly reduces the size of the files. The repetitiveness of user activity typically yields compression ratios over 95%, with a month of typical full-time programming activity resulting in an approximately 1MB zip.

To help with the analysis of traces collected with the Mylyn Monitor, the org.eclipse.mylyn.monitor.reports plug-in provides infrastructure for collecting and summarizing data across one or more traces. This reporting package provides an API to process records for a user across one or more trace files in a chronological order.

Interaction events

Streams

Mylyn currently has two consumers of the user's interaction event streams issued by the monitor:

  • Task Context model: all events that contribute to the degree-of-interest of elements are consumed, and externalized to zipped XML files in the .metadata/.mylyn/contexts directory. Currently the interaction event kinds included are selection, edit, propagation, prediction.
  • Interaction event logger: the logger in ..mylyn.monitor.usage consumes all events and appends them to .metadata/.mylyn/monitor-history.xml if logging is enabled in the Monitor preference page. This stream includes additional events that are monitored, such as preference changes.

Attributes

Note that if events are collapsed (i.e. multiple events are combined into a single one) the EndDate and Interest fields capture the aggregate information. These fields should not be used otherwise, since interaction events should be considered immutable and should not directly represent interest.

  • Kind: determines the type of interaction that took place (see listing below)
  • OriginId: the UI affordance that the event was issued from
  • StructureKind: the content type of the elementbeing interacted with
  • StructureHandle: a unique identifier for the element being interacted with
  • Navigation: an identifier for the kind of relation that corrsponds to the navigation to this element
  • StartDate: time stamp for the occurence of the event
  • EndDate: if an aggregate event, time stamp of the last occurrence
  • Delta: additional information relevant to interaction monitoring
  • Interest: if an aggregate event, amount of interest of all contained events (note: may be removed since interest should not be stored on events)

Event Kinds

Depending on which stream you are using, the interaction events may contain non user-initiated interactions such as interest propagations. In general, selection, edit and command events are the ones that initiate from the user, while propagation and prediction events originate from a tool.

NOTE: refer to the InteractionEvent Javadoc for the most up-to-date documentation of kinds.

  • Selection: user selection of elements, issued by the Eclipse post-selection mechanism
  • Edit: edit events that are created by text selections in the editor
  • Command: commands and actions invoked via buttons, menus, and keyboard shortcuts
  • Preference: workbench preference changes
  • Prediction: elements determined relevant by Active Search
  • Propagation: elements determined to be structurally related, such as the parent chain in a containment hierarchy
  • Manipulation: direct manipulation of interest via "Mark as Landmark" and "Mark Less Interesting"
  • Attention: interaction with a task, used for the meta-context

Extensibility

Interested developers can provide notification of other events by generating their own InteractionEvents, and injected using MonitorUiPlugin.getDefault().notifyInteractionObserved(InteractionEvent). InteractionEvents are assumed to be immutable and thus their fields are defined as string instances. The "delta" field can be used for adding additional information to an event. As loggers of InteractionEvents are to be content-agnostic and transparently encode and decode these fields, more complicated information may be provided as an XML-encoded string in the delta field. The Apache Ant project's org.apache.tools.ant.filters.StringInputStream class may be helpful for processing such fields afterwards.

Activity Meta-Context

Overview of meta context events.

Description Kind OriginId StructureKind StructureHandle Delta
Task activation COMMAND org.eclipse.ui.workbench activation <task handle>
(e.g. https://bugs.eclipse.or/bugs-89806)
activated
deactivated
Task activity timing ATTENTION org.eclipse.ui.workbench

os

user (for manipulations)
timing <active task handle> (null if no active task)
(e.g. https://bugs.eclipse.or/bugs-89806)
added
Workbench lifecycle events ATTENTION org.eclipse.ui.workbench

os

user (for manipulations)
lifecycle <product id> started
stopped

Uploading interaction histories

The current code relies on CGI scripts that are not CVS, but that are deprecated and will be replaced by Servlets. If you would like a copy of the CGI scripts please email mylyn-dev.

Headless use

The headless framework bundle available as a separate download. Running it requires J2SE 1.3 and the following plug-ins/JARs:

  • org.eclipse.core.runtime
  • org.eclipse.osgi
  • org.eclipse.equinox.common
  • org.eclipse.core.jobs
  • org.eclipse.equinox.registry
  • org.eclipse.equinox.preferences
  • org.eclipse.update.core
  • org.eclipse.core.contenttype
  • org.eclipse.core.runtime.compatibility.auth

Tasks API (org.eclipse.mylyn.tasks.core)

This API allows generic access to supported bug/task/ticket/issue trackers.

Bugzilla API (org.eclipse.mylyn.bugzilla.core) Headless Use

We maintain examples of headless Bugzilla API in test cases. A good way to get started is to run the test case as a JUnit test and work from there:

  • org.eclipse.mylyn.bugzilla.tests/src/org.eclipse.mylyn.bugzilla.tests.headless

The provisional Bugzilla API can be used independently of the Eclipse Workbench and Mylyn UI facilities as a Java API to Bugzilla. Also see the Mylyn Architecture document.

  • Mylyn dependencies
    • org.eclipse.mylyn.context.core
    • org.eclipse.mylyn.tasks.core
    • org.eclipse.mylyn.bugzilla.core
    • org.eclipse.mylyn
  • Eclipse dependencies (need to be on classpath but the platform doesn't need to be running)
    • org.eclipse.core.runtime
    • org.eclipse.equinox.common
    • org.eclipse.osgi
    • org.eclipse.update.core
  • Apache libs (can be found in the org.eclipse.mylyn plugin folder)
    • commons-codec-1.3.jar
    • commons-httpclient-3.0.1.jar
    • commons-logging.jar
    • commons-logging-api.jar

Quick Example

BugzillaRepositoryConnector connector = new BugzillaRepositoryConnector();			
connector.init(new TaskList());
TaskRepository repository = new TaskRepository(BugzillaCorePlugin.REPOSITORY_KIND, "http://bugzillarepository.com");
repository.setAuthenticationCredentials("userid", "password");
// If site protected by http authentication
repository.setHttpAuthenticationCredentials("httpauthuserid", "httpauthpassword");			
// Get the report from repository
AbstractRepositoryTask task = connector.createTaskFromExistingKey(repository, "2"); // bug number 2
// Access task information
System.err.println(task.getSummary());
System.err.println(task.getPriority());

// Access/set report data via common attribute keys:
task.getTaskData().getAttributeValue(RepositoryTaskAttribute.USER_ASSIGNED);
task.getTaskData().setAttributeValue(RepositoryTaskAttribute.USER_ASSIGNED, "rob");
task.getTaskData().setAttributeValue(RepositoryTaskAttribute.PRIORITY, "P2");
// ...or by Bugzilla keys
task.getTaskData().getAttributeValue(BugzillaReportElement.BUG_SEVERITY.getKeyString());
task.getTaskData().setAttributeValue(BugzillaReportElement.BUG_SEVERITY.getKeyString(), "critical");
// Post modified report to repository
connector.getTaskDataHandler().postTaskData(repository, task.getTaskData());


  • If a facility you need is not available in bugzilla.core file a bug report. Chances are that it is in bugzilla.ui and can be extracted.

Context API (org.eclipse.mylyn.context.core)

When Mylyn is running within the full eclipse platform, the org.eclipse.mylyn.tasks.ui plugin specifies where the contexts should be stored. When running without the org.eclipse.mylyn.tasks.ui plugin, you must specify this location yourself.

In plugin.xml for your plugin:

   <extension point="org.eclipse.mylyn.context.core.bridges">
  	  	<contextStore class="com.example.HardCodedContextStore"/>
   </extension>

com.example.HardCodedContextStore must extend org.eclipse.mylyn.context.core.AbstractContextStore and implement getRootDirectory().

Back to the top