ProM是流程挖掘最重要的开源学术工具,在2000年左右由流程挖掘之父 Wil van der Aalst及其团队创建,目前已发展将近20多年,免费插件已达到2000多个。下面将介绍如何使用此工具来编写一个入门插件Hello World。
目录
1.所需环境准备
具体可以参考上一文章:流程挖掘工具-ProM的安装与使用教程_北冥有鱼zsp的博客-CSDN博客
2 定义一个插件
创建一个HelloWorld.java,代码如下:
package org.processmining.plugins.gettingstarted;
import org.processmining.contexts.uitopia.annotations.UITopiaVariant;
import org.processmining.framework.plugin.PluginContext;
import org.processmining.framework.plugin.annotations.Plugin;
public class HelloWorld {
@Plugin(
name = "My Hello World Plugin",
parameterLabels = {},
returnLabels = { "Hello world string" },
returnTypes = { String.class },
userAccessible = true,
help = "Produces the string: 'Hello world'"
)
@UITopiaVariant(
affiliation = "My company",
author = "My name",
email = "My e-mail address"
)
public static String helloWorld(PluginContext context) {
return "Hello World";
}
}
这段简单的代码定义了一个ProM插件。实际的插件逻辑包含在helloWorld函数中,该函数的参数是PluginContext对象,这是所有ProM插件的要求。该方法生成了一个包含文本“helloWorld”的字符串。
这个方法构成插件的事实是由@Plugin注释定义的。此注释为插件提供了“My Hello World plug-in”的名称(name)。此外,其他参数的解释如下:
parameterLabels:
输入列表,在本例中为空。
returnLabels:
输出标签的列表,每个标签都标记一个返回的对象。在这种情况下,只返回一个对象,即“Helloworld字符串”。
returnTypes:
输出类型列表,每个类型指定返回对象的类型。在本例中,类型为String.class,即此插件返回的对象类型为String。
userAccessible:
用户是否可以访问插件。这通常应设置为true。
help:
关于插件的一些说明性文本(可选)。
通过使用@Plugin注释,框架知道这个方法构成了一个插件。启动ProM后,将扫描所有类文件以查找此注释,并注册插件。如果用@Plugin注释注释的方法是静态的,如我们的示例中所示,那么当要求框架执行此插件时,它将调用该方法,就像调用了框架中的某个地方一样:
HelloWorld.helloWorld(context);
@UITopiaVariant注释通知ProM GUI该插件的存在,它通常提供以下内容:
affiliation: 作者的单位。
author: 作者的姓名。
email: 作者的电子邮件地址。
在使用输入参数扩展示例之前,我们首先解释如何执行此插件。
3 执行插件
在eclipse中点击该项目下的ProM with UITopia选项卡,选择run as 运行Prom with UITopia即可运行该项目。
将Hello World插件添加到ProM后,运行“ProM with UITopia”并选择“Actions”选项卡。该选项卡应包含“My Hello World plug-in”,如下所示:
选择“My Hello World Plug-in”,然后选择“Start”(开始)按钮。现在将执行插件,这将导致ProM打开唯一输出对象的视图,如下所示:
4. 多个输出
在上一个示例中,我们创建了一个返回单个字符串的插件,但是,插件可以返回多个对象。考虑以下插件定义:
package org.processmining.plugins.gettingstarted;
import org.processmining.contexts.uitopia.annotations.UITopiaVariant;
import org.processmining.framework.plugin.PluginContext;
import org.processmining.framework.plugin.annotations.Plugin;
public class HelloWorld2 {
@Plugin(
name = "My 2nd Hello World Plug-in",
parameterLabels = {},
returnLabels = {"Hello string", "Number", "Worlds string" },
returnTypes = {String.class, Integer.class, String.class },
userAccessible = true,
help = "Produces three objects: 'Hello', number, 'world'"
)
@UITopiaVariant(
affiliation = "My company",
author = "My name",
email = "My e-mail address"
)
public static Object[] helloWorlds(PluginContext context) {
return new Object[] { "Hello", new Integer(6), "Worlds" };
}
}
此插件名为“My 2nd Hello World Plug-in”。同样,插件的逻辑在方法体中定义。注意,该方法的返回类型实际上是Object[],表示该插件返回多个对象。框架不关心方法的返回类型。相反,插件返回的对象的类型必须由@Plugin注释的returnTypes参数指定。还提供了返回对象的标签。框架要求返回标签列表的大小与返回类型列表的大小相同。此外,这里还确定了返回对象的顺序。
注意:在插件执行之前,框架无法验证返回的对象是否确实是正确的类型。例如,如果此方法不会返回包含两个字符串但包含两个整数的数组,则框架将抛出异常。
5. 多个输入
插件开发的下一步是开发带有输入参数的插件。考虑以下插件来组合:
package org.processmining.plugins.gettingstarted;
import org.processmining.contexts.uitopia.annotations.UITopiaVariant;
import org.processmining.framework.plugin.PluginContext;
import org.processmining.framework.plugin.annotations.Plugin;
public class HelloWorld3 {
@Plugin(
name = "My Combine Worlds Plug-in",
parameterLabels = { "First string", "Number", "Second string" },
returnLabels = { "First string several second strings" },
returnTypes = { String.class },
userAccessible = true,
help = "Produces one string consisting of the first and a number of times the third parameter."
)
@UITopiaVariant(
affiliation = "My company",
author = "My name",
email = "My e-mail address"
)
public static Object helloWorlds(PluginContext context, String first, Integer number, String second) {
String s = first;
for (int i = 0; i < number; i++) {
s += "," + second;
}
return s;
}
}
与前两个“HelloWorld”插件不同,该插件需要参数。同样,这些参数是通过标签和类型指定的。但是,类型不是由注释提供的,而是由方法定义提供的。在上面的示例中,需要三个参数:
标记为“第一个字符串”的字符串,
标记为“数字”的整数,以及
标记为“第二个字符串”的字符串。
要执行此插件,我们需要将现有对象与所需的输入参数匹配,如下所示:
当所有所需的输入参数都匹配时,可以执行插件:
6. 总结
在本节中,我们概述了如何创建简单的基于方法的插件。最后,我们列出了开发插件时需要记住的要点:
(1) 返回类型以及参数类型不应使用泛型(即,List<String>不能用作参数)。原因是框架无法在运行时读取这些泛型,因此无法知道哪些插件可以作为其他插件的输入。
(2)数组既可以用作参数类型,也可以用作返回类型。插件可以指定返回String[].class类型的对象。也可以请求此类型的参数。
(3) 插件应尽可能在其参数和返回类型定义中使用接口。例如,一个返回PetrinetImpl对象(实现Petrinet接口)的插件应该声明它返回一个Petrinet.class类型的对象。
在本文的其余部分中,我们首先讨论上下文的概念,并展示如何开发特定于上下文的插件。然后,我们将展示如何使用ProM中内置的重载功能制作更精细的插件。
如需进行相关的了解或者交流,欢迎私信或者加入QQ群:671290481.