org.jdal.ui.bind.AbstractBinder.java Source code

Java tutorial

Introduction

Here is the source code for org.jdal.ui.bind.AbstractBinder.java

Source

/*
 * Copyright 2002-2010 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jdal.ui.bind;

import java.beans.PropertyDescriptor;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdal.beans.PropertyUtils;
import org.jdal.beans.SpringConverter;
import org.jdal.ui.DefaultModelHolder;
import org.jdal.ui.ModelHolder;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyAccessException;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.core.convert.Property;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;

/**
 * Base class for Binders. Implement doBind() to do the binding.
 * Dereference ModelHolders when setting its as binded model.
 * 
 * @author Jose Luis Martin
 * @since 1.1
 */
public abstract class AbstractBinder extends SpringConverter implements PropertyBinder {

    private static final Log log = LogFactory.getLog(AbstractBinder.class);

    /** binded property name */
    protected String propertyName;
    /** last value, used to revert o detect cicles */
    protected Object oldValue;
    /** binded model */
    private ModelHolder<Object> modelHolder;
    /** component object */
    protected Object component;
    /** if true, binding is readOnly, ie from model to control */
    protected boolean readOnly = false;
    private ControlBindingErrorProcessor errorProcessor = new ControlBindingErrorProcessor();
    private BindingResult bindingResult;

    public AbstractBinder() {
        registerCustomEditor(Date.class, new CustomDateEditor(SimpleDateFormat.getDateTimeInstance(), true));
    }

    /**
     * {@inheritDoc}
     */
    public final void bind(Object component, String propertyName, Object model) {
        bind(component, propertyName, model, false);
    }

    /**
     * {@inheritDoc}
     */
    public final void bind(Object component, String propertyName, Object model, boolean readOnly) {
        this.propertyName = propertyName;
        setModel(model);
        this.component = component;
        this.readOnly = readOnly;
        doBind();
    }

    /**
     * Hook method to do bind via Component Listeners
     * By default, do nothing
     */
    protected void doBind() {

    }

    public final void refresh() {
        doRefresh();
    }

    public final void update() {
        if (!readOnly && modelHolder != null) {
            bindingResult = createBindingResult();
            doUpdate();
        }
    }

    /**
     * Create a new Binding result, override to set nested paths on complex binders
     * @return a new instance of BindingResult for this model
     */
    protected BindingResult createBindingResult() {
        Object model = getModel();
        return new BeanPropertyBindingResult(model, model.getClass().getSimpleName());
    }

    abstract protected void doRefresh();

    abstract protected void doUpdate();

    /**
     * Set value on binded object using the property name.
     * @param value the value to set
     */
    protected void setValue(Object value) {
        BeanWrapper wrapper = getBeanWrapper();
        Object convertedValue = convertIfNecessary(value, wrapper.getPropertyType(this.propertyName));
        try {
            wrapper.setPropertyValue(propertyName, convertedValue);
            oldValue = value;
        } catch (PropertyAccessException pae) {
            log.error(pae);
            errorProcessor.processPropertyAccessException(component, pae, bindingResult);
        }
    }

    /**
     * Get value from model
     * @return model value
     */
    protected Object getValue() {
        BeanWrapper wrapper = getBeanWrapper();
        Object value = null;
        try {
            value = wrapper.getPropertyValue(propertyName);
        } catch (BeansException e) {
            log.error(e);
        }

        return value;
    }

    private BeanWrapper getBeanWrapper() {
        BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(getModel());
        wrapper.setConversionService(getConversionService());
        wrapper.registerCustomEditor(Date.class,
                new CustomDateEditor(SimpleDateFormat.getDateTimeInstance(), true));

        return wrapper;
    }

    /**
     * @return Property for property binder
     */
    protected Property getProperty() {
        PropertyDescriptor pd = getPropertyDescriptor();
        return new Property(getModel().getClass(), pd.getReadMethod(), pd.getWriteMethod());
    }

    // Getters and Setters

    public String getPropertyName() {
        return propertyName;
    }

    public void setPropertyName(String propertyName) {
        this.propertyName = propertyName;
    }

    protected Object getOldValue() {
        return oldValue;
    }

    protected void setOldValue(Object oldValue) {
        this.oldValue = oldValue;
    }

    public Object getModel() {
        return modelHolder != null ? modelHolder.getModel() : null;
    }

    @SuppressWarnings("unchecked")
    public void setModel(Object model) {
        if (model instanceof ModelHolder) {
            this.modelHolder = (ModelHolder<Object>) model;
        } else {
            model = new DefaultModelHolder<Object>(model);
        }
    }

    /**
     * @return the component
     */
    public Object getComponent() {
        return component;
    }

    /**
     * @param component the component to set
     */
    public void setComponent(Object component) {
        this.component = component;
    }

    public BindingResult getBindingResult() {
        return bindingResult;
    }

    public Class<?> getPropertyType() {
        return getPropertyDescriptor().getPropertyType();
    }

    public PropertyDescriptor getPropertyDescriptor() {
        return PropertyUtils.getPropertyDescriptor(getModel().getClass(), propertyName);
    }
}