LSPS documentation logo
LSPS Documentation
Validating Record Values

Validation of record values checks the values of Record instances and their properties: Validation returns a list of validation messages for the values that do not meet the required criteria.

The criteria for values of records and their properties are defined as constraints. Each constraint defines its constraint type and maps to a Record or a Property. It is the constraint type that defines the semantics of the validation—for the constraint to be met, the value of the Record or property must meet the condition defined in the constraint type.

For example, you could define a constraint that binds the doesNotContainDigits constraint type to the record field givenName. Or you could define your own constraint type isISBN with a constraint expression that checks if a value is in the ISBN format and then a constraint that would bind it to such record fields as Book.ISBN or Journal.ISBN.

To check if a Record or property value meets the constraints, call the validate() function. The function returns a list of constraint violations: each failed constraint is added to the list as a ConstraintViolation with a message returned by the constraint expression of their constraint type, the record instance that failed the validation, and their constraint definition.

You can call the validate() function:

  • over a record field instance: all constraints defined for the record field within the model are checked.
  • over a record instance: all constraints on the record's fields, the record itself, and its super types are validated and that in this order.

To provide additional granularity to validation on runtime, the validate() call can have tags as its arguments: on validation, the constraint is applied only if the tags of the validate() call are identical to the constraint's tags expression. This applies only if any of the constraints for the record or record field define a tag expression. If the constraints do not contain any tags, they are applied on any validate() call.

When validating Record data from a ui::form, the violation messages can be displayed in the form with the showConstraintViolations() function.

validatewithconstraints.png
Validating record value using constraints

Defining Constraints

To define a constraint for a Record or a Record Field, do the following:

  1. Open or create a constraint definition file.
  2. In the constraint editor, do the following:
    1. In the Constraint area, click Add.
    2. In the Constraint Details area, define the constraint details:
      • ID: unique identifier of the constraint

        It is recommended to use IDs in the format <RecordName>.<FieldName>.<ConstraintTypeName>, such as, Book.ISBN.Format, Book.ISBN.NotNull, ISIN.IsNumber, ISIN.HasMinLength, etc.

      • Record (property): record or record Field to which the constraint applies

        Use the dot operator to use records or record Fields on Data Relationship ends.

      • Tags: expression that results in a list of tags

        Tags serve to filter constraints that are applied on validation of the Record or Record Field.

        Example Tag expression

        tag1 and (tag2 or tag3) and not tag4
      • Constraint type: constraint type that defines the constraint expression, type, parameters
creatingConstraint.png
Defining constraints

Defining Constraint Types

Note: The Standard Library contains a rich set of constraint types. Hence check the available constraint types before you define custom constraint types.

To define a constraint type, do the following:

  1. Open or create a constraint type definition file.
  2. In the constraint type editor, do the following:
    1. In the Constraint Types area, click Add.
    2. In the Constraint Type Details area, define the constraint type details.

Every constraint type defines the following properties:

  • Name: name of the constraint type

    The constraint type name should refer to what is validated, for example, IsEmail, IsNumber, HasMinLength, etc.

  • Applied to: data type to which the constraint type can apply
  • Generic types: Type parameters allow a constraint type to operate over a parameter that can be of different data types in different calls. The concept is based on generics as used in Java. You can also make a generic data type extend another data type with the extends keyword. The syntax is then <type_param_1> extends <type1>, <type_param_2> extends <type2>.
  • Parameters: input parameters of the constraint type

    The following parameters are provided by default and cannot be deleted:

    • value: input object value (the value is automatically filled in based on the Applied to data type)
    • context: additional data that can be passed as parameters

      The context parameter can be used instead of tags. It is an object of the type Map<String, Object> and when defined by the validate() call, the call cannot define any tag arguments.

    • constraintId: ID of the constraint definition that calls the constraint

      You can define additional parameters.

  • Type: return type of the constraint expression
    • simple: Expression return value is a String which represents the error message.
    • complex: Expression return value is a list of ConstraintViolation objects or their subtype.

      Complex types allow cascading validation when related records and records fields are validated as part of the record validation.

  • Expression: constraint check expression

    If validation is successful, the expression must return null; if it fails, it must return

  • a String when Type is set to simple or a list of ConstraintViolation objects when Type is complex.
definingConstraintType.png
Defining constraint type

Filtering Constraints using Tags

A constraint can define a tag expression, which must evaluate to true for the constraint to be applied: The expression serves as a filter on constraints. When the validate() function is called, the constraint definition is invoked only if the validate() call contains at least one of the constraint's tags as its argument. If the constraints do not contain any tags, they are applied on any validate() call of the Record or Record field.

Validation tags can contain subtags. They allow you to create hierarchical tags: if a tag contains a collection of subtags, the tag is considered a union of its subtags.

For example, if a tag Car defines subtags ProductionYear and Model, on validate() call, the tag Car resolves to the ProductionYear and Model tags.

Defining Tags

To define tags, do the following:

  1. Create a Validation Tag Definition (right-click your module, then click New -> Validation Tag Definition)
  2. Double-click the definition to open it in the Validation Tag Editor.
  3. In the Validation Tags area, click Add.
  4. In the Validation Tag Details area, define the tag's properties.