eu.europa.ec.markt.tlmanager.view.binding.BindingManager.java Source code

Java tutorial

Introduction

Here is the source code for eu.europa.ec.markt.tlmanager.view.binding.BindingManager.java

Source

/*
 * DSS - Digital Signature Services
 *
 * Copyright (C) 2011 European Commission, Directorate-General Internal Market and Services (DG MARKT), B-1049 Bruxelles/Brussel
 *
 * Developed by: 2011 ARHS Developments S.A. (rue Nicolas Bov 2B, L-1253 Luxembourg) http://www.arhs-developments.com
 *
 * This file is part of the "DSS - Digital Signature Services" project.
 *
 * "DSS - Digital Signature Services" is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * DSS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * "DSS - Digital Signature Services".  If not, see <http://www.gnu.org/licenses/>.
 */

package eu.europa.ec.markt.tlmanager.view.binding;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.*;
import javax.swing.text.JTextComponent;

import org.apache.commons.lang.StringUtils;
import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.Binding;
import org.jdesktop.beansbinding.Binding.SyncFailure;
import org.jdesktop.beansbinding.Binding.ValueResult;
import org.jdesktop.beansbinding.BindingListener;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.beansbinding.Converter;
import org.jdesktop.beansbinding.PropertyStateEvent;
import org.jdesktop.beansbinding.Validator;
import org.jdesktop.swingx.JXDatePicker;

import eu.europa.ec.markt.tlmanager.util.Util;
import eu.europa.ec.markt.tlmanager.view.certificate.CertificateProperty;
import eu.europa.ec.markt.tlmanager.view.common.DateTimePicker;
import eu.europa.ec.markt.tlmanager.view.common.DefaultDocumentListener;
import eu.europa.ec.markt.tlmanager.view.multivalue.MandatoryLabelHandler;
import eu.europa.ec.markt.tlmanager.view.multivalue.MultivaluePanel;

/**
 * A class for organising the work with bindings.
 * Each binding has a name that serves as key in a <code>HashMap</code>.
 *
 * @version $Revision: 2786 $ - $Date: 2013-10-23 16:31:23 +0200 (mer., 23 oct. 2013) $
 */

public class BindingManager implements BindingListener {

    /** The Constant LOG. */
    private static final Logger LOG = Logger.getLogger(BindingManager.class.getName());

    /** The bindings. */
    private Map<String, Binding> bindings;

    /** The Constant BP_TEXT. */
    private static final BeanProperty BP_TEXT = BeanProperty.create("text"); // JTextField

    /** The Constant BP_COMBO. */
    private static final BeanProperty BP_COMBO = BeanProperty.create("selectedItem"); // JComboBox

    /** The Constant BP_MVALUE. */
    private static final BeanProperty BP_MVALUE = BeanProperty.create("multivalueModel"); // MultivaluePanel

    /** The Constant BP_DATEPICKER. */
    private static final BeanProperty BP_DATEPICKER = BeanProperty.create("date"); // JXDatePicker

    /** The Constant BP_DATETIMEPICKER. */
    private static final BeanProperty BP_DATETIMEPICKER = BeanProperty.create("dateTime"); // DateTimePicker

    /** The Constant BP_CHECKBOX. */
    private static final BeanProperty BP_CHECKBOX = BeanProperty.create("selected"); // JCheckBox

    /** The Constant BP_CERTIFICATE_PROPERTY. */
    private static final BeanProperty BP_CERTIFICATE_PROPERTY = BeanProperty.create("certificatePropertyModel"); // CertificateProperty

    private MandatoryLabelHandler labelHandler;

    private boolean bindingInProgress;

    /**
     * The default constructor for BindingManager.
     * 
     * @param labelHandler
     */
    public BindingManager(MandatoryLabelHandler labelHandler) {
        this.labelHandler = labelHandler;
        init();
    }

    /**
     * Inits the bindings.
     */
    private void init() {
        if (bindings == null) {
            bindings = new HashMap<String, Binding>();
        }
    }

    /**
     * Retrieve binding.
     * 
     * @param name the name
     * @return the binding
     */
    private Binding retrieveBinding(String name) {
        Binding binding = bindings.get(name);
        if (binding == null) {
            LOG.log(Level.SEVERE, "Binding not found for name: " + name);
        }

        return binding;
    }

    /**
     * Amends the source for a previously created binding.
     * 
     * @param source the new source object
     * @param name the name of the binding
     */
    public void amendSourceForBinding(Object source, String name) {
        bindingInProgress = true;
        if (source == null) {
            LOG.log(Level.SEVERE, ">>>Bound object may not be null: " + name);
        }
        Binding binding = retrieveBinding(name);
        if (binding != null) {
            binding.setSourceObject(source);

            LOG.fine("Bind " + source + " (" + name + ")");
            ValueResult sourceValueForTarget = binding.getSourceValueForTarget();
            if (sourceValueForTarget.failed()) {
                SyncFailure failure = sourceValueForTarget.getFailure();
                LOG.log(Level.SEVERE, ">>>>>>Binding failure");
                if (failure != null) {
                    LOG.log(Level.SEVERE, ">>>" + failure.getType() + " for " + name);
                }
                LOG.log(Level.SEVERE, ">>>>>>");
            }
        }
    }

    /**
     * Determine bean property for a component and sets it up with appropriate listeners.
     * 
     * @param component the component
     * 
     * @return the bean property
     */
    private BeanProperty setupComponent(final JComponent component) {
        if (component instanceof JTextField) {
            final JTextField tf = (JTextField) component;
            tf.getDocument().addDocumentListener(new DefaultDocumentListener() {
                @Override
                protected void changed() {
                    if (component.getParent() instanceof JComboBox) {
                        JComboBox comboBox = (JComboBox) component.getParent();
                        labelHandler.handleLabelStateFor(comboBox,
                                Util.DEFAULT_NO_SELECTION_ENTRY.equals(tf.getText()));
                    } else {
                        labelHandler.handleLabelStateFor(component, StringUtils.isEmpty(tf.getText()));
                    }
                    labelHandler.handleLabelStateFor(component, tf.getText().isEmpty());
                }
            });
            return BP_TEXT;
        } else if (component instanceof JComboBox) {
            final JComboBox box = (JComboBox) component;
            addListenerForEditableCombobox(box, new EditableComboboxListener() {
                @Override
                public void itemChanged(Object item) {
                    labelHandler.handleLabelStateFor(component, Util.DEFAULT_NO_SELECTION_ENTRY.equals(item));
                }
            });
            return BP_COMBO;
        } else if (component instanceof MultivaluePanel) {
            return BP_MVALUE;
        } else if (component instanceof JXDatePicker) {
            final JXDatePicker picker = (JXDatePicker) component;
            picker.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (picker.getDate() != null) {
                        labelHandler.handleLabelStateFor(component, false);
                    } else {
                        labelHandler.handleLabelStateFor(component, true);
                    }
                }
            });
            return BP_DATEPICKER;
        } else if (component instanceof DateTimePicker) {
            final DateTimePicker picker = (DateTimePicker) component;
            picker.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (picker.getDateTime() != null) {
                        labelHandler.handleLabelStateFor(component, false);
                    } else {
                        labelHandler.handleLabelStateFor(component, true);
                    }
                }
            });
            return BP_DATETIMEPICKER;
        } else if (component instanceof JCheckBox) {
            return BP_CHECKBOX;
        } else if (component instanceof CertificateProperty) {
            return BP_CERTIFICATE_PROPERTY;
        }

        return null;
    }

    /**
     * Shortcut for {@link #createBindingForComponent(JComponent component, String sourceBeanProperty, String name)} followed by {@link #appendConverter(Converter converter, String name)}
     *
     * @param component
     * @param sourceBeanProperty
     * @param name
     * @param converter
     */
    public void createBindingForComponent(JComponent component, String sourceBeanProperty, String name,
            Converter converter) {
        createBindingForComponent(component, sourceBeanProperty, name);
        appendConverter(converter, name);
    }

    private static interface EditableComboboxListener {
        void itemChanged(Object item);
    }

    private void addListenerForEditableCombobox(final JComboBox jComboBox,
            final EditableComboboxListener listener) {
        jComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                final Object selectedItem = jComboBox.getSelectedItem();
                listener.itemChanged(selectedItem);
            }
        });
        if (jComboBox.isEditable()) {
            ((JTextComponent) jComboBox.getEditor().getEditorComponent()).getDocument()
                    .addDocumentListener(new DefaultDocumentListener() {
                        protected void changed() {
                            final Object item = jComboBox.getEditor().getItem();
                            listener.itemChanged(item);
                        }
                    });
        }
    }

    /**
     * Creates the binding for component.
     * 
     * @param component the component
     * @param sourceBeanProperty the source bean property
     * @param name the name
     */
    public void createBindingForComponent(JComponent component, String sourceBeanProperty, String name) {
        LOG.fine("Create binding for " + component + " on " + sourceBeanProperty + " with name " + name);
        if (component instanceof JComboBox) {
            JComboBox jComboBox = (JComboBox) component;
            if (jComboBox.isEditable()) {
                component = (JComponent) jComboBox.getEditor().getEditorComponent();
            }
        }
        BeanProperty bp = setupComponent(component);
        if (bp != null) {

            Binding binding = Bindings.createAutoBinding(UpdateStrategy.READ_WRITE, null,
                    BeanProperty.create(sourceBeanProperty), // bean
                    component, bp, name); // ui
            bindings.put(name, binding);
            binding.addBindingListener(this);
        } else {
            LOG.log(Level.SEVERE,
                    ">>>Unable to determine type of given component {0} - No BeanProperty could be set!",
                    component);
        }
    }

    /**
     * Appends a converter to a previously created binding.
     * 
     * @param converter the converter
     * @param name the name of the binding
     */
    public void appendConverter(Converter converter, String name) {
        if (converter == null) {
            LOG.log(Level.SEVERE, ">>>Provided converter may not be null for name: " + name);
        } else {
            Binding binding = retrieveBinding(name);
            if (binding != null) {
                binding.setConverter(converter);
            }
        }
    }

    /**
     * Appends a validator to a previously created binding.
     * 
     * @param validator the validator
     * @param name the name of the binding
     */
    public void appendValidator(Validator validator, String name) {
        if (validator == null) {
            LOG.log(Level.SEVERE, ">>>Provided validator may not be null for name: " + name);
        } else {
            Binding binding = retrieveBinding(name);
            if (binding != null) {
                binding.setValidator(validator);
            }
        }
    }

    /**
     * Adds the binding.
     * 
     * @param binding the binding
     */
    public void addBinding(Binding binding) {
        String name = binding.toString();
        if (binding.getName() != null && !binding.getName().isEmpty()) {
            name = binding.getName();
        }
        addBinding(binding, name);
    }

    /**
     * Adds the binding.
     * 
     * @param binding the binding
     * @param name the name
     */
    private void addBinding(Binding binding, String name) {
        bindings.put(name, binding);
        LOG.log(Level.INFO, "Added a binding called {0} to list of {1} bindings",
                new Object[] { name, bindings.size() });
    }

    /**
     * Removes the binding.
     * 
     * @param name the name
     */
    private void removeBinding(String name) {
        if (bindings.remove(name) != null) {
            LOG.log(Level.INFO, "Removed a binding called {0} from the list of {1} bindings",
                    new Object[] { name, bindings.size() });
        } else {
            LOG.log(Level.INFO, "Binding {0} could not be removed from the list of {1} bindings",
                    new Object[] { name, bindings.size() });
        }
    }

    /**
     * Iterate through all stored bindings and unbinds them.
     */
    public void unbindAll() {
        for (Binding binding : bindings.values()) {
            if (binding.isBound()) {
                try {
                    binding.unbind();
                } catch (Exception ex) {
                    LOG.log(Level.SEVERE, ">>>BindingManager.unbindAll(): Exception because of " + binding.getName()
                            + ":" + ex.getMessage(), ex);
                }
            }
        }
    }

    /**
     * Iterate through all stored bindings and binds them.
     */
    public void bindAll() {
        for (Binding binding : bindings.values()) {
            try {
                binding.bind();
            } catch (Exception ex) {
                LOG.log(Level.SEVERE, ">>>BindingManager.bindAll(): Exception because of " + binding.getName()
                        + ": " + ex.getMessage(), ex);
            }
        }
        bindingInProgress = false;
    }

    /**
     * Gives information about whether any binding is not yet finalized with {@link #bindAll()}.
     * 
     * @return the bindingInProgress status
     */
    public boolean isBindingInProgress() {
        return bindingInProgress;
    }

    boolean doPrintouts = false;

    // Methods for BindingListener
    /**
     * Binding became bound.
     * 
     * @param binding the binding {@inheritDoc}
     */
    @Override
    public void bindingBecameBound(Binding binding) {
        if (doPrintouts) {
            System.out.println(binding.getName() + ": bindingBecameBound");
        }
    }

    /**
     * Binding became unbound.
     * 
     * @param binding the binding {@inheritDoc}
     */
    @Override
    public void bindingBecameUnbound(Binding binding) {
        if (doPrintouts) {
            System.out.println(binding.getName() + ": bindingBecameUnbound");
        }
    }

    /**
     * Sync failed.
     * 
     * @param binding the binding
     * @param failure the failure {@inheritDoc}
     */
    @Override
    public void syncFailed(Binding binding, SyncFailure failure) {
        labelHandler.handleLabelStateFor((Component) binding.getTargetObject(), true);
        if (doPrintouts) {
            System.out.println(binding.getName() + ": syncFailed");
        }
    }

    /**
     * Synced.
     * 
     * @param binding the binding {@inheritDoc}
     */
    @Override
    public void synced(Binding binding) {
        labelHandler.handleLabelStateFor((Component) binding.getTargetObject(), false);
        if (doPrintouts) {
            System.out.println(binding.getName() + ": synced");
        }
    }

    /**
     * Source changed.
     * 
     * @param binding the binding
     * @param event the event {@inheritDoc}
     */
    @Override
    public void sourceChanged(Binding binding, PropertyStateEvent event) {
        if (doPrintouts) {
            System.out.println(binding.getName() + ": sourceChanged");
        }
    }

    /**
     * Target changed.
     * 
     * @param binding the binding
     * @param event the event {@inheritDoc}
     */
    @Override
    public void targetChanged(Binding binding, PropertyStateEvent event) {
        if (doPrintouts) {
            System.out.println(binding.getName() + ": targetChanged");
        }
    }
}