Monday, April 16, 2012

Source Provider, Property Tester and the Expressions Framework

The expressions framework provides powerful means to declare expressions via XML and query them at runtime. Such expressions can be used without loading the defining Plug-in. You can find them in command/menu enablements. There you find visibleWhen, enabledWhen, activeWhen expressions. But you also can use them for your own needs.

In this example we will create our own Source Provider with a custom property tester (don't worry, I will explain this right ahead).

There is good documentation available for further reading.

Source code for this tutorial is available on github as a single zip archive, as a Team Project Set or you can browse the files online. 


The expression framework can create/evaluate boolean expressions - something that in the end evaluates to true or false. To evaluate we need an object to work with (a source) and operators which return a boolean value.

Eclipse already defines commonly used sources and operators.

A simple example of an expression looks like this:

and is a basic operator that - of course - performs a boolean and operation. systemTest queries a java system property and compares it to a given value. So this expression evaluates to true only if we are working on an i386 linux machine.

Our source is not explicitely defined in the expression as the operator queries a static source System.getProperties().

Step 1: Creating a SourceProvider

For most expressions we will need sources that contain modifiable content. Use the predefined sources to get the active editor, the active selection or similar workbench related items. In this tutorial we will create a custom source to denote the current user.

Create a new Plug-in Project called com.codeandme.coreexpressions. In the plugin.xml create a new extension for and add a new sourceProvider to it. Create two new variables for the sourceProvider:
set name to com.codeandme.coreexpressions.currentStatus and com.codeandme.coreexpressions.currentUser and leave priorityLevel set to workbench.

Now implement the sourceProvider by creating a class com.codeandme.coreexpressions.ExampleSourceProvider:
package com.codeandme.coreexpressions;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.ui.AbstractSourceProvider;
import org.eclipse.ui.ISources;

public class ExampleSourceProvider extends AbstractSourceProvider {

 public static final String CURRENT_STATUS = "com.codeandme.coreexpressions.currentStatus";
 public static final String CURRENT_USER = "com.codeandme.coreexpressions.currentUser";

 private Object fUser = null;
 private String fStatus = "startup";

 public ExampleSourceProvider() {

 public void dispose() {

 public Map getCurrentState() {
  HashMap<String, Object> map = new HashMap<String, Object>();
  map.put(CURRENT_USER, fUser);
  map.put(CURRENT_STATUS, fStatus);

  return map;

 public String[] getProvidedSourceNames() {
  return new String[] { CURRENT_USER, CURRENT_STATUS };
We need to implement two methods:
  • getProvidedSourceNames()
    returns an array of source identifiers (variables). These are the same we already defined as variables in the plugin.xml.
  • getCurrentState()
    returns a Map<String, Object> with entries for each defined variable.

Step 2: Creating a property tester

Eclipse provides a generic expression operator test which allows to register custom tests.

Create a new extension for org.eclipse.core.expressions.propertyTesters with a unique id.

The type reflects to the kind of objects you'd get from the source provider. For now leave it to java.lang.Object.

The identifier of a specific property to check should be a fully qualified name. It consists of a namespace part and a properties name. It is good practice to set the namespace to your Plug-in identifier. Therefore set namespace to com.codeandme.coreexpressions and add two specific properties name,validated to properties. Hence our properties are named:
  • com.codeandme.coreexpressions.validated
Finally implement the class com.codeandme.coreexpressions.ExamplePropertyTester:
package com.codeandme.coreexpressions;

import org.eclipse.core.expressions.PropertyTester;

public class ExamplePropertyTester extends PropertyTester {

 private static final String NAME = "name";
 private static final String VALIDATED = "validated";

 public ExamplePropertyTester() {

 public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
  if (NAME.equals(property))
   return receiver.toString().equals(expectedValue);

  if (VALIDATED.equals(property)) {
   // do some background checks to see if user is validated
   return true;

  return false;
The receiver of the test() implementation is some object from a source provider. If you set your property tester to only accept objects of a certain type you need to add an instanceof check in the test() method.

Step 3: Your own expression

To use our source provider and property tester we can either create an expression for some activeWhen, enabledWhen or visibleWhen statement or we can extend org.eclipse.core.expressions.definitions to store the expression for later usage.

Create a new extension for org.eclipse.core.expressions.definitions with a unique id. Add a with section to define which source to use. Set variable to the name of our currentUser source: com.codeandme.coreexpressions.currentUser.

Add a test section to define our custom test. Set property to and value to a string to compare against. In the sample I use "John Doe".

Make sure you activate forcePluginActivation. This defines that the Plug-in defining the property tester should be activated. If it is not activated, the property test cannot be performed.

The final definition:
                  value="John Doe">
Step 4: Updating your source

Expressions do work right now, but our source is some kind of static. It won't change its status. Open ExampleSourceProvider and add following code:
 public void setCurrentUser(Object user) {
  fUser = user;
  fStatus = (user == null) ? "logged off" : "logged on";

  fireSourceChanged(ISources.WORKBENCH, CURRENT_USER, fUser);
  fireSourceChanged(ISources.WORKBENCH, CURRENT_STATUS, fStatus);
fireSourceChanged() will tell Eclipse that a source changed and therefore forces expressions using this source to be re-evaluated.

To get an instance of your source provider you can query the ISourceProviderService:
ISourceProviderService service =(ISourceProviderService) PlatformUI.getWorkbench().getService(ISourceProviderService.class);
ISourceProvider provider = service.getSourceProvider(ExampleSourceProvider.CURRENT_USER);


  1. Hi,

    thanks for this great Tutorial.
    From where do you call setCurrentUser()? Where do you have a reference to your ExampleSourceProvider?

    Best regards

    1. Hi Frank,

      check out the example code in the SVN repository, especially this file:

      The reference is gatherede from ISourceProviderService.getSourceProvider(...) as shown in the very last code snippet in the blog post