Creating your own Form Validator plugin

Single field validation

Form validators are used to implement complex logic that must be evaluated on the server side and are not covered by the default Metadata Validator element.

You can create your own Form Validator.

Conditions:

  • The new Form Validator class must implement the "FieldValidator" interface.
  • The new Form Validator class must be declared under the package "com.openkm.plugin.form.validator".
  • The new Form Validator class must be annotated with "@PluginImplementation".
  • The new Form Validator class must extend "BasePlugin".

Form Validator interface:

package com.openkm.plugin.form;

import net.xeoh.plugins.base.Plugin;

import java.util.List;

/**
 * FieldValidator
 */
public interface FieldValidator extends Plugin {

    String getName();

    String validate(String value, List<String> uuids);
}

The new class must be loaded into the package com.openkm.plugin.form.validator because the application plugin system will try to load it from there.

Do not omit the tag @PluginImplementation; otherwise the application plugin system will not be able to retrieve the new class.

 

More information at Register a new plugin.

Methods description

MethodTypeDescription

getName()

String

The method returns the name of the plugin used in the form list selector.

validate(String value, List<String> uuids)

String

When the returned string equals "", the application considers everything correct; otherwise, the returned text is the error.

The value variable contains the value of the metadata field, and the uuids are the list of UUIDs of the affected nodes (documents, folders, mails, records).

If only one node will be updated (the common case), the list will contain only one uuid. If multiple nodes are selected, it will contain the list of all selected nodes to which the metadata changes should be applied.

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="Technology" name="okg:technology">
        <input label="Title" type="text" name="okp:technology.title"/>
        <input label="Date" type="date" name="okp:technology.date" />
        <textarea label="Description" name="okp:technology.description"/>
        <select label="Type" name="okp:technology.type" type="multiple">
            <option label="New Product" value="t1"/>
            <option label="New Feature" value="t2" />
            <option label="Customatization" value="t3" />
            <option label="Integration" value="t4" />
            <option label="Quality" value="t5" />
            <option label="Other" value="t6" />
        </select>
        <select label="Priority" name="okp:technology.priority" type="simple">
            <option label="low" value="low"/>
            <option label="Medium" value="Medium"/>
            <option label="High" value="High" />
        </select>
        <textarea label="Comment" name="okp:technology.comment">
            <validator type="plugin" parameter="com.openkm.plugin.form.validator.DuplicateDocumentNumberValidator"/>
        </textarea>
        <input label="Link" type="link" name="okp:technology.link"/>
    </property-group>
</property-groups>

In this example, two identical comments will not be allowed in the metadata field named okp:technology.comment.

package com.openkm.plugin.form.validator;

import java.util.ArrayList;
import java.util.List;

import com.openkm.module.db.stuff.DbSessionManager;
import com.openkm.plugin.form.FieldValidator;
import org.springframework.beans.factory.annotation.Autowired;

import com.openkm.api.OKMRelation;
import com.openkm.bean.Relation;
import com.openkm.db.service.LegacySrv;
import com.openkm.plugin.BasePlugin;

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

@PluginImplementation
public class DuplicateDocumentNumberValidator extends BasePlugin implements FieldValidator {

    @Autowired
    private LegacySrv legacySrv;

    @Autowired
    private OKMRelation okmRelation;

    @Override
    public String getName() {
        return "Duplicated document number";
    }

    @Override
    public String validate(String value, List<String> uuids) {
        String validate = "";
        String token = DbSessionManager.getInstance().getSystemToken();
        String sql = "SELECT RGT_UUID FROM OKM_PGRP_CUR_TECHNOLOGY WHERE RGT_PRO_COMMENT='" + value + "'";

        try {
            List<List<String>> result = legacySrv.executeSQL(sql);
            if (result.size() > 0) {
                if (uuids.isEmpty()) {
                    validate = "Duplicated document number";
                } else {
                    List<String> allowedUuids = new ArrayList<>();
                    for (String uuid : uuids) {
                        allowedUuids.add(uuid);
                        List<Relation> relations = okmRelation.getRelations(token, uuid);
                        for (Relation relation : relations) {
                            allowedUuids.add(relation.getNode());
                        }
                    }

                    for (List<String> resultList : result) {
                        if (!allowedUuids.contains(resultList.get(0))) {
                            validate = "Duplicated document number";
                        }
                    }
                }
            }
        } catch (Exception e) {
            validate = e.getMessage();
        }

        return validate;
    }
}

Full form validation

Deprecated as of version 8.1.15; we suggest using Creating your own FormInterceptor plugin.

This method is executed when adding, updating, and when checking if a node can be promoted to a record.

The application checks if a node can be promoted to a record when the file plan configuration is enabled.

The variable fullValidation is set to true only when the application is checking if a node can be promoted to a record.

Form validators are used to implement complex logic that must be evaluated on the server side and are not covered by the default Metadata Validator element.

You can create your own Form Validator.

Conditions:

  • The new Form Validator class must implement the "FormValidator" interface.
  • The new Form Validator class must be declared under the package "com.openkm.plugin.form.validator".
  • The new Form Validator class must be annotated with "@PluginImplementation".
  • The new Form Validator class must extend "BasePlugin".

Form Validator interface:

package com.openkm.plugin.form;

import net.xeoh.plugins.base.Plugin;

import java.util.List;

/**
 * FormValidator
 *
 */
public interface FormValidator extends Plugin {
	void validate(NodeBase node, String grpName, Map<String, String> properties, boolean fullValidation) throws ValidationFormException;

	String getName();
}

The new class must be loaded into the package com.openkm.plugin.form.validator because the application plugin system will try to load it from there.

Do not omit the tag @PluginImplementation; otherwise the application plugin system will not be able to retrieve the new class.

 

More information at Register a new plugin.

Methods description

MethodTypeDescription

getName()

String

The method returns the name of the plugin used in the form list selector.

validate(NodeBase node, String grpName, Map<String, String> properties, boolean fullValidation)

Void

When an error is found, an exception of type ValidationFormException should be thrown.

The node variable is the OpenKM node where the user added or updated the metadata.

The grpName is the name of the metadata group.

The properties variable contains a map with all the metadata values set by the user.

The variable fullValidation is set to true when checking if a node can be promoted to a record.

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="Full validation" name="okg:full" validatorClassName="com.openkm.plugin.form.validator.FullMetadataValidationSample">
        <input label="Field 1" name="okp:full.number1"></input>
        <input label="Field 2" name="okp:full.number2"></input>
        <input label="Field 3" name="okp:full.number3"></input>
    </property-group>
</property-groups>

In this example, the fields should have numeric values and field1 < field2 < field3:

import com.company.MetadataConstants;
import com.openkm.bean.form.ValidationError;
import com.openkm.core.ValidationFormException;
import com.openkm.db.bean.NodeBase;
import com.openkm.plugin.BasePlugin;
import net.xeoh.plugins.base.annotations.PluginImplementation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@PluginImplementation
public class FullMetadataValidationSample extends BasePlugin implements FormValidator {

    @Override
    public void validate(NodeBase nodeBase, String grpName, Map<String, String> properties, boolean fullValidation) throws ValidationFormException {
		Map<String, List<ValidationError>> errors = new HashMap<>();
		List<ValidationError> validationErrors = new ArrayList<>();
		String field1 = properties.get(MetadataConstants.LOCATION_PROPERTY_NUMBER1_NAME);
		String field2 = properties.get(MetadataConstants.LOCATION_PROPERTY_NUMBER2_NAME);
		String field3 = properties.get(MetadataConstants.LOCATION_PROPERTY_NUMBER3_NAME);
		int field1Values = 0;
		int field2Values = 0;
		int field3Values = 0;

		// Parse integer
		try {
			field1Values = Integer.parseInt(field1);
		} catch (Exception e) {
			ValidationError validationError = new ValidationError();
			validationError.setErrorMessage("Field 1 seems does not contain an integer");
			validationError.setPropertyName(MetadataConstants.LOCATION_PROPERTY_NUMBER1_NAME);
			validationError.setErrorCode("ERROR-003345");
			validationError.setPropertyLabel("First number");
			validationError.setUuid(nodeBase.getUuid());
			validationErrors.add(validationError);
		}

		try {
			field2Values = Integer.parseInt(field2);
		} catch (Exception e) {
			ValidationError validationError = new ValidationError();
			validationError.setErrorMessage("Field 2 seems does not contain an integer");
			validationError.setPropertyName(MetadataConstants.LOCATION_PROPERTY_NUMBER2_NAME);
			validationError.setErrorCode("ERROR-003345");
			validationError.setPropertyLabel("First number");
			validationError.setUuid(nodeBase.getUuid());
			validationErrors.add(validationError);
		}

		try {
			field3Values = Integer.parseInt(field3);
		} catch (Exception e) {
			ValidationError validationError = new ValidationError();
			validationError.setErrorMessage("Field 3 seems does not contain an integer");
			validationError.setPropertyName(MetadataConstants.LOCATION_PROPERTY_NUMBER2_NAME);
			validationError.setErrorCode("ERROR-003345");
			validationError.setPropertyLabel("First number");
			validationError.setUuid(nodeBase.getUuid());
			validationErrors.add(validationError);
		}

		// Field2 value greather than field1
		if (field2Values < field1Values) {
			ValidationError validationError = new ValidationError();
			validationError.setErrorMessage("Field 1 is greater than field2");
			validationError.setPropertyName(MetadataConstants.LOCATION_PROPERTY_NUMBER2_NAME);
			validationError.setErrorCode("ERROR-003345");
			validationError.setPropertyLabel("Second number");
			validationError.setUuid(nodeBase.getUuid());
			validationErrors.add(validationError);
		}

		// Field2 value greather than field1
		if (field3Values < field2Values) {
			ValidationError validationError = new ValidationError();
			validationError.setErrorMessage("Field 2 is greater than field3");
			validationError.setPropertyName(MetadataConstants.LOCATION_PROPERTY_NUMBER3_NAME);
			validationError.setErrorCode("ERROR-003345");
			validationError.setPropertyLabel("Second number");
			validationError.setUuid(nodeBase.getUuid());
			validationErrors.add(validationError);
		}

		if (validationErrors.size() > 0) {
			errors.put("Validation was not successfully", validationErrors);
			throw new ValidationFormException(errors);
		}
    }

    @Override
    public String getName() {
        return "Full metadata validation sample";
    }
}