/* Copyright (c) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package sample.gbase.recipe; import com.google.api.gbase.client.FeedURLFactory; import com.google.api.gbase.client.GoogleBaseEntry; import com.google.api.gbase.client.GoogleBaseService; import com.google.api.gbase.client.NumberUnit; import com.google.gdata.util.ServiceException; import java.io.IOException; import java.net.URL; import java.util.Set; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Inserts, updates or deletes a recipe, * depending on the "action" servlet initialization parameter. */ @SuppressWarnings("serial") public class RecipeActionServlet extends HttpServlet { public static final String DISPLAY_JSP = "/WEB-INF/recipeEdit.jsp"; private static final int ACTION_ADD = 0; private static final int ACTION_UPDATE = 1; private static final int ACTION_DELETE = 2; protected FeedURLFactory urlFactory; /** The operation this servlet has to perform. */ protected int action = -1; @Override public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); ServletContext context = servletConfig.getServletContext(); urlFactory = (FeedURLFactory) context.getAttribute(RecipeListener.FEED_URL_FACTORY_ATTRIBUTE); String action = servletConfig.getInitParameter("action"); if ("add".equals(action)) { this.action = ACTION_ADD; } else if ("update".equals(action)) { this.action = ACTION_UPDATE; } else if ("delete".equals(action)) { this.action = ACTION_DELETE; } else { throw new ServletException("Unknown action: " + action); } } private boolean isAdd() { return ACTION_ADD == action; } private boolean isUpdate() { return ACTION_UPDATE == action; } private boolean isDelete() { return ACTION_DELETE == action; } @Override public void destroy() { super.destroy(); } /** Inserts or updates the submitted recipe and redirects to recipeList. */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { GoogleBaseService service = (GoogleBaseService) request.getAttribute( AuthenticationFilter.SERVICE_ATTRIBUTE); Recipe recipe = getPostedRecipe(request); if (!recipe.isComplete()) { String message = "<div class='errormessage'>Please fill out " + "all the mandatory fields.</div>"; editRecipe(request, response, recipe, message); } else { try { if (isAdd()) { recipeAdd(service, recipe); } else if (isUpdate()) { recipeUpdate(service, recipe); } else { throw new ServletException("Unknown POST action: " + action); } } catch (ServiceException e) { RecipeUtil.logServiceException(this, e); RecipeUtil.forwardToErrorPage(request, response, e); return; } listOwnRecipes(response); } } /** Redirect to the page that lists customer's recipes. */ protected void listOwnRecipes(HttpServletResponse response) throws IOException { String redirectUrl = "recipeList"; response.sendRedirect(response.encodeRedirectURL(redirectUrl)); } /** * Inserts a recipe using the specified authenticated service. * * @param service an authenticated GoogleBaseService * @param recipe recipe to be inserted * @throws IOException * @throws ServiceException */ protected void recipeAdd(GoogleBaseService service, Recipe recipe) throws IOException, ServiceException { URL feedUrl = urlFactory.getItemsFeedURL(); GoogleBaseEntry entry = recipe.toGoogleBaseEntry(null); service.insert(feedUrl, entry); } /** * Updates a recipe using the specified authenticated service. * * The recipe must have a valid GoogleBase id. * * @param service an authenticted GoogleBaseService * @param recipe recipe to be updated * @throws ServiceException * @throws IOException */ protected void recipeUpdate(GoogleBaseService service, Recipe recipe) throws ServiceException, IOException { URL feedUrl = urlFactory.getItemsEntryURL(recipe.getId()); GoogleBaseEntry entry = recipe.toGoogleBaseEntry(feedUrl.toString()); service.update(feedUrl, entry); } /** * Uses the specified authenticated service to delete a recipe. * * @param service an authenticated service * @param id the id of the recipe * @throws ServiceException * @throws IOException */ protected void recipeDelete(GoogleBaseService service, String id) throws ServiceException, IOException { URL feedUrl = urlFactory.getItemsEntryURL(id); service.delete(feedUrl); } /** * Builds a Recipe from the parameters submitted with the specified request. * * @param request http request to be processed * @return a submitted recipe */ static Recipe getPostedRecipe(HttpServletRequest request) { String id = getNullIfEmpty(request.getParameter(RecipeUtil.ID_PARAMETER)); String title = getNullIfEmpty(request.getParameter( RecipeUtil.TITLE_PARAMETER)); String url = getNullIfEmpty(request.getParameter(RecipeUtil.URL_PARAMETER)); String description = getNullIfEmpty(request.getParameter( RecipeUtil.DESCRIPTION_PARAMETER)); Set<String> mainIngredient = RecipeUtil.validateValues( request.getParameterValues(RecipeUtil.MAIN_INGREDIENT_PARAMETER)); Set<String> cuisine = RecipeUtil.validateValues( request.getParameterValues(RecipeUtil.CUISINE_PARAMETER)); NumberUnit<Integer> cookingTime; try { cookingTime = new NumberUnit<Integer>( new Integer(request.getParameter(RecipeUtil.COOKING_TIME_PARAMETER)), RecipeUtil.COOKING_TIME_UNIT); } catch (Exception e) { // If anything goes bad, we set cookingTime to null cookingTime = null; } Recipe recipe = new Recipe(id, title, url, description, mainIngredient, cuisine, cookingTime); return recipe; } static private String getNullIfEmpty(String s) { return s != null && "".equals(s) ? null : s; } /** Shows the page for inserting or updating a recipe or deletes a recipe. */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { GoogleBaseService service = (GoogleBaseService) request.getAttribute( AuthenticationFilter.SERVICE_ATTRIBUTE); String id = request.getParameter(RecipeUtil.ID_PARAMETER); try { if (isDelete()) { recipeDelete(service, id); listOwnRecipes(response); } else { // The recipe that will be used on the edit page // for inserting or updating. Recipe recipe = null; if (isAdd()) { recipe = new Recipe(); } else if (isUpdate()) { URL entryUrl = urlFactory.getItemsEntryURL(id); GoogleBaseEntry entry = service.getEntry(entryUrl); recipe = new Recipe(entry); } if (recipe != null) { // Ready to add or update editRecipe(request, response, recipe, null); } } } catch (ServiceException e) { RecipeUtil.logServiceException(this, e); RecipeUtil.forwardToErrorPage(request, response, e); return; } } /** * Sets the {@value RecipeUtil#RECIPE_ATTRIBUTE} attribute of the request to * contain the specified recipe and forwards the request to the * {@value #DISPLAY_JSP} page. * * @param request * @param response * @param recipe the recipe to be passed to the edit jsp page * @param message HTML code to be displayed at the top of the page, usually an * error message */ private void editRecipe(HttpServletRequest request, HttpServletResponse response, Recipe recipe, String message) throws ServletException, IOException { request.setAttribute(RecipeUtil.RECIPE_ATTRIBUTE, recipe); request.setAttribute(RecipeUtil.MESSAGE_ATTRIBUTE, message == null ? "" : message); // Forward to the JSP request.getRequestDispatcher(DISPLAY_JSP).forward(request, response); } }