Pull to refresh

Биндинг и валидация JSR295

Reading time3 min
Views6.3K
Преамбула

На досуге решил разобрать биндинг и валидацию в Java Beans Binding (JSR 295). Реализация предлагаемая JSR 295 показалась мне проще и удобнее, чем аналогичный функционал, предоставляемый в рамках JGoodies.

Ниже рассмотрю два небольших примера биндинга контролов и пример создания и использования валидатора.

Биндинг текстового поля (JTextField)

Определим простой класс, со свойствами которого будут связаны элементы формы

class MyBean extends AbstractBean {
    private String strProperty = "";
    //
    // Конструкторы, геттеры и сеттеры здесь.
    //
}


Процесс биндинга текстовых полей довольно прост и в комментариях практически не нуждается. Связывание двух свойств различных элементов осуществляется путем создания объекта класса AutoBinding. Этот класс синхронизирует свойства объектов, руководствуясь одной из трех стратегий:

1. READ_ONCE — синхронизация осуществляется только один раз, во время связывания полей объектов.

2. READ — целевой объект синхронизируется с источником.

3. READ_WRITE — синхронизация объектов друг с другом.

Процесс создания объектов класса AutoBinding может быть упрощен посредством использования фабрики классов Bindings

// ...где-то в глубинах кода...
MyBean modelBean = new MyBean();
// ...
JTextField textField = new JTextField();
// ...
Bindings.createAutoBinding(READ_WRITE,
    modelBean, BeanProperty.create("strProperty"),
    textField, BeanProperty.create("text")).bind();


Все очевидно.
Биндинг комбобоксов (JComboBox)

Биндинг комбобоксов осуществляется в два этапа. Вначале комбобокс связывается со списком возможных значений, после чего осуществляется связывание свойства selectedItem с соответствующим свойством целевого класса.

Определим простой класс, представляющий элемент списка значений комбобокса

class ComboBoxVal {
    private int id = 0;
    private String text = "";
    //
    // Конструкторы, геттеры и сеттеры здесь.
    //   
}


Добавим в класс MyBean поле, с которым будет связываться свойство selectedItem комбобокса

class MyBean extends AbstractBean {
    private String stringProperty = "Hello!";
    private ComboBoxVal comboProperty = 
        new ComboBoxVal(0, "Item0");
// ...


Создадим список значений комбобокса

// ...где-то в глубинах кода... 
private List comboBoxData = new ArrayList(); 
// ... 
for (int i = 0; i < 10; i++) 
    comboBoxData.add(
        new ComboBoxVal(i, "Item" + i));


Поддержку биндинга сложных Swing-компонентов осуществляет фабрика классов SwingBindings. Свяжем комбобокс со список значений

JComboBox comboBox = new JComboBox();
// ...
SwingBindings.createJComboBoxBinding(
    READ, comboBoxData, comboBox).bind();


Осталось связать свойство selectedItem комбобокса с соответствующим свойством целевого класса

Bindings.createAutoBinding(READ_WRITE,
    comboBox, 
    BeanProperty.create("selectedItem"),
    modelBean, 
    BeanProperty.create("comboProperty")).bind();


создание Валидатора

В качестве примера реализуем простой валидатор для рассмотренного выше элемента textField. Наш валидатор будет осуществлять две проверки — на непустоту и на максимальное количество символов.

Все валидаторы должны наследоваться от параметризованного класса Validator, где T — тип данных с которым будет осуществляться работа.

class StringValidator extends Validator {
    private int maxStrLength = 10;
    // ...
    // Конструкторы, геттеры и сеттеры здесь.
    // ...
    public Result validate(String value) {
        if (value == null || value.length() == 0)
            return new StringEmptyResult();

        if (value.length() > maxStrLength)
            return new StringTooLong();

        return null;
    }

    public static class StringEmptyResult 
    extends Result {
        public StringEmptyResult() {
            super(0, "Str empty msg");
        }
    }

    public static class StringTooLong 
    extends Result {
        public StringTooLong() {
            super(1, "Str too long msg");
        }
    }
}


Проверкой значения занимается функция validate. В случае, если значение прошло валидацию, должен быть возвращен null. В противном случае следует возвратить объект класса Result, содержащий описание проблемы и код ошибки.

Использование валидатора

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

//...где-то в глубинах кода...
private Binding textBinding;
// ...
textBinding = Bindings.createAutoBinding(
    READ_WRITE,
    modelBean, BeanProperty.create("strProperty"),
    textField, BeanProperty.create("text"));
textBinding.setValidator(validator);
textBinding.bind();


Осталось только отреагировать на события валидации

textBinding.addBindingListener(
    new BindingListener(){
        public void syncFailed(Binding binding, 
        Binding.SyncFailure failure) {
            // Реакция на ошибку валидации.
        }
        public void synced(Binding binding) {
            // Реакция на успешную валидацию. 
        }
// ...


Конец.
Tags:
Hubs:
Total votes 4: ↑4 and ↓0+4
Comments4

Articles