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.automation.action".
  • The new Automation Action class must be annotated with "@PluginImplementation".

Validation interface:

package com.openkm.automation;

import java.util.Map;

import net.xeoh.plugins.base.Plugin;

public interface Action extends Plugin {
	public static final String METHOD_PRE = "executePre";
	public static final String METHOD_POST = "executePost";
	
	public void executePre(Map<String, Object> env, Object... params);
	public void executePost(Map<String, Object> env, Object... params);
	public boolean hasPost();
	public boolean hasPre();
	public String getName();
	public String getParamType00();
	public String getParamSrc00();
	public String getParamDesc00();
	public String getParamType01();
	public String getParamSrc01();
	public String getParamDesc01();
	public String getParamType02();
	public String getParamSrc02();
	public String getParamDesc02();
}

More information avalable at: Register a new plugin.

Methods description

MethodTypeDescription

executePre(Map<String, Object> env, Object... params)

void

The method executed by the Automation event on the "pre" stage when the validation conditions succeed.

executePost(Map<String, Object> env, Object... params)

void

The method executed by the Automation event on the "post" stage when the validation conditions succeed.

hasPost()

boolean

When this return true, it indicates that the executePost(...) method can be used in the Automation post stage.

More information about automation stages can be found at: Automation.

hasPre()

boolean

When this returns true, it indicates that the executePre(...) method can be used in the Automation pre stage.

More information about automation stages can be found at: Automation.

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:

  • Automation.PARAM_TYPE_EMPTY
  • Automation.PARAM_TYPE_TEXT
  • Automation.PARAM_TYPE_INTEGER
  • Automation.PARAM_TYPE_BOOLEAN
  • Automation.PARAM_TYPE_TEXTAREA
  • Automation.PARAM_TYPE_CODE
  • Automation.PARAM_TYPE_USER
  • Automation.PARAM_TYPE_ROLE
  • Automation.PARAM_TYPE_OMR

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:

  • Automation.PARAM_SOURCE_EMPTY
  • Automation.PARAM_SOURCE_FOLDER
  • Automation.PARAM_SOURCE_OMR

getParamDesc00

getParamDesc01

getParamDesc02

String

The parameter description.

Understanding env variable

The env variable is present on the isValid method, it is a Map of values injected by automation. These map values provide information about the node involved in the event and other related information.

As the methods to retrieve the data are centralized, this takes some time unless you take control of the AutomationUtils class.

 For example to retrieve the uuid of the node that caused an event use:

String uuid = AutomationUtils.getUuid(env);

Understanding params variable

The env variable is present on the 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.

As the methods to retrieve the parameters are centralized, this takes some time unless you take control of the AutomationUtils class.

For example to retrieve the first parameters as a String object use:

String param00 = AutomationUtils.getString(0, params);

Description of available ParamType values:

PropertyDescription

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:

PropertyDescription

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, you should consider the possibility of unintended recursion. For example if your action is linked to a "CREATE_DOCUMENT" event and in the action you create a new document you can go into an infinite loop. For this reason when you create a new Action you should take special care of these cases.

Basic recursive samples:

  • Automation task linked with a "Create document" event which includes an action that also creates a new document.
  • Automation task linked with a "Set metadata group" event which includes an action that also changes metadata group values.

Complex recursive sample:

  • Automation task linked with a "Create document" event which includes an action that changes metadata group values and automation task linked with a "Set metadata group" event which includes 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.automation.action;

import java.util.Map;

import net.xeoh.plugins.base.annotations.PluginImplementation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.openkm.automation.Action;
import com.openkm.automation.AutomationUtils;
import com.openkm.core.Config;
import com.openkm.dao.NodeBaseDAO;
import com.openkm.dao.bean.Automation;

/**
 * AddKeyword
 * 
 */
@PluginImplementation
public class AddKeyword implements Action {
	private static Logger log = LoggerFactory.getLogger(AddKeyword.class);
	
	@Override
	public void executePre(Map<String, Object> env, Object... params) {
	}
	
	@Override
	public void executePost(Map<String, Object> env, Object... params) {
		String keyword = AutomationUtils.getString(0, params);
		String uuid = AutomationUtils.getUuid(env);
		
		try {
			if (uuid != null && keyword != null && !keyword.isEmpty()) {
				if (Config.SYSTEM_KEYWORD_LOWERCASE) {
					keyword = keyword.toLowerCase();
				}
				
				NodeBaseDAO.getInstance().addKeyword(uuid, keyword);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
	}
	
	@Override
	public boolean hasPost() {
		return true;
	}
	
	@Override
	public boolean hasPre() {
		return false;
	}
	
	@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 "";
	}
}