 | Work in progress
This article is a work in progress. It's currently being reviewed.
If you have any remarks about this text please send them to dev@springmodules.dev.java.net . |
 | Note
In release 0.4, valang was moved out of the sandbox. This move was part of a general restructuring of the validation module (now valang as well as commons validator support) are part of the validation module) in which package names were changed, bugs were fixed, and new features were added. For more information about these changes, please refer to the change log of this release. |
Valang validator allows you to write declarative validation rules using an intuitive syntax. The purpose of Valang validator is:
- to quickly write validation rules without the need to create a class or write Java code.
- to ease the use of the Spring validation tools.
- to make validation rules compact, easily readable and maintainable.
Getting started
 | Getting the code
To use Valang validator you need to get the latest Spring Modules from CVS and run ant sandbox.jar. |
To add your own validator using Valang validator in your Spring configuration file use the org.springmodules.validation.ValangValidatorFactoryBean class:
<bean id="myValidator" class="org.springmodules.validation.valang.ValangValidator">
<property name="valang">
<value><![CDATA[
{ firstName : length(?) < 30 : 'First name too long' }
{ lastName : length(?) < 50 : 'Last name too long' }
]]></value>
</property>
</bean>
Usage
ValangValidator is a org.springframework.validation.Validator implementation. Any bean can be validated by this validator. However, if the bean does not contain a property used in the validation script an exception will be thrown.
 | Note
Prior to release 0.4, the org.springmodules.validation.ValangValidatorFactoryBean could be used as an alternative to org.springmodules.validation.ValangValidator. Since both classes served the same purpose, the former was deprecated and is planned to be removed in 0.5. |
Syntax
The Valang syntax consists of one syntax that can be repeated:
If evalutation of the rule fails the key is rejected with the message and optionally the error code and error parameters.
<key>
<key> is mandatory. Its value is used as a reject code when the evaluation of the rule fails. The value of the key may or may not be a bean property.
<rule>
<rule> is mandatory. The rule syntax is a set of one or more expressions combined with parentheses:
<predicate>
A predicate is a simple evaluation against and operator involving literals, bean properties or both and optionally functions and mathematical experessions.
Operators
Supported operators are:
- Binary operators:
- String, boolean, date and number operators:
- = | == | IS | EQUALS
- != | <> | >< | IS NOT | NOT EQUALS
- Number and date operators:
- > | GREATER THAN | IS GREATER THAN
- < | LESS THAN | IS LESS THAN
- => | >= | GREATER THAN OR EQUALS | IS GREATER THAN OR EQUALS
- <= | =< | LESS THAN OR EQUALS | IS LESS THAN OR EQUALS
- Unary operators:
- Object operators:
- IS NULL | NULL
- IS NOT NULL | NOT NULL
- String operators:
- HAS TEXT
- HAS NO TEXT
- HAS LENGTH
- HAS NO LENGTH
- IS BLANK
- IS NOT BLANK
- IS UPPERCASE | IS UPPER CASE | IS UPPER
- IS NOT UPPERCASE | IS NOT UPPER CASE | IS NOT UPPER
- IS LOWERCASE | IS LOWER CASE | IS LOWER
- IS NOT LOWERCASE | IS NOT LOWER CASE | IS NOT LOWER
- IS WORD
- IS NOT WORD
- Special operators:
- BETWEEN
- NOT BETWEEN
- IN
- NOT IN
- NOT
These operators are case insensitive. Binary operators have a left and a right side. Unary operators only have a left side.
Value types for both sides of binary operators must always match.
Some invalid examples:
BETWEEN / NOT BETWEEN operators
The between and not between operators have a special syntax:
Both the left side and the values can be any valid combination of literals, bean properties, functions and mathematical operations.
Some examples:
IN / NOT IN operators
The in and not in operators have a special syntax:
Both the left side and the values can be any valid combination of literals, bean properties, functions and mathematical operations.
There's another special syntax where a java.util.Collection, java.util.Enumeration, java.util.Iterator or object array instance can be retrieved from a bean property. The values of said instance are than used as right side of the in or not in operator. This feature allows you to create dynamic sets of values based on other values of the bean.
Some examples:
NOT operator
The not operator has a special syntax:
The not operator inverses the result of one or a set of predicates.
Literals
Supported literals are:
- string
- number
- date
- boolean
Spring literals
Strings are quoted with single quotes:
Number literals
Number literals are unquoted and are parsed by java.math.BigDecimal.
Date literals
Date literals are delimited with square brackets and are parsed upon each evalution by a special purpose date parser.
TODO: write documentation for date parser.
Boolean literals
Boolean literals are not quoted.
Bean properties
Type the name of the property to refer to a bean property:
The special bean property ? (question mark) refers to the key. If you want to use ? make sure the key corresponds to a valid bean property.
Lists elements
List elements can be accessed through their index number in the list.
Map entries
Values in map entries can be accessed through their key names. Keys must be string values.
Functions
Function syntax is:
Functions shipped with Valang validator are:
| Name |
Description |
| length |
Returns the size of the passed in collection or array. If the passed in argument is neither,
the length of the string returned from the toString() call on the passed in argument. |
| len |
see length |
| size |
see length |
| count |
see length |
match |
Matches the given regular expression (first argument) to the string returned from the toString() call on the passed in value (second argument). |
matches |
see match |
email |
Returns true if the string returned from the toString() call on the passed in argument
represents a valid email |
| upper |
Convert the value of the toString() method of a value to upper case. |
| lower |
same as upper but lower case. |
| ! |
not operation on a boolean value. |
| resolve |
wrap string in org.springframework.context.support.DefaultMessageSourceResolvable. |
| inRole |
Accepts a role name as an argument and returns true if the current user has this role. This function uses Acegi to fetch the current user. |
Function examples:
Mathematical expressions
Supported mathematical operators are:
Parentheses are supported and expression are parsed left to right so that
Values in expression can be literals, bean properties and functions.
Expression examples:
<message>
<message> is mandatory but can be an empty string if not used. The message is not parsed.
If no localized message is found this message will be used.
Localization
<error_code> and <error_parameters> support localization.
<error_code>
<error_code> is optional unless <error_parameters> is provided.
This key is used to find a localized message.
<error_parameters>
<error_parameters> is optional.
If error parameters are provided localized messages will be parsed before being displayed. {0} corresponds to the first parameters, {1} to the second and so on.
Customizations
Custom functions
Users can register custom functions to extend the functionality of the parser. This allows extending the functionality of the validator with user code.
To write a custom function extend org.springmodules.valang.function.AbstractFunction. Custom functions must implement the sole constructor of AbstractFunction. The doGetResult function must be implemented.
public class MyFunction extends AbstractFunction {
public MyFunction(Function[] arguments, int line, int column) {
super(arguments, line, column);
definedExactNumberOfArguments(1);
}
public Object doGetResult(Object target) {
return null;
}
}
Customize date parser
To add a custom date format to the date parser users must provide a regular expression that matches the date format and a date format.
The regular expression must only match the date format. Providing a regular expression that is not sufficiently strict may cause the date parser to stop working properly.
<bean id="myValidator" class="org.springmodules.validation.valang.ValangValidator">
<property name="valang">
<value><![CDATA[
{ firstName : length(?) < 30 : 'First name too long' }
{ lastName : length(?) < 50 : 'Last name too long' }
]]></value>
</property>
<property name="dateParserRegistrations">
<map>
<entry key="^\\d{2}:\\d{2} \\d{8}$" value="HH:mm yyyyMMdd">
</map>
</property>
</bean>