package hirondelle.fish.main.rating;
import java.util.List;
import java.util.regex.Pattern;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.database.Db;
import hirondelle.web4j.database.SqlId;
import hirondelle.web4j.model.Id;
import hirondelle.web4j.model.ModelCtorException;
import hirondelle.web4j.model.ModelFromRequest;
import hirondelle.web4j.request.RequestParameter;
import hirondelle.web4j.request.RequestParser;
import hirondelle.web4j.action.ActionTemplateListAndEdit;
import hirondelle.web4j.action.ResponsePage;
import hirondelle.fish.util.ReqParam;
import hirondelle.fish.util.TemplatedPage;
/**
Allow ratings to be edited for each {@link hirondelle.fish.main.resto.Resto}.
@sql statements.sql
@view view.jsp
*/
public final class RatingAction extends ActionTemplateListAndEdit {
/** Constructor. */
public RatingAction(RequestParser aRequestParser){
super(FORWARD, REDIRECT_TO_LISTING, aRequestParser);
}
public static final SqlId RATING_LIST = new SqlId("RATING_LIST");
public static final SqlId RATING_FETCH_FOR_CHANGE = new SqlId("RATING_FETCH_FOR_CHANGE");
public static final SqlId RATING_CHANGE = new SqlId("RATING_CHANGE");
private static final Pattern fRATING_REGEX = Pattern.compile("(0|1|2|3|4|5|6|7|8|9|10)");
public static final RequestParameter RATING_ID = ReqParam.ID;
public static final RequestParameter FISH_RATING = RequestParameter.withRegexCheck("FishRating", fRATING_REGEX);
public static final RequestParameter CHIPS_RATING = RequestParameter.withRegexCheck("ChipsRating", fRATING_REGEX);
public static final RequestParameter PRICE_RATING = RequestParameter.withRegexCheck("PriceRating", fRATING_REGEX);
public static final RequestParameter LOCATION_RATING = RequestParameter.withRegexCheck("LocationRating", fRATING_REGEX);
public static final RequestParameter SERVICE_RATING = RequestParameter.withRegexCheck("ServiceRating", fRATING_REGEX);
public static final RequestParameter BEER_RATING = RequestParameter.withRegexCheck("BeerRating", fRATING_REGEX);
/** List ratings for all restaurants. */
protected void doList() throws DAOException {
addToRequest(ITEMS_FOR_LISTING, listAllRatings());
}
/** Fetch a {@link Rating} in preparation for editing it. */
protected void attemptFetchForChange() throws DAOException {
Rating rating = fetchRating(getIdParam(RATING_ID));
if ( rating != null ){
addToRequest(ITEM_FOR_EDIT, rating);
}
else {
addError("Cannot fetch the selected item. Likely deleted by another user.");
}
}
/** Ensure user input can create a {@link Rating}. */
protected void validateUserInput() {
try {
ModelFromRequest builder = new ModelFromRequest(getRequestParser());
fRating = builder.build(Rating.class, RATING_ID, null, FISH_RATING, CHIPS_RATING, PRICE_RATING, LOCATION_RATING, SERVICE_RATING, BEER_RATING, null);
}
catch (ModelCtorException ex){
addError(ex);
}
}
/** Apply an edit to a {@link Rating}. */
protected void attemptChange() throws DAOException {
int numEdits = change(fRating);
if ( numEdits == 0 ){
addError("Update failed. Has item been deleted by another user?");
}
}
/**
Not implemented in this case. The ratings are created at the same time as the
underlying Restaurant, with <tt>0</tt> default values for each rated item.
*/
protected void attemptAdd() throws DAOException {
//empty
}
/** Not implemented in this case. */
protected void attemptDelete() throws DAOException {
//empty
}
// PRIVATE //
private Rating fRating;
private static final ResponsePage FORWARD = TemplatedPage.get(
"Ratings", "view.jsp", RatingAction.class
);
private static final ResponsePage REDIRECT_TO_LISTING = new ResponsePage("RatingAction.list");
/** Return a <tt>List</tt> of all {@link Rating} objects, for all restaurants. */
private List<Rating> listAllRatings() throws DAOException {
return Db.list(Rating.class, RATING_LIST);
}
/** Return a single {@link Rating} identified by its id. */
private Rating fetchRating(Id aRatingId) throws DAOException {
return Db.fetch(Rating.class, RATING_FETCH_FOR_CHANGE, aRatingId);
}
/** Update an existing {@link Rating}. */
private int change(Rating aRating) throws DAOException {
Object[] params = {
aRating.getFishRating(), aRating.getChipsRating(), aRating.getPriceRating(),
aRating.getLocationRating(), aRating.getServiceRating(),
aRating.getBeerRating(), aRating.getId()
};
return Db.edit(RATING_CHANGE, params);
}
}