ca.sqlpower.matchmaker.swingui.address.AddressValidationEntryPanel.java Source code

Java tutorial

Introduction

Here is the source code for ca.sqlpower.matchmaker.swingui.address.AddressValidationEntryPanel.java

Source

/*
 * Copyright (c) 2009, SQL Power Group Inc.
 *
 * This file is part of DQguru
 *
 * DQguru is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * DQguru 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */

package ca.sqlpower.matchmaker.swingui.address;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;

import org.antlr.runtime.RecognitionException;
import org.apache.log4j.Logger;

import ca.sqlpower.matchmaker.address.Address;
import ca.sqlpower.matchmaker.address.AddressDatabase;
import ca.sqlpower.matchmaker.address.AddressResult;
import ca.sqlpower.matchmaker.address.AddressValidator;
import ca.sqlpower.matchmaker.swingui.MMSUtils;
import ca.sqlpower.swingui.DataEntryPanel;
import ca.sqlpower.swingui.SPSUtils;
import ca.sqlpower.validation.Status;
import ca.sqlpower.validation.ValidateResult;

import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.sleepycat.je.DatabaseException;

/**
 * This data entry panel is for validating and editing a single {@link Address}.
 * This is different from the {@link AddressValidationPanel} as it is contained in
 * the {@link AddressValidationPanel} and the other panel shows all possible addresses
 * that needs corrections while this allows editing and is only one address.
 */
public class AddressValidationEntryPanel implements DataEntryPanel {

    private static final Logger logger = Logger.getLogger(AddressValidationEntryPanel.class);

    private final JPanel panel;
    private final AddressResult addressResult;
    private final AddressDatabase addressDatabase;

    //XXX: Add these 2 buttons to the panel and implement the functions
    //    private JButton undoButton;
    //    private JButton redoButton;

    /**
     * This is the selected AddressLabel which is in the middle of the 
     * validation screen waiting to be corrected.
     */
    private AddressLabel selectedAddressLabel;

    /**
     * This is a temporary parent pointer for this entry panel so it can call
     * the temporary save method on it's parent which is also temporary.
     */
    private final AddressValidationPanel parent;

    /**
     * This validator will be used to correct the last modified address from the user.
     */
    private AddressValidator addressValidator;

    /**
     * This builder puts together the error list below the main label. The builder
     * is a class level variable to allow editing the error list.
     */
    private DefaultFormBuilder problemsBuilder;

    /**
     * The list of suggestion labels
     */
    private JList suggestionList;

    /**
      * The result after validation step
      */
    private List<ValidateResult> validateResult;

    public AddressValidationEntryPanel(AddressValidationPanel parent, AddressResult addressResult,
            AddressDatabase addressDatabase) {
        this.parent = parent;
        this.addressResult = addressResult;
        this.addressDatabase = addressDatabase;
        panel = new JPanel();
        buildUI();
    }

    private void buildUI() {
        DefaultFormBuilder builder = new DefaultFormBuilder(
                new FormLayout("fill:pref:grow,4dlu,fill:pref", "pref,4dlu,pref,4dlu,fill:pref:grow"), panel);
        builder.setDefaultDialogBorder();
        CellConstraints cc = new CellConstraints();

        try {
            final Address address1;

            logger.debug("ADDRESS BEFORE PARSING IS : " + addressResult.getOutputAddress());
            address1 = Address.parse(addressResult.getOutputAddress().getAddress(),
                    addressResult.getOutputAddress().getMunicipality(),
                    addressResult.getOutputAddress().getProvince(),
                    addressResult.getOutputAddress().getPostalCode(), addressResult.getOutputAddress().getCountry(),
                    addressDatabase);
            logger.debug("ADDRESS AFTER PARSING IS : " + address1);
            logger.debug("The output address is not empty.");
            logger.debug("The non-empty address is: " + address1);
            this.addressValidator = new AddressValidator(addressDatabase, address1);

            JButton saveButton = new JButton("Save");
            selectedAddressLabel = new AddressLabel(addressResult.getOutputAddress(), null, true,
                    addressValidator.isAddressValid());
            selectedAddressLabel.addPropertyChangeListener(new PropertyChangeListener() {

                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equals("currentAddress")) {
                        // update the suggestionList
                        Address address = (Address) evt.getNewValue();
                        if (address.getType() == null) { //unparsed address, needs to be parsed, This could also be a failed to parse address, won't hurt to try parsing again
                            try {
                                address = Address.parse(address.getAddress(), address.getMunicipality(),
                                        address.getProvince(), address.getPostalCode(), address.getCountry(),
                                        addressDatabase);
                            } catch (RecognitionException e) {
                                MMSUtils.showExceptionDialog(panel,
                                        "There was an error while trying to parse this address", e);
                            } catch (DatabaseException e) {
                                MMSUtils.showExceptionDialog(panel,
                                        "There was a database error while trying to parse this address", e);
                            }
                        }
                        addressValidator = new AddressValidator(addressDatabase, address);
                        suggestionList.setModel(new JList(addressValidator.getSuggestions().toArray()).getModel());
                        selectedAddressLabel.setAddressValid(addressValidator.isAddressValid());
                        updateProblemDetails();
                        save();
                    }
                }
            });
            selectedAddressLabel.setFont(selectedAddressLabel.getFont()
                    .deriveFont((float) (selectedAddressLabel.getFont().getSize() + 3)));

            JButton revertButton = new JButton("Revert");
            revertButton.addActionListener(new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    try {
                        logger.debug("Revert Address: " + addressResult.toString());
                        Address address = Address.parse(addressResult.getInputAddress().getUnparsedAddressLine1(),
                                addressResult.getInputAddress().getMunicipality(),
                                addressResult.getInputAddress().getProvince(),
                                addressResult.getInputAddress().getPostalCode(),
                                addressResult.getInputAddress().getCountry(), addressDatabase);
                        addressResult.setOutputAddress(selectedAddressLabel.getCurrentAddress());
                        selectedAddressLabel.setCurrentAddress(address);
                    } catch (RecognitionException e1) {
                        e1.printStackTrace();
                    } catch (DatabaseException e1) {
                        throw new RuntimeException("A database exception occurred while parsing the address" + e1);
                    }
                }

            });

            saveButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    save();
                }
            });

            //         undoButton = new JButton("Undo");

            //         redoButton = new JButton("Redo");

            JLabel suggestLabel = new JLabel("Suggestions:");
            suggestLabel.setFont(suggestLabel.getFont().deriveFont(Font.BOLD));

            problemsBuilder = new DefaultFormBuilder(new FormLayout("fill:pref:grow"));
            updateProblemDetails();
            suggestionList = new JList(addressValidator.getSuggestions().toArray());
            logger.debug("There are " + addressValidator.getSuggestions().size() + " suggestions.");
            suggestionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            suggestionList.setCellRenderer(new AddressListCellRenderer(address1, false));
            suggestionList.addMouseListener(new MouseAdapter() {
                public void mouseReleased(MouseEvent e) {
                    logger.debug("Mouse Clicked on suggestion list " + ((JList) e.getSource()).getSelectedValue());
                    final Address selected = (Address) ((JList) e.getSource()).getSelectedValue();
                    if (selected != null) {
                        //XXX:This does not update the model currently
                        selectedAddressLabel.setCurrentAddress(selected);
                    }
                }
            });
            JScrollPane scrollList = new JScrollPane(suggestionList);
            scrollList.setPreferredSize(new Dimension(230, 1000));

            ButtonBarBuilder bbb = new ButtonBarBuilder();
            bbb.addRelatedGap();
            bbb.addGridded(revertButton);
            bbb.addRelatedGap();
            bbb.addGridded(saveButton);
            bbb.addRelatedGap();
            builder.add(bbb.getPanel(), cc.xy(1, 1));
            builder.add(suggestLabel, cc.xy(3, 1));
            builder.add(selectedAddressLabel, cc.xy(1, 3));
            builder.add(problemsBuilder.getPanel(), cc.xy(1, 5));
            builder.add(scrollList, cc.xywh(3, 3, 1, 3));

        } catch (RecognitionException e1) {
            MMSUtils.showExceptionDialog(getPanel(), "There was an error while trying to parse this address", e1);
        } catch (DatabaseException e1) {
            MMSUtils.showExceptionDialog(getPanel(),
                    "There was a database error while trying to parse this address", e1);
        }
    }

    public void updateProblemDetails() {
        validateResult = addressValidator.getResults();
        logger.debug("The size of the Problems is : " + validateResult.size());
        problemsBuilder.getPanel().removeAll();
        //XXX:This recreates the panel based on the same panel.
        problemsBuilder = new DefaultFormBuilder(new FormLayout("max(400;min)"), problemsBuilder.getPanel());
        JLabel problemsHeading = new JLabel("Problems:");
        problemsHeading.setFont(new Font(null, Font.BOLD, 13));
        problemsBuilder.append(problemsHeading);
        for (ValidateResult vr : validateResult) {
            logger.debug("The Problem details are: " + vr);
            if (vr.getStatus() == Status.FAIL) {
                problemsBuilder.append(new JLabel("<html>Fail: " + vr.getMessage() + "</html>",
                        SPSUtils.createIcon("fail", "Fail"), JLabel.LEFT));
            } else if (vr.getStatus() == Status.WARN) {
                problemsBuilder.append(new JLabel("<html>Warning: " + vr.getMessage() + "</html>",
                        SPSUtils.createIcon("warn", "Warn"), JLabel.LEFT));
            }
        }
        problemsBuilder.getPanel().revalidate();
        problemsBuilder.getPanel().repaint();
    }

    public boolean applyChanges() {
        // TODO Auto-generated method stub
        logger.debug("Stub call: AddressValidationEntryPanel.applyChanges()");
        return false;
    }

    public void discardChanges() {
        // TODO Auto-generated method stub
        logger.debug("Stub call: AddressValidationEntryPanel.discardChanges()");

    }

    public JComponent getPanel() {
        return panel;
    }

    public boolean hasUnsavedChanges() {
        // TODO Auto-generated method stub
        logger.debug("Stub call: AddressValidationEntryPanel.hasUnsavedChanges()");
        return false;
    }

    private void save() {
        addressResult.setOutputAddress(selectedAddressLabel.getCurrentAddress());
        addressResult.setValid(addressValidator.isAddressValid());
        logger.debug("SAVING: " + addressResult);
        parent.saveAddressResult(addressResult, validateResult.size() == 0);
    }

}