Custom Validation Rules - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 11. There's an updated version available that covers our most recent release.

01-09-2016

Custom Validation Rules

Overview

In addition to the regular-expression-based validation rules for fields, the Enterprise Forms add-on includes support for custom Java-based validation rules for fields, groups and pages. Custom rules can be added by implementing a simple Java interface, and adding a configuration node in the repository. Custom rules can be selected by the form author using the validation rules dropdown in the form field properties panel.

Rule Development

A custom validation rule class should be on the classpath of the site application, and must implement the interface com.onehippo.cms7.eforms.hst.validation.rules.ValidationRule:

public interface ValidationRule {
    boolean validate(Map<String, String[]> fieldValuesMap);

    RuleType getType();

    ErrorMessage getMessage(final String name, final String label,
                            final String value);

    ErrorMessage getMessage(String name, String label, String value,
                            Locale locale);

    String getRuleLabel();

}

For convenience, custom validation rule classes can extend the abstract base class com.onehippo.cms7.eforms.hst.validation.rules.BaseRule. This leaves the following methods to be implemented by the custom rule class:

boolean validate(Map<String, String[]> fieldValuesMap)

Validates the form input. The fieldValuesMap parameter contains the form field names and values within the rule's scope, i.e. for a field validation rule it contains only one field value, and for a page or group it contains all the field values in the page or group.

RuleType getType();

Returns one of the validation rule types enumerated in com.onehippo.cms7.eforms.hst.validation.rules.RuleType. Custom rules should return one of the following three:

  • RuleType.CUSTOM_FIELD_VALIDATION_RULE
  • RuleType.CUSTOM_GROUP_VALIDATION_RULE
  • RuleType.CUSTOM_PAGE_VALIDATION_RULE

protected String getResourceBundleBaseName()

Typically, a custom rule should provide its own resource bundle for localized messages, so this method should return the validation rule's fully qualified class name. The recommended approach is to provide these through Java resource bundles. From Enterprise Forms 3.0.1 onwards, these resource bundles can also be provided as Repository resource bundles. The Repository resource bundles are loaded first, in case no bundles are found, a fallback is done to the Java resource bundles.

public ErrorMessage getMessage(String name, String label, String value)

Returns a com.onehippo.cms7.eforms.hst.model.ErrorMessage.

The Enterprise Forms add-on includes an example custom field validation rule com.onehippo.cms7.eforms.hst.validation.rules.LuhnRule which implement the Luhn Algorithm, commonly used for shallow credit card number validity checks:

public class LuhnRule extends BaseRule {
    public static final String MESSAGE_KEY = "validation.message.luhn";

    @Override
    public boolean validate(Map<String, String[]> fieldValuesMap) {

        if (fieldValuesMap.isEmpty()) {
            return true;
        }

        // assuming one item
        String[] values = fieldValuesMap.values().iterator().next();

        if (ArrayUtils.isEmpty(values)) {
            return true;
        }

        for (String value : values) {

            if (StringUtils.isBlank(value)) {
                continue;
            }

            int sum = 0;
            boolean alternate = false;
            for (int i = value.length() - 1; i >= 0; i--) {
                try {
                    int n = Integer.parseInt(value.substring(i, i + 1));
                    if (alternate) {
                        n *= 2;
                        if (n > 9) {
                            n = (n % 10) + 1;
                        }
                    }
                    sum += n;
                    alternate = !alternate;
                } catch (NumberFormatException e) {
                    return false;
                }
            }

            if (!(sum % 10 == 0)) {
                return false;
            }
        }

        return true;
    }

    @Override
    public RuleType getType() {
        return RuleType.CUSTOM_FIELD_VALIDATION_RULE;
    }

    @Override
    protected String getResourceBundleBaseName() {
        return getClass().getCanonicalName();
    }

    @Override
    public ErrorMessage getMessage(String name, String label, String value) {
        return new ErrorMessage(MESSAGE_KEY, name, label, "Field " + label + " is invalid");
    }
}

The Enterprise Forms demo also includes an example page validation rule ( com.onehippo.cms7.eforms.demo.validationrules.NoEmptyFieldsOnPageRule) and an example group validation rule ( com.onehippo.cms7.eforms.demo.validationrules.NoEmptyFieldsInGroupRule).

Rule Configuration

Custom validation rules are configured in the repository under /hippo:configuration/hippo:modules/eforms/hippo:moduleconfig/eforms:validationrules (this is the same place where regular-expression-based rules are configured).

For each custom validation rule, a node name eforms:validationrule of type nt:unstructured must be created and have the following properties:

  • eforms:validationruleclass: The fully qualified class name of the validation rule class.

  • eforms:validationruleid: An alphanumeric identifier for the rule.

  • eforms:validationrulelabel: A human-readable identifier for the rule.

  • eforms:validationruleforpage (boolean): for page validation rules (i.e. method # getType() returning RuleType.CUSTOM_PAGE_VALIDATION_RULE) it is required and must be true. For field and group validation rules it is optional and must be false .

  • eforms:validationruleforgroup (boolean): for group validation rules (i.e. method # getType() returning RuleType.CUSTOM_GROUP_VALIDATION_RULE) it is required and must be true . Otherwise it is optional and must be false for field and page validation rules.

The Enterprise Forms demo includes configuration for all three provided example rules.

The "Luhn Algorithm" example field validation rule:

<sv:node sv:name="eforms:validationrule"
        xmlns:sv="http://www.jcp.org/jcr/sv/1.0">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>nt:unstructured</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleclass" sv:type="String">
    <sv:value>
       com.onehippo.cms7.eforms.hst.validation.rules.LuhnRule
    </sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleid" sv:type="String">
    <sv:value>luhn</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationrulelabel" sv:type="String">
    <sv:value>Luhn Algorithm</sv:value>
  </sv:property>
</sv:node> 

The "No empty field in group" example group validation rule:

<sv:node sv:name="eforms:validationrule"
         xmlns:sv="http://www.jcp.org/jcr/sv/1.0">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>nt:unstructured</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleclass" sv:type="String">
    <sv:value>
      com.onehippo.cms7.eforms.demo.validationrules.NoEmptyFieldsInGroupRule
    </sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleforgroup" sv:type="Boolean">
    <sv:value>true</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleid" sv:type="String">
    <sv:value>noemptyfieldsingroup</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationrulelabel" sv:type="String">
    <sv:value>No empty fields in group</sv:value>
  </sv:property>
</sv:node> 

The "No empty field in page" example page validation rule:

<sv:node sv:name="eforms:validationrule"
         xmlns:sv="http://www.jcp.org/jcr/sv/1.0">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>nt:unstructured</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleclass" sv:type="String">
    <sv:value>
      com.onehippo.cms7.eforms.demo.validationrules.NoEmptyFieldsOnPageRule
    </sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleforpage" sv:type="Boolean">
    <sv:value>true</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationruleid" sv:type="String">
    <sv:value>noemptyfieldsonpage</sv:value>
  </sv:property>
  <sv:property sv:name="eforms:validationrulelabel" sv:type="String">
    <sv:value>No empty fields in page</sv:value>
  </sv:property>
</sv:node> 

Rule Selection

To configure a form item (field, group or page) to use a custom validation rule, simply select the item and in its properties box, select the rule from the "Validation Rule" dropdown:

Save and publish the form. In the site application, verify that the validation rule is active in the site application by submitting the form with invalid values:

 

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?