Package hirondelle.fish.main.search

Source Code of hirondelle.fish.main.search.RestoSearchAction

package hirondelle.fish.main.search;

import java.util.*;
import java.util.logging.*;
import hirondelle.web4j.model.AppException;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.request.RequestParser;
import hirondelle.web4j.request.RequestParameter;
import hirondelle.web4j.action.ResponsePage;
import hirondelle.web4j.action.ActionTemplateSearch;
import hirondelle.web4j.database.Db;
import hirondelle.web4j.database.SqlId;
import hirondelle.fish.main.resto.Resto;
import hirondelle.fish.util.TemplatedPage;
import hirondelle.web4j.util.Util;
import hirondelle.web4j.model.ModelFromRequest;
import hirondelle.web4j.database.DynamicCriteria;
import static hirondelle.web4j.database.DynamicCriteria.DESC;
import static hirondelle.web4j.database.DynamicCriteria.WHERE;
import static hirondelle.web4j.database.DynamicCriteria.AND;
import static hirondelle.web4j.util.Consts.NEW_LINE;

/**
Search for {@link Resto}s by name.
<P>There are two search criteria, one on name, and one on price.
<P>As well, the sort order of the listing may also be reversed.
<P> <em>Implementation Note:</em><br>
The <tt>WHERE</tt> and <tt>ORDER BY</tt> clauses of the SQL statement
are dynamically generated using {@link hirondelle.web4j.database.DynamicCriteria}.
@sql statements.sql
@view view.jsp
*/
public final class RestoSearchAction extends ActionTemplateSearch {

  /** Constructor. */
  public RestoSearchAction(RequestParser aRequestParser){
    super(FORWARD, aRequestParser);
  }
 
  public static final RequestParameter STARTS_WITH = RequestParameter.withLengthCheck("Starts With");
  public static final RequestParameter REVERSE_SORT = RequestParameter.withRegexCheck("Reverse Sort", "(true)");
  public static final RequestParameter MIN_PRICE = RequestParameter.withLengthCheck("Minimum Price");
  public static final RequestParameter MAX_PRICE = RequestParameter.withLengthCheck("Maximum Price");
  public static final RequestParameter ORDER_BY = RequestParameter.withLengthCheck("Order By");
 
  public static final SqlId RESTO_DYNAMIC_SEARCH = new SqlId("RESTO_DYNAMIC_SEARCH");
 
  /**
   Ensure the user input can build a {@link RestoSearchCriteria}.
  
   <P>The end user may input criteria on name, price or both. The {@link #ORDER_BY} parameter is always submitted,
   since there is no 'blank' value in the <tt>SELECT</tt> control.
  */
  protected void validateUserInput() throws AppException {
    try {
      ModelFromRequest builder = new ModelFromRequest(getRequestParser());
      fCriteria = builder.build(RestoSearchCriteria.class, STARTS_WITH, MIN_PRICE, MAX_PRICE, ORDER_BY, REVERSE_SORT);
    }
    catch (ModelCtorException ex){
      addError(ex);
    }
  }
 
  /** Fetch the records consistent with input criteria, and display the result. */
  protected void listSearchResults() throws AppException {
    //note that BOTH the criteria AND the corresponding '?' data need to be calculated 'simultaneously': they are
    //closely related, since the data passed in depends tightly on which criteria are present
    List restos = Db.search(Resto.class, RESTO_DYNAMIC_SEARCH, getCriteria(), getParams());
    if ( restos.isEmpty() ){
      addMessage("No Results.");
    }
    else {
      addToRequest(ITEMS_FOR_LISTING, restos);
    }
  }
 
  // PRIVATE
  private static final ResponsePage FORWARD = TemplatedPage.get("Search", "view.jsp", RestoSearchAction.class);
  private RestoSearchCriteria fCriteria;
  private static final String NAME_LIKE = "Name Like ?" + NEW_LINE;
  private static final String PRICE_RANGE = "Price >= ? AND Price <= ?" + NEW_LINE;
  private static final Logger fLogger = Util.getLogger(RestoSearchAction.class);
 
  /* Could move this method into a DAO, if desired. */
  private DynamicCriteria getCriteria() throws ModelCtorException {
    StringBuilder result = new StringBuilder(WHERE + NEW_LINE);
    boolean hasAddedFirstCriterion = false;
   
    if( Util.textHasContent(fCriteria.getStartsWith()) ) {
      result.append(NAME_LIKE);
      hasAddedFirstCriterion = true;
    }
    if( fCriteria.getMinPrice() != null ){
      if( hasAddedFirstCriterion ){
        result.append(AND);
      }
      result.append(PRICE_RANGE);
    }
   
    result.append(DynamicCriteria.ORDER_BY + fCriteria.getOrderBy());
    if (fCriteria.isReverseOrder()) {
      result.append(DESC);
    }
   
    fLogger.fine("Dynamic SQL criteria: " + result);
    return new DynamicCriteria(result);
  }
 
  /**
   Return the user input values for all '?' placeholders.
  
   <P>Since the underlying SQL is dynamic, the exact sequence of params depends on the selected criteria.
   Different Object sequences are needed for different groups of criteria.
  */
  private Object[] getParams(){
    List<Object> result = new ArrayList<Object>();
    if( Util.textHasContent(fCriteria.getStartsWith()) ){
      result.add(fCriteria.getStartsWith());
    }
    if ( fCriteria.getMinPrice() != null ) {
      result.add( fCriteria.getMinPrice() );
      result.add( fCriteria.getMaxPrice() );
    }
    return result.toArray();
  }
}
TOP

Related Classes of hirondelle.fish.main.search.RestoSearchAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.