Creating your own Automation Action
You can create your own Automation Action.
Conditions:
- The new Automation Action class must implement the "Action" interface.
- The new Automation Action class must be declared under the package "com.openkm.plugin.automation.action".
- The new Automation Action class must be annotated with "@PluginImplementation".
- The new Automation Action class must extend of "BasePlugin".
Automation Action interface:
package com.openkm.plugin.automation;
import com.openkm.db.bean.AutomationRule.EnumEvents;
import net.xeoh.plugins.base.Plugin;
import java.util.List;
import java.util.Map;
public interface Action extends Plugin {
void executePre(Map<String, Object> env, Object... params) throws AutomationException;
void executePost(Map<String, Object> env, Object... params) throws AutomationException;
String getName();
String getParamType00();
String getParamSrc00();
String getParamDesc00();
String getParamType01();
String getParamSrc01();
String getParamDesc01();
String getParamType02();
String getParamSrc02();
String getParamDesc02();
List<EnumEvents> getValidEventsAtPre();
List<EnumEvents> getValidEventsAtPost();
}
The new class must be loaded into the package com.openkm.plugin.automation.action because application plugins system will try to load from there.
Do not miss the tag @PluginImplementation otherwise the application plugin system will not be able to retrieve the new class.
More information about Register a new plugin.
Methods description
Method | Type | Description |
---|---|---|
executePre(Map<String, Object> env, Object... params) |
void |
The method executed by the Automation event when the validation conditions succeed, on "pre" stage. |
executePost(Map<String, Object> env, Object... params) |
void |
The method executed by the Automation event when the validation conditions succeed, on "post" stage. |
getName() |
String |
Sets the name that will be shown in the administrator user interface selector list. |
getParamType00 getParamType01 getParamType02 |
String |
Sets the parameter type. Available values:
When value is set to Automation.PARAM_TYPE_EMPTY The parameters work as a logical group. [ getParamType00 + getParamSrc00 + getParamDesc00 ] |
getParamSrc00 getParamSrc01 getParamSrc02 |
String |
Sets the source type. Available values:
|
getParamDesc00 getParamDesc01 getParamDesc02 |
String |
The parameter description. |
getValidEventsAtPre() |
List<EnumEvents> |
Return a list of events. The method returns a list of valid events for the action in pre. |
getValidEventsAtPost() |
List<EnumEvents> |
Return a list of events. The method returns a list of valid events for the action in post. |
Understanding env variable
The env variable is present on isValid method, it is a Map of values injected by automation. These map values provide information about the node involved on the event and other related information.
It takes some time, until you take control of the AutomationUtils class, because they are centralized, the methods to retrieve data.
Take a look at Variables by automation event to know what variables are available for each event.
For example to retrieve the node that caused the event.
NodeBase node = automationUtils.getNodeToEvaluate(env);
Understanding params variable
The env variable is present on isValid method, it is an array of Objects. This array is filled by Automation event based on the number of parameters set on Action class ( which will not be Automation.PARAM_TYPE_EMPTY value).
The array can have serveral Objects with a distinct type, it is necessary retrieve the parameters to the correct object type.
It takes some time, until you take control of AutomationUtils class, because they are centralized, the methods to retrieve parameters.
For example to retrieve the first parameters as String object.
String param00 = AutomationUtils.getString(0, params);
Description of available ParamType values:
Property | Description |
---|---|
Automation.PARAM_TYPE_EMPTY |
Indicates an empty value. |
Automation.PARAM_TYPE_TEXT |
Indicates a text value will be required. |
Automation.PARAM_TYPE_INTEGER |
Indicates an integer value will be required. |
Automation.PARAM_TYPE_BOOLEAN |
Indicates a boolean value will be required. |
Automation.PARAM_TYPE_TEXTAREA |
Indicates a text area value will be required. |
Automation.PARAM_TYPE_CODE |
Indicates that code will be required. |
Automation.PARAM_TYPE_USER |
Indicates that a valid application user will be required. |
Automation.PARAM_TYPE_ROLE |
Indicates that a valid application role will be required. |
Automation.PARAM_TYPE_OMR |
Indicates that a valid OMR id - object mark recognition - will be required. |
Description of available Src values:
Property | Description |
---|---|
PARAM_SOURCE_EMPTY |
Indicates an empty source. |
PARAM_SOURCE_FOLDER |
Indicates that the source must be a folder. |
PARAM_SOURCE_OMR |
Indicates that the source must be a valid OMR - object mark recognition -. |
Detecting recursion
When you create your automation actions, should consider recursion case. For example if your action goes linked with "CREATE_DOCUMENT" event and into the action you create a new document you can go into an infinite loop. For it when you create a new Action should take special care of this cases.
Basic recursive samples:
- Automation task linked with "Create document" event when into is set an action that also creates a new document.
- Automation task linked with "Set metadata group" event when into is set an action that also changes metadata group values.
Complex recursive sample:
- Automation task linked with "Create document" event when into is set an action that changes metadata group values and automation task linked with "Set metadata group" event when into is set an action that creates a new document.
Code to detect recursive calls caused by automation action classes:
if (StackTraceUtils.isCallingMe(this.getClass().getName())) {
log.info("Recursion detected");
return;
}
Example
AddKeyword class:
package com.openkm.plugin.automation.action;
import com.openkm.core.Config;
import com.openkm.db.bean.Automation;
import com.openkm.db.bean.AutomationRule.EnumEvents;
import com.openkm.db.service.NodeBaseSrv;
import com.openkm.plugin.BasePlugin;
import com.openkm.plugin.automation.Action;
import com.openkm.plugin.automation.AutomationException;
import com.openkm.plugin.automation.AutomationUtils;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* AddKeyword
*/
@PluginImplementation
public class AddKeyword extends BasePlugin implements Action {
private static ArrayList<EnumEvents> EVENTS_AT_PRE = new ArrayList<>();
private static ArrayList<EnumEvents> EVENTS_AT_POST
= Stream.of(EnumEvents.EVENT_DOCUMENT_CREATE, EnumEvents.EVENT_DOCUMENT_UPDATE, EnumEvents.EVENT_DOCUMENT_DELETE,
EnumEvents.EVENT_DOCUMENT_RENAME, EnumEvents.EVENT_DOCUMENT_MOVE, EnumEvents.EVENT_DOCUMENT_RESTORE_VERSION,
EnumEvents.EVENT_DOCUMENT_DOWNLOAD_FROM_UI, EnumEvents.EVENT_DOCUMENT_DOWNLOAD_FROM_UI_FOR_PREVIEW,
EnumEvents.EVENT_DOCUMENT_PRINT, EnumEvents.EVENT_DOCUMENT_STAMP, EnumEvents.EVENT_RECORD_CREATE,
EnumEvents.EVENT_RECORD_DELETE, EnumEvents.EVENT_FOLDER_CREATE, EnumEvents.EVENT_FOLDER_DELETE,
EnumEvents.EVENT_MAIL_CREATE, EnumEvents.EVENT_MAIL_DOWNLOAD_FROM_UI, EnumEvents.EVENT_LINK_CREATE,
EnumEvents.EVENT_TEXT_EXTRACTOR, EnumEvents.EVENT_PROPERTY_GROUP_ADD, EnumEvents.EVENT_PROPERTY_GROUP_SET,
EnumEvents.EVENT_PROPERTY_GROUP_REMOVE, EnumEvents.EVENT_MAIL_IMPORT_ATTACHMENTS
).collect(Collectors.toCollection(ArrayList::new));
@Autowired
private NodeBaseSrv nodeBaseSrv;
@Autowired
private AutomationUtils automationUtils;
@Override
public void executePre(Map<String, Object> env, Object... params) throws AutomationException {
}
@Override
public void executePost(Map<String, Object> env, Object... params) throws AutomationException {
try {
String keyword = automationUtils.getString(0, params);
String uuid = automationUtils.getNodeToEvaluate(env).getUuid();
if (uuid != null && keyword != null && !keyword.isEmpty()) {
if (Config.SYSTEM_KEYWORD_LOWERCASE) {
keyword = keyword.toLowerCase();
}
nodeBaseSrv.addKeyword(uuid, keyword);
}
} catch (Exception e) {
throw new AutomationException("AddKeyword exception", e);
}
}
@Override
public String getName() {
return "AddKeyword";
}
@Override
public String getParamType00() {
return Automation.PARAM_TYPE_TEXT;
}
@Override
public String getParamSrc00() {
return Automation.PARAM_SOURCE_EMPTY;
}
@Override
public String getParamDesc00() {
return "Keyword";
}
@Override
public String getParamType01() {
return Automation.PARAM_TYPE_EMPTY;
}
@Override
public String getParamSrc01() {
return Automation.PARAM_SOURCE_EMPTY;
}
@Override
public String getParamDesc01() {
return "";
}
@Override
public String getParamType02() {
return Automation.PARAM_TYPE_EMPTY;
}
@Override
public String getParamSrc02() {
return Automation.PARAM_SOURCE_EMPTY;
}
@Override
public String getParamDesc02() {
return "";
}
@Override
public List<EnumEvents> getValidEventsAtPre() {
return EVENTS_AT_PRE;
}
@Override
public List<EnumEvents> getValidEventsAtPost() {
return EVENTS_AT_POST;
}
}