/********************************************************************
 * Copyright © 2005 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.service.pagination;

// Java Classes
import java.io.Serializable;
import java.util.List;

// Library Classes
import org.apache.commons.lang.builder.ToStringBuilder;

// Framework Classes
import gov.va.med.fw.model.AbstractEntity;

/**
 * A class that stores query information used for paginated searches.
 *
 * @author Andrew Pach
 * @version 1.0
 */
public class SearchQueryInfo extends AbstractEntity implements Serializable
{
    /**
	 * An instance of serialVersionUID
	 */
	private static final long serialVersionUID = 103187236004574488L;

	/**
     * This search approach is based on the data retrieved.  Based on the size of data and the number of rows retrieved,
     * one of the other search approaches will be dynamically selected on the fly.  This is the prefered approach since
     * the the VM should not run out of memory and all memory will be read into memory when the resultant record set
     * isn't too large.
     */
    public static final String SEARCH_DATA_OPTIMIZED = "dataOptimized";

    /**
     * This search approach will read all records in memory no matter how big the result set is.  This approach should
     * only be used when the search criteria won't retrieve so many results that the VM will run out of memory. This
     * approach will also not display background data updates when the user is sorting or paging across the resultant
     * data.
     */
    public static final String SEARCH_READ_ALL = "readAll";

    /**
     * This search approach will only read one page's worth of data in memory at a time.  This approach will read the
     * initial page of data quicker than the "read all" approach, but is slightly slower when the user is sorting or
     * paging across data.
     */
    public static final String SEARCH_SINGLE_PAGE = "singlePage";

    /**
     * The caller is requesting a new search.
     */
    public static final String ACTION_SEARCH = "actionSearch";

    /**
     * The caller is requesting no action.  If no results have been read, a search will be
     * performed to retrieve the results for the previous page.  If results have already
     * been read, no further action will be taken.
     */
    public static final String ACTION_NONE = "actionNone";

    /**
     * The caller is requesting to go to a new page.
     */
    public static final String ACTION_PAGE = "actionPage";

    /**
     * The caller is requesting to sort on a new column.
     */
    public static final String ACTION_SORT = "actionSort";

    /**
     * The caller is requesting to updated selected items.
     */
    public static final String ACTION_SELECT = "actionSelect";

    /**
     * The search optimization type to use.
     */
    private String searchOptimizationType = SEARCH_DATA_OPTIMIZED;

    /**
     * Defines which search type was performing.  This should be SEARCH_READ_ALL or SEARCH_SINGLE_PAGE.
     */
    private String searchTypePerformed = null;

    /**
     * The number of entries per page.
     */
    private int numberPerPage = Integer.MAX_VALUE;

    /**
     * The current page.
     */
    private int pagingPage = 1;

    /**
     * The maximum number of records that can be retrieved from a search.
     */
    private int maxAllowedRecords = Integer.MAX_VALUE;

    /**
     * The list of SortElements.
     */
    private List sortElements = null;

    /**
     * Determines whether the search should be case sensitive or not.  Default: false.
     */
    private boolean caseSensitive = false;

    /**
     * If true, empty parameter string filters are skipped.  If false, empty filters are checked for null. Default:
     * false.
     */
    private boolean removeEmptyStrings = false;

    /**
     * Flag indicating whether the query performed a sort or not.
     */
    private boolean sortPerformed = false;

    /**
     * Flag indicating that a sort was requested on a column that is not supported in the database.
     */
    private boolean sortColumnNotSupported = false;

    /**
     * The total number of entries that the data query would retrieve.  Eventhough the query might only return one pages
     * worth of data, this value should list the total number of entries that are available.
     */
    private int totalNumberOfEntries = 0;

    /**
     * The maximum number of estimated bytes allowed in memory per search for a full results set.
     */
    private int maxInMemoryEstimatedResultsSizeInBytes = -1;

    /**
     * The search action being performed.
     */
    private String searchAction = ACTION_SEARCH;

    /**
     * The optional results.  This will be populated when a search is not needed and the results
     * have been previously retrieved outside of the search service.
     */
    private List results = null;

    /**
     * Sets the number of entries per page.
     *
     * @param numberPerPage The number of entries per page.
     */
    public void setNumberPerPage(int numberPerPage)
    {
        this.numberPerPage = numberPerPage;
    }

    /**
     * Gets the number of entries per page.
     *
     * @return Returns the number of entries per page.
     */
    public int getNumberPerPage()
    {
        return numberPerPage;
    }

    /**
     * Sets the current pagination page.
     *
     * @param pagingPage The current page
     */
    public void setPagingPage(int pagingPage)
    {
        this.pagingPage = pagingPage;
    }

    /**
     * Gets the current pagination page.
     *
     * @return The current page.
     */
    public int getPagingPage()
    {
        return pagingPage;
    }

    /**
     * Sets the sort elements.
     *
     * @param sortElements The sort elements.
     */
    public void setSortElements(List sortElements)
    {
        this.sortElements = sortElements;
    }

    /**
     * Gets the sort elements.
     *
     * @return Returns the sort elements.
     */
    public List getSortElements()
    {
        return sortElements;
    }

    /**
     * Gets whether emptry strings for filter based on null or be skipped.
     *
     * @return Returns the remove empty strings attribute.
     */
    public boolean getRemoveEmptyStrings()
    {
        return removeEmptyStrings;
    }

    /**
     * If true, empty parameter string filters are skipped.  If false, empty filters are checked for null.
     *
     * @param removeEmptyStrings Whether empty strings should be removed.
     */
    public void setRemoveEmptyStrings(boolean removeEmptyStrings)
    {
        this.removeEmptyStrings = removeEmptyStrings;
    }

    /**
     * Gets the flag that says whether the query performed a sort or not.
     *
     * @return True if the query performed a sort.  Otherwise, false.
     */
    public boolean getSortPerformed()
    {
        return sortPerformed;
    }

    /**
     * Sets whether the query performed a sort or not.
     *
     * @param sortPerformed Set to true if the query performed a sort.  Otherwise, set to false.
     */
    public void setSortPerformed(boolean sortPerformed)
    {
        this.sortPerformed = sortPerformed;
    }

    /**
     * Gets the flag that says whether a requested sort column is not supported within the database.
     *
     * @return the sort column not supported flag.
     */
    public boolean getSortColumnNotSupported()
    {
        return sortColumnNotSupported;
    }

    /**
     * Sets the flag that says whether a requested sort column is not supported within the database.
     *
     * @param sortColumnNotSupported The sort column not supported flag.
     */
    public void setSortColumnNotSupported(boolean sortColumnNotSupported)
    {
        this.sortColumnNotSupported = sortColumnNotSupported;
    }

    /**
     * Sets whether the search should be case sensitive or not.
     *
     * @param caseSensitive case sensitive flag.
     */
    public void setCaseSensitive(boolean caseSensitive)
    {
        this.caseSensitive = caseSensitive;
    }

    /**
     * Gets whether the search will be case sensitive or not.
     *
     * @return the case sensitive flag.
     */
    public boolean getCaseSensitive()
    {
        return caseSensitive;
    }

    /**
     * Sets the search optimization type.  One of the SEARCH constants in this file should be used.
     *
     * @param searchOptimizationType The search optimization type.
     */
    public void setSearchOptimizationType(String searchOptimizationType)
    {
        this.searchOptimizationType = searchOptimizationType;
    }

    /**
     * Gets the search optimization type.
     *
     * @return The search optimization type.
     */
    public String getSearchOptimizationType()
    {
        return this.searchOptimizationType;
    }

    /**
     * Sets the type of search performed.  This should be either SEARCH_READ_ALL or SEARCH_SINGLE_PAGE.
     *
     * @param searchTypePerformed The type of search performed.
     */
    public void setSearchTypePerformed(String searchTypePerformed)
    {
        this.searchTypePerformed = searchTypePerformed;
    }

    /**
     * Gets the type of search performed.
     *
     * @return the type of search performed.
     */
    public String getSearchTypePerformed()
    {
        return searchTypePerformed;
    }

    /**
     * Sets the total number of entries retrieved from a query.
     *
     * @param totalNumberOfEntries The total number of entries
     */
    public void setTotalNumberOfEntries(int totalNumberOfEntries)
    {
        this.totalNumberOfEntries = totalNumberOfEntries;
    }

    /**
     * Gets the total number of entries retrieved from a query (may be more than the number of results if only one pages
     * worth of data was retrieved.
     *
     * @return The total number of entries
     */
    public int getTotalNumberOfEntries()
    {
        return totalNumberOfEntries;
    }

    /**
     * Sets the maximum estimated size in bytes of the largest result set allowed in memory per query.
     *
     * @param bytes The number of bytes allowed.
     */
    public void setMaxInMemoryEstimatedResultsSizeInBytes(int bytes)
    {
        this.maxInMemoryEstimatedResultsSizeInBytes = bytes;
    }

    /**
     * Gets the maximum in memory estimated results size in bytes.
     *
     * @return The number of bytes allowed.
     */
    public int getMaxInMemoryEstimatedResultsSizeInBytes()
    {
        return maxInMemoryEstimatedResultsSizeInBytes;
    }

    /**
     * Sets the search action to perform. Once of the "SEARCH" constants in this file should be used.
     *
     * @param searchAction The search action.
     */
    public void setSearchAction(String searchAction)
    {
        this.searchAction = searchAction;
    }

    /**
     * Gets the search action.
     *
     * @return the search action.
     */
    public String getSearchAction()
    {
        return searchAction;
    }

    /**
     * Gets the maximum number of records that may be retrieved from a search.
     *
     * @return The maximum number of allowed records.
     */
    public int getMaxAllowedRecords()
    {
        return maxAllowedRecords;
    }

    /**
     * Sets the maximum number of records that may be retrieved from a search.
     *
     * @param maxAllowedRecords The maximum number of allowed records.
     */
    public void setMaxAllowedRecords(int maxAllowedRecords)
    {
        this.maxAllowedRecords = maxAllowedRecords;
    }

    /**
     * Gets the optional list of results.
     * @return the results
     */
    public List getResults()
    {
        return results;
    }

    /**
     * Sets the optional results.
     * @param results the results to set.
     */
    public void setResults(List results)
    {
        this.results = results;
    }

    /**
     * @see gov.va.med.fw.model.AbstractEntity#buildToString(org.apache.commons.lang.builder.ToStringBuilder)
     */
    protected void buildToString(ToStringBuilder builder)
    {
        builder.append("numberPerPage", getNumberPerPage());
        builder.append("pagingPage", getPagingPage());
        builder.append("sortElements", getSortElements());
        builder.append("removeEmptyStrings", getRemoveEmptyStrings());
        builder.append("caseSensitive", getCaseSensitive());
        builder.append("searchOptimizationType", getSearchOptimizationType());
        builder.append("searchTypePerformed", getSearchTypePerformed());
        builder.append("totalNumberOfEntries", getTotalNumberOfEntries());
        builder.append("maxInMemoryEstimatedResultsSizeInBytes", getMaxInMemoryEstimatedResultsSizeInBytes());
        builder.append("searchAction", getSearchAction());
        builder.append("maxAllowedRecords", getMaxAllowedRecords());
        builder.append("results", getResults());
    }
}