Creating a ProM plug-in

Preferred steps to take

Create a YourPlugin class that will contain your plug-ins. For sake of simplicity, assume that your plug-in takes two inputs, and returns a single output.

@Plugin(name = "Your plug-in name", parameterLabels = { "Name of your first input", "Name of your second input", "Name of your configuration" }, 
    returnLabels = { "Name of your output" }, returnTypes = { YourOutput.class })
public class YourPlugin {
    //TODO: Add your methods, see below.
}

Create a private method that takes a PluginContext, a series of inputs, and a configuration.

private YourOutput yourPrivatePlugin(PluginContext context, YourFirstInput input1, YourSecondInput input2, YourConfiguration configuration) {
    //TODO: The body of your plug-in.
}

Create a public method that will be your first plug-in variant: One that runs in every context and assumes that the configuration is provided. This allows easy re-use of your plug-in by other plug-ins.

@UITopiaVariant(affiliation = "Your affiliation", author = "Your name", email = "Your e-mail address")
@PluginVariant(variantLabel = "Your plug-in name, parameters", requiredParameterLabels = { 0, 1, 2 })
public YourOutput yourConfiguredPlugin(PluginContext context, YourFirstInput input1, YourSecondInput input2, YourConfiguration configuration) {
    return yourPrivatePlugin(context, input1, input2, configuration);
}

In this code snippet, the requiredParameterLabels field determines which of the parameters are required for this plug-in variant (which excludes the first, obligatory, context parameter).

Create a constructor method in the YourConfiguration class that returns a default configuration, given the inputs.

public YourConfiguration(YourFirstInput input1, YourSecondInput input2) {
    //TODO: The body of your default configuration.
}

Create a public method that will be your second plug-in variant: One that runs in every context and uses the default configuration.

@UITopiaVariant(affiliation = "Your affiliation", author = "Your name", email = "Your e-mail address")
@PluginVariant(variantLabel = "Your plug-in name, parameters", requiredParameterLabels = { 0, 1 })
public YourOutput yourDefaultPlugin(PluginContext context, YourFirstInput input1, YourSecondInput input2) {
    YourConfiguration configuration = new YourConfiguration(input1, input2);
    return yourPrivatePlugin(context, input1, input2, configuration);
}

Create a YourDialog class that allows the user to change a configuration. For sake of simplicity, we assume that the dialog contains only a single panel. As this dialog should appear on the screen, use a UIPluginContext instead of a PluginContext.

public YourDialog(UIPluginContext context, YourFirstInput input1, YourSecondInput input2, YourConfiguration configuration) {
    this.configuration = configuration;
    //TODO: The body of your dialog that allows the user to change the configuration.
}

Create a public method that will be your third plug-in variant: One that runs only in a UI context and allows the user to change the configuration.

@UITopiaVariant(affiliation = "Your affiliation", author = "Your name", email = "Your e-mail address")
@PluginVariant(variantLabel = "Your plug-in name, dialog", requiredParameterLabels = { 0, 1 })
public YourOutput yourDefaultPlugin(UIPluginContext context, YourFirstInput input1, YourSecondInput input2) {
    YourConfiguration configuration = new YourConfiguration(input1, input2);
    YourDialog dialog = new YourDialog(context, input1, input2, configuration);
    InteractionResult result = context.showWizard("Your dialog title", true, true, dialog);
    if (result == InteractionResult.FINISHED) {
        return yourPrivatePlugin(context, input1, input2, configuration);
    }
    return null;
}

To help you getting started, these template classes and methods are already provided in a new package. Once you’ve created your own plug-in with configuration and dialog, you might want to remove these template classes.

Import plugins

@Plugin(name = "Import Your First Input from file", parameterLabels = { "Filename" }, returnLabels = { "Your First Input" }, returnTypes = { YourFirstInput.class })
@UIImportPlugin(description = "YFI files", extensions = { "yfi" })
public class ImportYourFirstInputPlugin extends AbstractImportPlugin {

        protected FileFilter getFileFilter() {
                return new FileNameExtensionFilter("YFI files", "yfi");
        }

        protected Object importFromStream(PluginContext context, InputStream input, String filename, long fileSizeInBytes)
                        throws Exception {
                YourFirstInput input1;
                // TODO: Import input1 from input stream
                return input1;
        }
}

Export plug-ins

@Plugin(name = "YO export (Your Output)", returnLabels = {}, returnTypes = {}, parameterLabels = {
                "Your Output", "File" }, userAccessible = true)
@UIExportPlugin(description = "Your Output", extension = "yo")
public class ExportYourOutputPlugin {

        @PluginVariant(variantLabel = "YO export (Your Output)", requiredParameterLabels = { 0, 1 })
        public void export(PluginContext context, YourOutput output, File file) throws IOException {
                // TODO: Output output to file file
        }
}

Visualizer plug-ins

public class VisualizeYourOutputPlugin {

        @Plugin(name = "Visualize Your Output", returnLabels = { "Visualized Your Output" }, returnTypes = { JComponent.class }, parameterLabels = { "Your Output" }, userAccessible = false)
        @Visualizer
        @PluginVariant(requiredParameterLabels = { 0 })
        public JComponent runUI(UIPluginContext context, YourOutput output) {
                JComponent component;
                // TODO: Create component from output.
                return component;
        }
}

Default visualizers

ProM allows to have multiple visualizers for a single object. For example, there are multiple ways to visualize an event log. ProM sorts the visualizers for an object by their name, and uses the first visualizer in the sorted list as default visualizer. For this reason, One would like to have control over which visualizer appears first in the list.

To do this, you can start the label of a visualizer with a text like “@0 “. For example, the previous visualizer would then become:

public class VisualizeYourOutputPlugin {

        @Plugin(name = "@0 Visualize Your Output", returnLabels = { "Visualized Your Output" }, returnTypes = { JComponent.class }, parameterLabels = { "Your Output" }, userAccessible = false)
        @Visualizer
        @PluginVariant(requiredParameterLabels = { 0 })
        public JComponent runUI(UIPluginContext context, YourOutput output) {
                JComponent component;
                // TODO: Create component from output.
                return component;
        }
}

These labels are sorted before the usual labels, and the part starting with “@” and ending with ” ” will not be shown. You can also use “@1 “, “@2 “, etc. in case you need to order multiple visualizers for some reason.