com.salas.bb.views.querybuilder.QueryBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.salas.bb.views.querybuilder.QueryBuilder.java

Source

// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program 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 2 of the License, or (at your option) any later version.
//
// This program 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, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: QueryBuilder.java,v 1.11 2006/06/01 12:49:59 spyromus Exp $
//

package com.salas.bb.views.querybuilder;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.uif.util.ResourceUtils;
import com.salas.bb.domain.query.IComparisonOperation;
import com.salas.bb.domain.query.ICriteria;
import com.salas.bb.domain.query.IProperty;
import com.salas.bb.domain.query.IQuery;
import com.salas.bb.domain.query.articles.ArticleTextProperty;
import com.salas.bb.utils.uif.BBFormBuilder;
import com.salas.bb.utils.uif.UifUtilities;
import com.salas.bb.utils.i18n.Strings;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;

/**
 * Query builder component. It takes query as input and edits its criterias.
 */
public class QueryBuilder extends JPanel {
    private static final String QUERY_TYPE_ALL = Strings.message("querybuilder.type.all");
    private static final String QUERY_TYPE_ANY = Strings.message("querybuilder.type.any");

    public static final String PROP_CRITERIA_COUNT = "criteriaCount";

    /** Width (in dlu) of Add/Delete control buttons. */
    private static final int CONTROL_BUTTON_WIDTH = 20;

    private IQuery query;

    private JPanel criteriaPanel;
    private JComboBox cbConstraint;
    private JButton btnAdd;

    /**
     * Creates builder which
     */
    public QueryBuilder() {
        initGUI();
        setQuery(null);
    }

    /**
     * Loads data from query to the criteria builders. If query has no criteria yet,
     * one will be added.
     *
     * @param aQuery query to put.
     *
     * @throws NullPointerException if query is not specified.
     */
    public void setQuery(IQuery aQuery) {
        query = aQuery;

        setEnabled(query != null);
        if (query != null) {
            loadCriteriasFromQuery();

            cbConstraint.setSelectedItem(query.isAndQuery() ? QUERY_TYPE_ALL : QUERY_TYPE_ANY);
        }
    }

    private void loadCriteriasFromQuery() {
        int count = query.getCriteriaCount();
        if (count > 0) {
            for (int i = 0; i < count; i++) {
                ICriteria criteria = query.getCriteriaAt(i);
                appendCriteriaBuilderToPanel(criteria);
            }
        } else
            addEmptyCriteria();
    }

    /**
     * Adds new criteria and corresponding row to the table.
     */
    void addEmptyCriteria() {
        // We want Article Text to be the first because it is the most obvious and helps the user understand the dialog box.
        IProperty firstProperty = ArticleTextProperty.INSTANCE;
        IComparisonOperation firstOperation = (IComparisonOperation) firstProperty.getComparsonOperations()
                .iterator().next();
        String defaultValue = firstProperty.getDefaultValue();

        ICriteria criteria = query.addCriteria();
        criteria.setProperty(firstProperty);
        criteria.setComparisonOperation(firstOperation);
        criteria.setValue(defaultValue);

        appendCriteriaBuilderToPanel(criteria);
    }

    /**
     * Removes the criteria from the query and corresponding builder from panel.
     *
     * @param index criteria index.
     * @throws IndexOutOfBoundsException if criteria index is less than 0 or greater than
     */
    void removeCriteria(int index) {
        if (query.getCriteriaCount() > 1) {
            query.removeCriteria(index);
            removeCriteriaBuilderFromPanel(index);
        }
    }

    // ---------------------------------------------------------------------------------------------
    // GUI part
    // ---------------------------------------------------------------------------------------------

    private void initGUI() {
        initComponents();

        String columnsLayout = "max(25dlu;p), 2dlu, max(30dlu;p), 4dlu, 0dlu:grow, 4dlu, " + CONTROL_BUTTON_WIDTH
                + "dlu";

        BBFormBuilder builder = new BBFormBuilder(columnsLayout, this);

        UifUtilities.smallerFont(builder.append(Strings.message("querybuilder.match"), 1));
        builder.append(cbConstraint);
        UifUtilities.smallerFont(builder.append(Strings.message("querybuilder.of.the.following.conditions"), 1));
        builder.append(btnAdd);
        builder.appendRelatedComponentsGapRow();
        builder.appendRow("pref");
        builder.nextLine(2);
        builder.append(criteriaPanel, 7, CellConstraints.FILL, CellConstraints.FILL);
    }

    private void initComponents() {
        criteriaPanel = new JPanel();
        BoxLayout layout = new BoxLayout(criteriaPanel, BoxLayout.Y_AXIS);
        criteriaPanel.setLayout(layout);

        cbConstraint = new JComboBox();
        cbConstraint.addItem(QUERY_TYPE_ALL);
        cbConstraint.addItem(QUERY_TYPE_ANY);
        cbConstraint.addItemListener(new QueryTypeSelectionListener());

        btnAdd = new JButton(new AddEmptyCriteriaAction());
        btnAdd.setText(null);
        btnAdd.setIcon(ResourceUtils.getIcon("add.icon"));
        sizeFunctionButton(btnAdd);
    }

    private void sizeFunctionButton(JButton aButton) {
        aButton.setPreferredSize(new Dimension(aButton.getSize().width, 20));
    }

    private void appendCriteriaBuilderToPanel(ICriteria aCriteria) {
        Collection properties = query.getAvailableProperties();
        CriteriaBuilder builder = new CriteriaBuilder(properties, aCriteria);

        criteriaPanel.add(createRowComponentForBuilder(builder));

        int count = query.getCriteriaCount();
        firePropertyChange(PROP_CRITERIA_COUNT, count - 1, count);
    }

    private JPanel createRowComponentForBuilder(CriteriaBuilder aBuilder) {
        JPanel criteriaRow = new JPanel();

        JButton btnDelete = new JButton(new DeleteCriteriaButtonListener(criteriaRow));
        btnDelete.setText(null);
        btnDelete.setIcon(ResourceUtils.getIcon("delete.icon"));
        sizeFunctionButton(btnDelete);

        String columnsDefinition = "pref:grow, 2dlu, " + CONTROL_BUTTON_WIDTH + "dlu";
        BBFormBuilder formBuilder = new BBFormBuilder(columnsDefinition, criteriaRow);
        formBuilder.append(aBuilder);
        formBuilder.append(btnDelete);

        return criteriaRow;
    }

    private void removeCriteriaBuilderFromPanel(int aIndex) {
        criteriaPanel.remove(aIndex);

        int count = query.getCriteriaCount();
        firePropertyChange(PROP_CRITERIA_COUNT, count + 1, count);
    }

    /**
     * Listens for button presses and adds new empty criteria record.
     */
    private class AddEmptyCriteriaAction extends AbstractAction {
        /** Creates listener. */
        public AddEmptyCriteriaAction() {
            super("+");
        }

        /** Invoked when user presses Add button. */
        public void actionPerformed(ActionEvent e) {
            addEmptyCriteria();
        }
    }

    /**
     * Listens to changes in query type and puts them into query object.
     */
    private class QueryTypeSelectionListener implements ItemListener {
        /** Invoked when user selects different query type. */
        public void itemStateChanged(ItemEvent e) {
            query.setAndQuery(cbConstraint.getSelectedItem().equals(QUERY_TYPE_ALL));
        }
    }

    /**
     * Listens for Delete button and issues command to remove corresponding row.
     */
    private class DeleteCriteriaButtonListener extends AbstractAction {
        private final Component criteriaRow;

        /**
         * Creates listener for a given row.
         *
         * @param aCriteriaRow row.
         */
        public DeleteCriteriaButtonListener(Component aCriteriaRow) {
            super("-");
            criteriaRow = aCriteriaRow;
        }

        /** Invoken when user presses Delete button. */
        public void actionPerformed(ActionEvent e) {
            int indexOfCriteria = findIndexOfCriteria(criteriaRow);
            removeCriteria(indexOfCriteria);
        }

        private int findIndexOfCriteria(Component aCriteriaRow) {
            Component[] rows = criteriaPanel.getComponents();
            int index = -1;

            for (int i = 0; index == -1 && i < rows.length; i++) {
                Component row = rows[i];
                if (row == aCriteriaRow)
                    index = i;
            }

            return index;
        }
    }
}