Creating your own FormInterceptor plugin
Available since OpenKM version 8.1.15
You can create your own form interceptor plugin to intercept all the add, set and get methods.
Description of common features allowed to be implemented by this plugin type:
- Intercept the values of the properties before creation (add) what allows to:
- Update values
- Validate values
- Autocomplete values
- Intercept get properties or form elements to:
- Remove values ( fields )
- Change UI behaviour of form elements ( set fields as read-only, hide fields, etc )
- Create form elements on the fly what will not be keep in the database ( requires filtering in add and set stages )
- Apply mask to values to be displayed ( protect critical values )
- Change the order of the form elements
- intercept the values of the properties before update (set) to:
- Update values
- Validate values
- Autocomplete values
Conditions:
- The new Form Validator class must implement the "FormInterceptor" interface.
- The new Form Validator class must be declared under the package "com.openkm.plugin.form.interceptor".
- The new Form Validator class must be annotated with "@PluginImplementation".
- The new Form Validator class must extend of "BasePlugin".
Form Validator interface:
package com.openkm.plugin.form.interceptor;
import com.openkm.bean.form.FormElement;
import com.openkm.core.ValidationFormException;
import net.xeoh.plugins.base.Plugin;
import java.util.List;
import java.util.Map;
public interface FormInterceptor extends Plugin {
String getName();
void add(String uuid, String grpName, Map<String, String> properties) throws ValidationFormException;
void get(String uuid, String grpName, Map<String, String> properties, List<FormElement> formElements, boolean useDefaultValue, boolean autocomplete);
void set(String uuid, String grpName, Map<String, String> properties) throws ValidationFormException;
}
The new class must be loaded into the package com.openkm.plugin.form.interceptor because the application plugins system will try to load from there.
Do not miss the tag @PluginImplementation; otherwise, the application plugin system cannot retrieve the new class.
More information at Register a new plugin.
Methods description
Method | Type | Description |
---|---|---|
getName() |
String |
The method returns the name of the plugin |
add(String uuid, String grpName, Map<String, String> properties) |
void |
Intercept the action of adding metadata. |
get(String uuid, String grpName, Map<String, String> properties, List<FormElement> formElements, boolean useDefaultValue, boolean autocomplete) |
void |
Intercept the action of getting metadata. |
set(String uuid, String grpName, Map<String, String> properties) |
void |
Intercept the action of set metadata. |
Example of the Form validator implementation
Metadata definition:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE property-groups PUBLIC "-//OpenKM//DTD Property Groups 3.10//EN"
"http://www.openkm.com/dtd/property-groups-3.10.dtd">
<property-groups>
<property-group label="Consulting" name="okg:consulting">
<input label="Input label" name="okp:consulting.input1" />
<separator label="Separator label" name="okp:consulting.separator" />
<input label="Input label" name="okp:consulting.input2" />
</property-group>
</property-groups>
In the following example plugin, different modifications are applied to the metadata only during the add, get, and set actions for a user with the ID "test." We suggest testing the example with this user and a different one.
package com.openkm.plugin.form.interceptor;
import com.openkm.bean.form.FormElement;
import com.openkm.bean.form.Input;
import com.openkm.bean.form.ValidationError;
import com.openkm.core.DatabaseException;
import com.openkm.core.PathNotFoundException;
import com.openkm.core.ValidationFormException;
import com.openkm.db.service.NodeBasePropertiesSrv;
import com.openkm.plugin.BasePlugin;
import com.openkm.principal.PrincipalUtils;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@PluginImplementation
public class SampleFormInterceptor extends BasePlugin implements FormInterceptor {
private static final Logger log = LoggerFactory.getLogger(SampleFormInterceptor.class);
private final String TEST_USER = "test";
@Autowired
private NodeBasePropertiesSrv nodeBasePropertiesSrv;
@Override
public String getName() {
return "SampleFormInterceptor";
}
/**
* Description of common features allowed to be implemented by this plugin type:
* 1. intercept the values of the properties before creation (add) what allows to:
* - update values
* - validate values
* - autocomplete values
* <p>
* 2. Intercept get properties or form elements to:
* - remove values ( fields )
* - change UI behaviour of form elements ( set fields as read-only, hide fields, etc )
* - create form elements on the fly what will not be keep in the database ( requires filtering in add and set stages )
* - apply mask to values to be displayed ( protect critical values )
* - change the order of the form elements
* <p>
* 3. intercept the values of the properties before update (set) to:
* - update values
* - validate values
* - autocomplete values
**/
@Override
public void add(String uuid, String grpName, Map<String, String> properties) throws ValidationFormException {
log.info("add({}, {}, {})", uuid, grpName, properties);
String userId = PrincipalUtils.getUser();
if (TEST_USER.equals(userId)) {
// Iterate through the properties map and log each property individually
log.info("Properties in group '{}' for node '{}':", grpName, uuid);
for (Map.Entry<String, String> entry : properties.entrySet()) {
log.info(" Property - Key: '{}', Value: '{}'", entry.getKey(), entry.getValue());
// update the value of the property with the key "okp:consulting.input1"
if ("okp:consulting.input1".equals(entry.getKey())) {
properties.put(entry.getKey(), entry.getValue() + " ( Updated by SampleFormInterceptor at add )");
} else if ("okp:consulting.input2".equals(entry.getKey())) {
String valueInput2 = entry.getValue();
if (StringUtils.isEmpty(valueInput2) || valueInput2.length() < 4) {
// Show error in UI
Map<String, List<ValidationError>> errors = new HashMap<>();
List<ValidationError> validationErrors = new ArrayList<>();
ValidationError validationError = new ValidationError();
validationError.setErrorMessage("Field input2 is mandatory and must have at least 4 characters");
validationError.setPropertyName("okp:consulting.input2");
validationError.setErrorCode("ERROR-003345");
validationError.setPropertyLabel("Input label 2");
validationError.setUuid(uuid);
validationErrors.add(validationError);
errors.put("Validation was not successfully", validationErrors);
throw new ValidationFormException(errors);
}
}
}
}
}
@Override
public void get(String uuid, String grpName, Map<String, String> properties, List<FormElement> formElements, boolean useDefaultValue,
boolean autocomplete) {
// Use default value is true when showing form elements before adding the metadata group
String userId = PrincipalUtils.getUser();
if (TEST_USER.equals(userId)) {
if (properties != null) {
properties.remove("okp:consulting.input1");
properties.put("okp:consulting.input3", "On the fly field");
}
if (CollectionUtils.isNotEmpty(formElements)) {
formElements.removeIf(formElement -> "okp:consulting.input1".equals(formElement.getName()));
// Add form element on the fly
Input input = new Input();
input.setName("okp:consulting.input3");
input.setLabel("Input label 3");
input.setType("text");
input.setValue("On the fly field");
input.setReadonly(true);
formElements.add(input);
}
}
}
@Override
public void set(String uuid, String grpName, Map<String, String> properties) throws ValidationFormException {
log.info("set({}, {}, {})", uuid, grpName, properties);
String userId = PrincipalUtils.getUser();
if (TEST_USER.equals(userId)) {
// Because the parameter "okp:consulting.input1" is not in the properties map, it will be added to the map
// to keep the properties map consistent with the form elements in the database
Map<String, String> currentProperties;
try {
currentProperties = nodeBasePropertiesSrv.getProperties(uuid, grpName, true);
} catch (PathNotFoundException | DatabaseException e) {
throw new RuntimeException(e);
}
if (currentProperties.containsKey("okp:consulting.input1")) {
properties.put("okp:consulting.input1", properties.get("okp:consulting.input1"));
}
if (properties.containsKey("okp:consulting.input2")) {
properties.put("okp:consulting.input2", properties.get("okp:consulting.input2"));
}
if (properties.containsKey("okp:consulting.input2")) {
String valueInput2 = properties.get("okp:consulting.input2");
if (StringUtils.isEmpty(valueInput2) || valueInput2.length() < 4) {
// Show error in UI
Map<String, List<ValidationError>> errors = new HashMap<>();
List<ValidationError> validationErrors = new ArrayList<>();
ValidationError validationError = new ValidationError();
validationError.setErrorMessage("Field input2 is mandatory and must have at least 4 characters");
validationError.setPropertyName("okp:consulting.input2");
validationError.setErrorCode("ERROR-003345");
validationError.setPropertyLabel("Input label 2");
validationError.setUuid(uuid);
validationErrors.add(validationError);
errors.put("Validation was not successfully", validationErrors);
throw new ValidationFormException(errors);
}
}
}
}
}