Validators

The validation of a single input field is done by a sequence of so called validators. Every validator does process the current input value in some way and passes the result to the next validator in the sequence (or, if it fails to process, the validation of this input field is cancelled). The sequence of validators is divided into three parts (matching, converting and checking), each of them containing a specific type of validators (matchers, converters and checkers, respectively). Let's have a closer look at the three phases of validation:

  1. Matching: The first phase of input validation is done by a sequence of matchers. A matcher takes the current input value (a string) and accepts it or not (according to his predefined rules). If it does accept the input string, it returns a result string, which is then taken as the current input field value and passed to the next validator (i.e., another matcher or a converter). Typical examples for matchers are the TrimMatcher, which removes leading and trailing spaces, and the RegExpMatcher, which matches the input string against a given regular expression (both can be found in the de.odysseus.calyxo.forms.match package, where the predefined Calyxo Forms matchers are implemented).
  2. Converting: The second phase of input validation is done by a single converter. A converter takes the current input value (a string) and tries to convert it to a value from its corresponding domain (i.e., booleans, numbers, dates, etc.). If the input string is a valid string representation of such a value, this value is taken as the current input field value and passed to the next validator (i.e., a checker). Typical examples for converters are the BooleanConverter, which converts the strings "true" and "false" to the corresponding values of java.lang.Boolean, and the LongConverter, which converts to java.lang.Long instances (both can be found in the de.odysseus.calyxo.forms.convert package, where the predefined Calyxo Forms converters are implemented).
  3. Checking: The third phase of input validation is done by a sequence of checkers. A checker takes the current input value and accepts it or not (according to his predefined rules). A checker does not change the current input value. If the input is accepted the validation continues with the next validator (i.e., a checker), if there is one. Typical examples for checkers are the LengthChecker, which assures that the length of a string is in a given interval, and the RangeChecker, which does a similar job for a numerical value. (both can be found in the de.odysseus.calyxo.forms.check package, where the predefined Calyxo Forms checkers are implemented).

Implementation, declaration and usage

In general, to use a validator for the validation of an input field the following three steps have to be executed:

  1. Implementation: Write a Java class implementing one of the three validator interfaces defined in the de.odysseus.calyxo.forms package: Matcher, Converter or Checker. Chances are good, that you are not required to do so too soon, since Calyxo Forms offers a whole bunch of validators covering standard tasks. If you are interested in writing custom validators, have a look into the Validators section of the extension points documentation.
  2. Declaration: Add a <matcher>, <converter> or <checker> element to the <validators> section of your configuration file, which refers to your class and defines a name, properties and a message for your new validator. This will be explained in more detail below.
  3. Usage: Add a <match>, <convert> or <check> element, which refers to the name of the validator defined in step 2., to every <field> element of your configuration file's <forms> section, where you like to use your validator. This is the only step you need to care about, when you're satisfied with Calyxo's built-in validators. It will be further illustrated in the Fields section.

Declaring a custom validator

As mentioned above, you need to declare your custom validators in the <validators> section of your forms configuration file. Even if you did not implement any validators as Java classes, you might find it useful, to declare a validator using one of Calyxo's built-in validator classes. All of them are already declared in the file calyxo-validators.xml, a copy of which can be found in the directory CALYXO_HOME/calyxo-forms/conf/share/. When using them in your form validation, you can change their properties and/or message whenever you need. But if you intend to do so in the same way at many different input fields, it might be easier to declare a custom validator.

Let's look at an example defining a customized version of the LengthChecker, which is used to check the length of an input string:

<validators>
  <checker id="length8"
    class="de.odysseus.calyxo.forms.check.LengthChecker">

    <property name="min" value="8"/>
    <property name="max" value="8"/>

    <message key="error.check.length8" bundle="foo.msg">
      <arg name="field"/>
    </message>

  </checker>
</validators>

Now the checker with name "length8" is ready to be used for field validation. It will check the given input string to consist of exactly eight characters (since both of it's properties, i.e. min and max have been set to 8) and will generate an appropriate error message if the test fails. The message has to be configured in the file msg.properties in package foo, for example with the entry "error.check.length8=Field '{0}' must have a length of 8". The single argument of the message has been named "field" by placing <arg name=…> in the body of the message element. This increases the readability of the field validations, especially for messages with more than one argument.

Let's have a glance at using your new validator, though this is not our topic in this section. To check the input for property bar to be exactly of length eight (and generate the message "Field 'Bar' must have a length of 8" if it fails) you simply add the following lines to your <form> definition:

<field property="bar">

  <check name="length8">
    <message>
      <arg name="field" value="Bar"/>
    </message>
  </check>

</field>