com.sfs.whichdoctor.search.sql.DebitSqlHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.sfs.whichdoctor.search.sql.DebitSqlHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2009 David Harrison.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * Contributors:
 *     David Harrison - initial API and implementation
 ******************************************************************************/
package com.sfs.whichdoctor.search.sql;

import com.sfs.DataFilter;
import com.sfs.Formatter;
import com.sfs.beans.BuilderBean;
import com.sfs.beans.UserBean;
import com.sfs.whichdoctor.beans.DebitBean;
import com.sfs.whichdoctor.beans.SearchBean;
import com.sfs.whichdoctor.beans.TagBean;
import com.sfs.whichdoctor.dao.DebitDAO;
import com.sfs.whichdoctor.search.TagSearchDAO;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

/**
 * The Class DebitSqlHandler.
 *
 * @author David Harrison
 */
public class DebitSqlHandler extends SqlHandlerBase {

    /** The data logger. */
    private static Logger dataLogger = Logger.getLogger(DebitSqlHandler.class);

    /** The Constant LIMIT. */
    private static final int LIMIT = 50;

    /** The tag search dao. */
    @Resource
    private TagSearchDAO tagSearchDAO;

    /** The debit dao. */
    @Resource
    private DebitDAO debitDAO;

    /**
     * Instantiates a new debit sql handler.
     */
    public DebitSqlHandler() {
        super();
        this.setType("debit");
        this.setIdentifierColumn("invoice.GUID");
        this.setDefaultOrder("InvoiceNo");
    }

    /**
     * Initiate a SearchBean for the search type.
     *
     * @param user the user
     *
     * @return configured SearchBean
     */
    public final SearchBean initiate(final UserBean user) {

        SearchBean search = new SearchBean();

        DebitBean searchCriteria = new DebitBean();
        DebitBean searchConstraints = new DebitBean();

        searchCriteria.setCancelled(false);
        searchConstraints.setCancelled(true);
        searchCriteria.setGSTRate(-1);

        /**
         * If user is not an Administrator or in the Finances group then they
         * shouldn't be able to view secured invoices....
         */
        if (user != null && !user.isFinancialUser()) {
            searchCriteria.setSecurity("Standard");
        }

        search.setRequestedPage(1);
        search.setLimit(LIMIT);
        search.setOrderColumn("invoice.InvoiceNo");
        search.setOrderColumn2("");
        search.setOrderColumn3("");
        search.setOrderAscending(true);
        search.setType("debit");
        search.setSearchCriteria(searchCriteria);
        search.setSearchConstraints(searchConstraints);

        return search;
    }

    /**
     * Gets the group by.
     *
     * @return the group by
     */
    public final String getGroupBy() {
        return "";
    }

    /**
     * Gets the count sql.
     *
     * @return the count sql
     */
    public final String getCountSql() {
        return "SELECT count(DISTINCT invoice.GUID) " + this.getSQL().getValue("debit/search");
    }

    /**
     * Gets the select sql.
     *
     * @return the select sql
     */
    public final String getSelectSql() {
        return "SELECT DISTINCT invoice.GUID " + getSQL().getValue("debit/search");
    }

    /**
     * Load the identified objects and return results as a Collection of
     * Objects.
     *
     * @param uniqueIds the unique ids
     * @param loadDetails the load details
     *
     * @return a Collection of Objects
     */
    public final Collection<Object> load(final Collection<Integer> uniqueIds, final BuilderBean loadDetails) {

        Collection<Object> results = new ArrayList<Object>();

        if (uniqueIds != null) {
            for (Integer uniqueId : uniqueIds) {
                try {
                    DebitBean debit = this.debitDAO.loadGUID(uniqueId, loadDetails);
                    results.add(debit);
                } catch (Exception e) {
                    dataLogger.error("Error loading debit (" + uniqueId + ") for search: " + e.getMessage());
                }
            }
        }
        return results;
    }

    /**
     * Construct the SQL string, description and parameters.
     *
     * @param objCriteria Object containing search criteria values
     * @param objConstraints Object containing search constraint values
     *
     * @return Map containing a String[] { sql, description } =>
     *         Collection< Object > parameters
     *
     * @throws IllegalArgumentException the illegal argument exception
     */
    public final Map<String[], Collection<Object>> construct(final Object objCriteria, final Object objConstraints)
            throws IllegalArgumentException {

        DebitBean searchCriteria = null;
        DebitBean searchConstraints = null;

        if (objCriteria instanceof DebitBean) {
            searchCriteria = (DebitBean) objCriteria;
        }
        if (objConstraints instanceof DebitBean) {
            searchConstraints = (DebitBean) objConstraints;
        }

        if (searchCriteria == null) {
            throw new IllegalArgumentException("The search criteria must be " + "a valid DebitBean");
        }
        if (searchConstraints == null) {
            throw new IllegalArgumentException("The search constraints must be " + "a valid DebitBean");
        }

        StringBuffer sqlWHERE = new StringBuffer();
        StringBuffer description = new StringBuffer();
        Collection<Object> parameters = new ArrayList<Object>();

        if (searchCriteria.getTags() != null) {
            try {
                for (TagBean tag : searchCriteria.getTags()) {
                    Map<String[], Collection<Object>> results = this.tagSearchDAO.construct(tag, new TagBean());

                    for (String[] index : results.keySet()) {
                        String tagWHERE = index[0];
                        String tagDescription = index[1];
                        Collection<Object> tagParameters = results.get(index);

                        if (tagWHERE.compareTo("") != 0) {
                            /*
                             * A WHERE condition is defined, add to the SQL
                             * WHERE clause
                             */
                            sqlWHERE.append(
                                    " " + this.getSQL().getValue("debit/searchTags") + " WHERE " + tagWHERE + ")");
                            /* Add to the description and process the arrays */
                            description.append(tagDescription);
                            if (tagParameters != null) {
                                parameters.addAll(tagParameters);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                dataLogger.error("Error setting tag search options: " + e.getMessage());
            }
        }

        if (searchCriteria.getBasicSearch() != null) {
            if (searchCriteria.getBasicSearch().compareTo("") != 0) {
                String searchString = searchCriteria.getBasicSearch().trim();

                int basicSearch = 0;
                try {
                    basicSearch = Integer.parseInt(searchCriteria.getBasicSearch());
                } catch (NumberFormatException nfe) {
                    dataLogger.debug("Error parsing BasicSearch parameter: " + nfe.getMessage());
                }
                if (basicSearch == 0) {
                    // If the search string has : in the first ten characters
                    // the financial
                    // abbreviation is probably included - strip it out for
                    // search purposes
                    if (searchString.indexOf(": ") > 3 && searchString.indexOf(": ") < 10) {
                        searchString = searchString.substring(3, searchString.length());
                    }

                    String field = "%" + searchString + "%";
                    sqlWHERE.append(" AND (concat(invoice.InvoiceNo, ': ', " + "invoice.Description) LIKE ?)");
                    description.append(" and a debit description like '" + searchCriteria.getBasicSearch() + "'");
                    parameters.add(field);
                } else {
                    String field = searchCriteria.getBasicSearch();
                    sqlWHERE.append(" AND (invoice.InvoiceNo LIKE ?)");
                    description.append(" and a debit number of '" + searchCriteria.getBasicSearch() + "'");
                    parameters.add("%" + field);
                }
            }
        }

        if (searchCriteria.getNumber() != null) {
            boolean blSearchConstraints = false;
            if (searchCriteria.getNumber().compareTo("") != 0) {
                if (searchConstraints.getNumber() != null) {
                    if (searchConstraints.getNumber().compareTo("") != 0) {
                        blSearchConstraints = true;
                    }
                }

                if (blSearchConstraints) {
                    if (searchConstraints.getNumber().compareTo("-") == 0) {
                        // Less than DebitNo specified
                        sqlWHERE.append(" AND invoice.InvoiceNo <= ?");
                        description.append(" and a debit number less than '" + searchCriteria.getNumber() + "'");
                        parameters.add(searchCriteria.getNumber());
                    } else if (searchConstraints.getNumber().compareTo("+") == 0) {
                        // Greater then DebitNo specified
                        sqlWHERE.append(" AND invoice.InvoiceNo >= ?");
                        description.append(" and a debit number greater than '" + searchCriteria.getNumber() + "'");
                        parameters.add(searchCriteria.getNumber());
                    } else {
                        // Range between a and b - find whether greater than or
                        // less than
                        int debitA = 0;
                        int debitB = 0;
                        try {
                            debitA = Integer.parseInt(searchCriteria.getNumber());
                        } catch (NumberFormatException nfe) {
                            dataLogger.debug("Error parsing DebitNo parameter: " + nfe.getMessage());
                        }
                        try {
                            debitB = Integer.parseInt(searchConstraints.getNumber());
                        } catch (NumberFormatException nfe) {
                            dataLogger.debug("Error parsing DebitNo parameter: " + nfe.getMessage());
                        }
                        if (debitA == debitB) {
                            // criteria A and B are the same
                            sqlWHERE.append(" AND invoice.InvoiceNo LIKE ?");
                            description.append(" and a debit number of '" + searchCriteria.getNumber() + "'");
                            parameters.add("%" + searchCriteria.getNumber());
                        }
                        if (debitA < debitB) {
                            // criteria A is less than B
                            sqlWHERE.append(" AND invoice.InvoiceNo BETWEEN ? AND ?");
                            description.append(" and a debit number between '" + searchCriteria.getNumber()
                                    + "' and '" + searchConstraints.getNumber() + "'");
                            parameters.add(searchCriteria.getNumber());
                            parameters.add(searchConstraints.getNumber());
                        }
                        if (debitA > debitB) {
                            // Criteria A is greater than B
                            sqlWHERE.append(" AND invoice.InvoiceNo BETWEEN ? AND ?");
                            description.append(" and a debit number between '" + searchConstraints.getNumber()
                                    + "' and '" + searchCriteria.getNumber() + "'");
                            parameters.add(searchConstraints.getNumber());
                            parameters.add(searchCriteria.getNumber());
                        }
                    }
                } else {
                    sqlWHERE.append(" AND invoice.InvoiceNo LIKE ?");
                    description.append(" and a debit number of '" + searchCriteria.getNumber() + "'");
                    parameters.add("%" + searchCriteria.getNumber());
                }
            }
        }

        if (searchCriteria.getGUIDList() != null) {
            final StringBuffer guidWHERE = new StringBuffer();

            for (String guid : searchCriteria.getGUIDList()) {
                if (StringUtils.isNotBlank(guid)) {
                    guidWHERE.append(" OR invoice.GUID = ?");
                    parameters.add(guid);
                }
            }
            if (guidWHERE.length() > 0) {
                // Append the guidWHERE buffer to the sqlWHERE buffer
                sqlWHERE.append(" AND (");
                // Append the guidWHERE but strip the first OR statement
                sqlWHERE.append(guidWHERE.toString().substring(4));
                sqlWHERE.append(")");
                description.append(" and has a GUID in the supplied list");
            }
        }

        if (searchCriteria.getIdentifierList() != null) {
            final StringBuffer identifierWHERE = new StringBuffer();

            for (String identifier : searchCriteria.getIdentifierList()) {
                if (StringUtils.isNotBlank(identifier)) {
                    identifierWHERE.append(" OR invoice.InvoiceNo LIKE ?");
                    parameters.add("%" + identifier);
                }
            }
            if (identifierWHERE.length() > 0) {
                // Append the identifierWHERE buffer to the sqlWHERE buffer
                sqlWHERE.append(" AND (");
                // Append the identifierWHERE but strip the first OR statement
                sqlWHERE.append(identifierWHERE.toString().substring(4));
                sqlWHERE.append(")");
                description.append(" and has a debit number in the supplied list");
            }
        }

        if (searchConstraints.getOutstandingValue() != 0) {
            final double outstandingA = searchCriteria.getOutstandingValue();
            final double outstandingB = searchConstraints.getOutstandingValue();

            if (outstandingA < outstandingB) {
                // criteria A is less than B
                sqlWHERE.append(" AND invoice.OutstandingValue BETWEEN ? AND ?");
                description.append(" and an outstanding value between '" + Formatter.toCurrency(outstandingA, "$")
                        + "' and '" + Formatter.toCurrency(outstandingB, "$") + "'");
                parameters.add(outstandingA);
                parameters.add(outstandingB);
            }
            if (outstandingA > outstandingB) {
                // Criteria A is greater than B
                sqlWHERE.append(" AND invoice.OutstandingValue BETWEEN ? AND ?");
                description.append(" and an outstanding value between '" + Formatter.toCurrency(outstandingB, "$")
                        + "' and '" + Formatter.toCurrency(outstandingA, "$") + "'");
                parameters.add(outstandingB);
                parameters.add(outstandingA);
            }
            if (outstandingA == outstandingB) {
                sqlWHERE.append(" AND invoice.OutstandingValue = ?");
                description.append(
                        " and an outstanding value equal to '" + Formatter.toCurrency(outstandingA, "$") + "'");
                parameters.add(outstandingA);
            }
        } else {
            if (searchCriteria.getOutstandingValue() != 0) {
                sqlWHERE.append(" AND invoice.OutstandingValue = ?");
                description.append(" and an outstanding value equal to '"
                        + Formatter.toCurrency(searchCriteria.getOutstandingValue(), "$") + "'");
                parameters.add(searchCriteria.getOutstandingValue());
            }
        }

        if (searchCriteria.getPersonId() > 0) {
            sqlWHERE.append(" AND invoice.PersonId = ?");
            description.append(" and a person GUID equal to '" + searchCriteria.getPersonId() + "'");
            parameters.add(searchCriteria.getPersonId());
        }
        if (searchCriteria.getOrganisationId() > 0) {
            sqlWHERE.append(" AND invoice.OrganisationId = ?");
            description.append(" and an organisation GUID equal to '" + searchCriteria.getOrganisationId() + "'");
            parameters.add(searchCriteria.getOrganisationId());
        }

        if (searchCriteria.getDescription() != null) {
            if (searchCriteria.getDescription().compareTo("") != 0) {
                if (searchCriteria.getDescription().indexOf("\"") > -1) {
                    // Description contains "" so treat as a specific search
                    sqlWHERE.append(" AND invoice.Description LIKE ?");
                    description.append(" and a debit description like '" + searchCriteria.getDescription() + "'");
                    parameters.add(StringUtils.replace(searchCriteria.getDescription(), "\"", ""));
                } else {
                    sqlWHERE.append(" AND invoice.Description LIKE ?");
                    description.append(" and a debit description like '" + searchCriteria.getDescription() + "'");
                    parameters.add("%" + searchCriteria.getDescription() + "%");
                }
            }
        }

        if (searchCriteria.getCancelled()) {
            if (searchConstraints.getCancelled()) {
                // Only cancelled invoices
                sqlWHERE.append(" AND invoice.Cancelled = true");
                description.append(" and the debit is cancelled");
            }
        } else {
            if (!searchConstraints.getCancelled()) {
                // Only non-cancelled debits
                sqlWHERE.append(" AND invoice.Cancelled = false");
                description.append(" and the debit is not cancelled");
            }
        }

        if (searchCriteria.getGSTRate() >= 0) {
            sqlWHERE.append(" AND invoice.GSTRate = ?");
            description.append(" and GST is " + Formatter.toPercent(searchCriteria.getGSTRate() / 100, 1, "%")
                    + " in the debit");
            parameters.add(searchCriteria.getGSTRate());
        }

        if (StringUtils.isNotBlank(searchCriteria.getSecurity())) {
            sqlWHERE.append(" AND financialtype.Security = ?");
            description.append(" and has a security setting of '" + searchCriteria.getSecurity() + "'");
            parameters.add(searchCriteria.getSecurity());
        }

        // Other searches: cancelled, date issued
        if (searchCriteria.getIssued() != null) {
            if (searchConstraints.getIssued() != null) {
                int larger = searchCriteria.getIssued().compareTo(searchConstraints.getIssued());
                if (larger > 0) {
                    // SearchCriteria date after SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getIssued());
                    String fieldB = this.getDf().format(searchConstraints.getIssued());
                    sqlWHERE.append(" AND invoice.Issued BETWEEN ? AND ?");
                    description.append(" and issued between '" + fieldB + "' and '" + fieldA + "'");
                    parameters.add(fieldB);
                    parameters.add(fieldA);
                }
                if (larger < 0) {
                    // SearchCriteria date before SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getIssued());
                    String fieldB = this.getDf().format(searchConstraints.getIssued());
                    sqlWHERE.append(" AND invoice.Issued BETWEEN ? AND ?");
                    description.append(" and issued between '" + fieldA + "' and '" + fieldB + "'");
                    parameters.add(fieldA);
                    parameters.add(fieldB);

                }
                if (larger == 0) {
                    // SearchCritier and SearchConstraint are equal
                    String field = this.getDf().format(searchCriteria.getIssued());
                    sqlWHERE.append(" AND invoice.Issued = ?");
                    description.append(" and issued on '" + field + "'");
                    parameters.add(field);
                }
            } else {
                String field = this.getDf().format(searchCriteria.getIssued());
                sqlWHERE.append(" AND invoice.Issued = ?");
                description.append(" and issued on '" + field + "'");
                parameters.add(field);
            }
        }

        if (searchCriteria.getCreatedDate() != null) {
            if (searchConstraints.getCreatedDate() != null) {
                int larger = searchCriteria.getCreatedDate().compareTo(searchConstraints.getCreatedDate());
                if (larger > 0) {
                    // SearchCriteria date after SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getCreatedDate());
                    String fieldB = this.getDf().format(searchConstraints.getCreatedDate());
                    sqlWHERE.append(" AND guid.CreatedDate BETWEEN ? AND ?");
                    description.append(" and created between '" + fieldB + "' and '" + fieldA + "'");
                    parameters.add(fieldB);
                    parameters.add(fieldA);
                }
                if (larger < 0) {
                    // SearchCriteria date before SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getCreatedDate());
                    String fieldB = this.getDf().format(searchConstraints.getCreatedDate());
                    sqlWHERE.append(" AND guid.CreatedDate BETWEEN ? AND ?");
                    description.append(" and created between '" + fieldA + "' and '" + fieldB + "'");
                    parameters.add(fieldA);
                    parameters.add(fieldB);

                }
                if (larger == 0) {
                    // SearchCritier and SearchConstraint are equal
                    String field = this.getDf().format(searchCriteria.getCreatedDate());
                    sqlWHERE.append(" AND guid.CreatedDate = ?");
                    description.append(" and created on '" + field + "'");
                    parameters.add(field);
                }
            } else {
                String field = this.getDf().format(searchCriteria.getCreatedDate());
                sqlWHERE.append(" AND guid.CreatedDate = ?");
                description.append(" and created between '" + field + "'");
                parameters.add(field);
            }
        }

        if (searchCriteria.getModifiedDate() != null) {
            if (searchConstraints.getModifiedDate() != null) {
                int larger = searchCriteria.getModifiedDate().compareTo(searchConstraints.getModifiedDate());
                if (larger > 0) {
                    // SearchCriteria date after SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getModifiedDate());
                    String fieldB = this.getDf().format(searchConstraints.getModifiedDate());
                    sqlWHERE.append(" AND guid.ModifiedDate BETWEEN ? AND ?");
                    description.append(" and modified between '" + fieldB + "' and '" + fieldA + "'");
                    parameters.add(fieldB);
                    parameters.add(fieldA);
                }
                if (larger < 0) {
                    // SearchCriteria date before SearchConstraint date
                    String fieldA = this.getDf().format(searchCriteria.getModifiedDate());
                    String fieldB = this.getDf().format(searchConstraints.getModifiedDate());
                    sqlWHERE.append(" AND guid.ModifiedDate BETWEEN ? AND ?");
                    description.append(" and modified between '" + fieldA + "' and '" + fieldB + "'");
                    parameters.add(fieldA);
                    parameters.add(fieldB);

                }
                if (larger == 0) {
                    // SearchCritier and SearchConstraint are equal
                    String field = this.getDf().format(searchCriteria.getModifiedDate());
                    sqlWHERE.append(" AND guid.ModifiedDate = ?");
                    description.append(" and modified on '" + field + "'");
                    parameters.add(field);
                }
            } else {
                String field = this.getDf().format(searchCriteria.getModifiedDate());
                sqlWHERE.append(" AND guid.ModifiedDate = ?");
                description.append(" and modified on '" + field + "'");
                parameters.add(field);
            }
        }

        if (searchCriteria.getTypeName() != null) {
            if (searchCriteria.getTypeName().compareTo("") != 0) {
                sqlWHERE.append(" AND financialtype.Name LIKE ?");
                description.append(" and a debit type like '" + searchCriteria.getTypeName() + "'");
                parameters.add(searchCriteria.getTypeName());
            }
        }

        if (searchCriteria.getClassName() != null) {
            if (searchCriteria.getClassName().compareTo("") != 0) {
                sqlWHERE.append(" AND financialtype.Class LIKE ?");
                description.append(" and a debit class like '" + searchCriteria.getClassName() + "'");
                parameters.add(searchCriteria.getClassName());
            }
        }

        if (searchCriteria.getIncludeGUIDList() != null) {
            final StringBuffer guidWHERE = new StringBuffer();

            for (String guid : searchCriteria.getIncludeGUIDList()) {
                if (StringUtils.isNotBlank(guid)) {
                    guidWHERE.append(" OR invoice.GUID = ?");
                    parameters.add(guid);
                }
            }
            if (guidWHERE.length() > 0) {
                // Append the guidWHERE buffer to the sqlWHERE buffer
                sqlWHERE.append(" OR (");
                // Append the guidWHERE but strip the first OR statement
                sqlWHERE.append(guidWHERE.toString().substring(4));
                sqlWHERE.append(")");
                description.append(" and has a GUID in the supplied list");
            }
        }

        String[] index = new String[] { sqlWHERE.toString(), DataFilter.getHtml(description.toString()) };

        Map<String[], Collection<Object>> results = new HashMap<String[], Collection<Object>>();

        results.put(index, parameters);

        return results;
    }
}