Dashboard > Atlassian Plugins > ... > Libraries > Confluence Supplier Library
  Atlassian Plugins Log In | Sign Up   View a printable version of the current page.  
  Confluence Supplier Library

Added by David Peterson , last edited by David Peterson on Oct 14, 2008  (view change) show comment
Labels: 

This library provides the ability for plugins to share data, both between each other and with Confluence users.

Details

Name Confluence Supplier
Current Version 3.0.1
JavaDoc API https://bamboo.developer.atlassian.com/download/CNFSPPLR-STABLE/artifacts/latest/JavaDoc/index.html

Maven 2

Dependency XML

<dependency>
  <groupId>org.randombits.confluence<groupId>
  <artifactId>confluence-supplier</artifactId>
  <version>3.0.1</version>
</dependency>

Repository XML

<repository>
  <id>atlassian-m2-contrib</id>
  <name>Atlassian Maven 2 Contributor Repository</name>
  <url>https://maven.atlassian.com/contrib</url>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
</repository>

Instructions

Assumptions
  1. The project is building with Maven 2.
  2. The Maven 2 details above have been added to your project's pom.xml file.

The Supplier library lets you both supply data to other plugins such as the Reporting Plugin, as well as pulling in data from other plugins. Depending on your plugin, you may wish to do either, or both.

Setting up your plugin to connect with other plugins

The Supplier library makes use of the [Confluence Intercom Library] to enable inter-plugin communications. As such, we need to register our new supplier with the Intercom system via a 'ConnectionBundle' - in this case a 'LocalSupplierBundle'.

Firstly, we need to have an IntercomStartup implementation which will register our connections. There can be multiple {{IntercomStartup}}s, and you can group suppliers together so they can be turned on or off in the Plugin Admin console. The Reporting Plugin does this with the 'debug' suppliers which are generally turned off.

In any case, for our purposes, we need something like this:

import org.randombits.confluence.intercom.ConnectionBundle;
import org.randombits.confluence.intercom.IntercomException;
import org.randombits.confluence.intercom.IntercomStartup;
import org.randombits.confluence.intercom.LocalIntercomListener;
import org.randombits.confluence.supplier.LocalSupplierBundle;

public class FooSupplierStartup extends IntercomStartup {
    public FooSupplierStartup() throws IntercomException {
    }

    @Override protected ConnectionBundle createConnectionBundle() {
        // Add as many connections as you wish here.
        return new LocalSupplierBundle( new FooSupplier(), new BarSupplier() );
    }

    @Override protected LocalIntercomListener createLocalIntercomListener() {
        // Create a listener implementation to get notifications about local connection registrations.
    }
}

Then, register your listener by putting it into the 'atlassian-plugin.xml' file for your plugin:

<!-- Foo Supplier Startup -->
    <listener name='Foo Supplier Startup' class='my.package.FooSupplierStartup'
              key='fooSupplierStartup'>
        <description>Sets up the Foo Suppliers.</description>
    </listener>

Supplying information to other plugins

You will need to create a class which implements the org.randombits.confluence.supplier.Supplier interface. It has three methods:

public boolean supportsPrefix(String prefix)

This method returns true if the supplier supports the specified prefix. Each supplier should have a prefix which users can provide to specify which supplier should be used. Some suppliers will require a prefix, others can make it optional, in which case the supportsContext method is the sole determinant for whether or not a supplier is considered to be the supplier for a given key.

For example, a user may provide the following key value: 'foo:bar'. In this case 'foo' is the prefix and 'bar' is the key which will be passed to the getValue macro.

Let's say our new FooSupplier wants to make the prefix optional. The supplier's prefix is 'foo'. Your code should look something like this:

public boolean supportsPrefix(String prefix) {
    return prefix == null || "foo".equals(prefix);
}

To make the prefix required, simply drop the 'null' test:

public boolean supportsPrefix(String prefix) {
    return "foo".equals(prefix);
}

You could also support multiple prefixes if you wished, although this is not recommended except for linguistic or deprecation reasons.

public boolean supportsContext(Object context)

The second method used to determine if a supplier supports a given prefix/object combination is the supportsContext method. The context is the current object being processed. The method simply returns true if the object provided is supported by the supplier. For example, if our FooSupplier only supports Foo objects, the method would look like this:

public boolean supportsContext(Object context) {
    return context instanceof Foo;
}

public Object getValue(Object context, String key)

This method does the actual work. The context is the same object which was passed to supportsContext - the current object. The key is the second part of the key value, the part after the prefix. For example, if the key value is 'foo:bar', the key will be 'bar'.

This method can do anything it wants with key values, but a typical structure will be something like this:

public Object getValue(Object context, String key) throws UnsupportedContextException, SupplierException {
    if (context instance of Foo) {
        Foo foo = (Foo)context;
        
        // Generally, don't bother checking for key case-insensitivity -  it just adds extra processing.
        if ("bar".equals(key))
            return foo.getBar();

        // If the key isn't recognised, return null - the supplier will then move onto another supplier.
        return null;
    }
    // Bad context. Shouldn't happen, but just in case...
    throw new UnsupportedContextException( context );
}

That's basically it for suppliers. Add more keys to the getValue method to provide more access to your object's information.

{report-info:foo:bar}

Pulling data from other plugins

Of course, your plugin may want to actually retrieve data from suppliers; your own or those provided by other plugins. In that case, you still need to have the 'confluence-supplier' library dependency provided above.

Basically, the SupplierAssistant support class has two method you will use: findValue and processValues.

findValue

Below is an example of using findValue.

import org.randombits.confluence.supplier.SupplierAssistant;
...
// Examples of using the SupplierAssistant.
Object value = SupplierAssistant.getInstance().findValue(context, key);
Bar bar = (Bar)SupplierAssistant.getInstance().findValue(myFoo, "foo:bar");
Long barId = (Long)SupplierAssistant.getInstance().findValue(myFoo, "foo:bar > bar:id");

findValue requires the root object and the keychain to access. Often that keychain will be provided by a Confluence user via a macro parameter, so the first example will be quite common, however you can pass in hard-coded keychains, such as the last two examples. The third example is a true keychain, with two pairs of prefix:key values chained together. Essentially, the SupplierAssistant will parse key chain as follows:

  1. Get the first prefix/key pair ('foo:bar').
  2. Find the supplier for the 'foo' prefix and context object (FooSupplier).
  3. Pass it the current context (myFoo) and the key ('bar').
  4. If the value returned isn't null, get the next prefix/key pair ('bar:id').
  5. Find the supplier for the 'bar' prefix and context object (BarSupplier).
  6. Pass it the current context (the 'Bar' value returned from the FooSupplier).
  7. Return the value from the BarSupplier.

processValues

processValues is similar to findValue, except that it allows multiple key chain values to be embedded in a single chain. For example:

import org.randombits.confluence.supplier.SupplierAssistant;
...
// Examples of using the SupplierAssistant.
String text = SupplierAssistant.getInstance().processValues(myFoo, "The %foo:bar% has an id of %foo:bar > bar:id%");

This will embed the values of 'foo:bar' and the 'bar:id' number into the surrounding text. This is quite useful for inserting supplier data into macro parameters, such as the 'name' parameter in link-page.

Conclusion

Hopefully that provides some basic information for getting started with the Confluence Supplier Library. Feel free to comment/ask questions/etc.

Copyright(c) CustomWare Asia Pacific Pty Ltd
Powered by Atlassian Confluence 2.7.3, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators