4.5.2.3.4. Validator

Валидатор предназначен для проверки значения, введенного в визуальном компоненте.

Следует отличать валидацию от проверки типа данных. Если для некоторого компонента, например TextField, задан тип, отличный от строкового (это происходит при связывании с атрибутом сущности или назначении datatype), то компонент не позволяет ввести значение, не удовлетворяющее этому типу - при потере фокуса или нажатии Enter компонент отобразит предыдущее значение.

Валидация же срабатывает не сразу при вводе или потере компонентом фокуса, а только при вызове у компонента метода validate(). Это означает, что компонент (и связанный с ним атрибут сущности) может некоторое время содержать значение, не удовлетворяющее условиям валидации. Это не является проблемой, так как обычно компоненты ввода с валидацией располагаются в экране редактирования, а он автоматически вызывает валидацию всех своих компонентов перед коммитом. Если же компонент находится не в экране редактирования, то необходимо вызывать его метод validate() в контроллере явно.

В XML-дескрипторе экрана валидатор для компонента может быть задан во вложенном элементе validator. Возможные атрибуты элемента validator:

  • script − путь к скрипту Groovy, осуществляющему валидацию.

  • class − имя класса Java, реализующего интерфейс Field.Validator.

  • Groovy-валидатор и стандартные классы Java-валидаторов, расположенные в пакете com.haulmont.cuba.gui.components.validators поддерживают атрибут message − сообщение, выводимое пользователю в случае ошибки валидации. Атрибут должен содержать сообщение или ключ в пакете сообщений экрана, например:

    <validator class="com.haulmont.cuba.gui.components.validators.PatternValidator"
               message="msg://validationError"
               pattern="\d{3}"/>

    # messages.properties
    validationError = Input error

Выбор механизма валидации осуществляется следующим образом:

  • Если не указано значение атрибута script, и сам элемент validator не содержит текста выражения Groovy, то в качестве валидатора используется класс, указанный в атрибуте class.

  • Если элемент validator содержит текст, то он будет использован как выражение Groovy и выполнен с помощью Scripting.

  • В противном случае с помощью Scripting будет выполнен скрипт Groovy, указанный в атрибуте script.

В выражение или скрипт Groovy будет передана одна переменная value, содержащая значение, введенное в визуальном компоненте. Выражение или скрипт должны вернуть boolean значение: true − valid, false − not valid.

Если в качестве валидатора используется класс Java, то он должен иметь либо дефолтный конструктор без параметров, либо конструктор со следующим набором параметров:

  • org.dom4j.Element, String - в этот конструктор будут переданы XML-элемент валидатора и имя пакета сообщений экрана.

  • org.dom4j.Element - в этот конструктор будет передан XML-элемент валидатора.

Если валидатор реализован внутренним классом, то он должен быть объявлен с модификатором static, а его имя для загрузки отделяется символом "$", например:

<validator class="com.sample.sales.gui.AddressEdit$ZipValidator"/>

Платформа уже содержит несколько реализаций наиболее часто используемых валидаторов (см. пакет com.haulmont.cuba.gui.components.validators), которые можно применять в проектах:

  • DateValidator

  • DoubleValidator

  • EmailValidator

  • IntegerValidator

  • LongValidator

  • PatternValidator

  • ScriptValidator

Валидатор-класс можно назначить компоненту не только в XML-дескрипторе экрана, но и программно, передавая экземпляр валидатора в метод addValidator() компонента.

Пример создания класса валидатора почтового индекса:

public class ZipValidator implements Field.Validator {
    @Override
    public void validate(Object value) throws ValidationException {
        if (value != null && ((String) value).length() != 6)
            throw new ValidationException("Zip must be of 6 characters length");
    }
}

Использование валидатора почтового индекса и стандартного валидатора по шаблону в полях компонента FieldGroup:

<fieldGroup>
    <field id="zip" required="true">
         <validator class="com.company.sample.gui.ZipValidator"/>
    </field>
    <field id="imei">
        <validator class="com.haulmont.cuba.gui.components.validators.PatternValidator"
               pattern="\d{15}"
               message="IMEI validation failed"/>
    </field>
</fieldGroup>

Пример программного задания валидатора:

if (Boolean.TRUE.equals(parameter.getRequired())) {
    tokenList.addValidator(new Field.Validator() {
        @Override
        public void validate(Object value) throws ValidationException {
            if (value instanceof Collection && CollectionUtils.isEmpty((Collection) value)) {
                throw new ValidationException(getMessage("paramIsRequiredButEmpty"));
            }
        }
    });
}