001package edu.pdx.cs410J.whitlock;
002
003import com.google.common.annotations.VisibleForTesting;
004
005import javax.servlet.ServletException;
006import javax.servlet.http.HttpServlet;
007import javax.servlet.http.HttpServletRequest;
008import javax.servlet.http.HttpServletResponse;
009import java.io.IOException;
010import java.io.PrintWriter;
011import java.util.HashMap;
012import java.util.Map;
013
014/**
015 * This servlet ultimately provides a REST API for working with an
016 * <code>AppointmentBook</code>.  However, in its current state, it is an example
017 * of how to use HTTP and Java servlets to store simple key/value pairs.
018 */
019public class AppointmentBookServlet extends HttpServlet
020{
021    private final Map<String, AppointmentBook> appointmentBooks = new HashMap<>();
022
023    public AppointmentBookServlet() {
024        createPreCannedAppointmentBook();
025    }
026
027    private void createPreCannedAppointmentBook() {
028        String owner = "PreCannedOwner";
029        AppointmentBook book = new AppointmentBook(owner);
030        this.appointmentBooks.put(owner, book);
031
032    }
033
034    /**
035     * Handles an HTTP GET request from a client by writing the value of the key
036     * specified in the "key" HTTP parameter to the HTTP response.  If the "key"
037     * parameter is not specified, all of the key/value pairs are written to the
038     * HTTP response.
039     */
040    @Override
041    protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
042    {
043        response.setContentType( "text/plain" );
044
045        String owner = getParameter( "owner", request );
046
047        AppointmentBook book = getAppointmentBookForOwner(owner);
048
049        prettyPrint(book, response.getWriter());
050
051        response.setStatus(HttpServletResponse.SC_OK);
052    }
053
054    private void prettyPrint(AppointmentBook book, PrintWriter pw) throws IOException {
055        PrettyPrinter pretty = new PrettyPrinter(pw);
056        pretty.dump(book);
057    }
058
059    @VisibleForTesting
060    AppointmentBook getAppointmentBookForOwner(String owner) {
061        return this.appointmentBooks.get(owner);
062    }
063
064    /**
065     * Handles an HTTP POST request by storing the key/value pair specified by the
066     * "key" and "value" request parameters.  It writes the key/value pair to the
067     * HTTP response.
068     */
069    @Override
070    protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
071    {
072        response.setContentType( "text/plain" );
073
074        String owner = getParameter("owner", request);
075
076        AppointmentBook book = getAppointmentBookForOwner(owner);
077
078        String description = getParameter("description", request);
079        String beginTime = getParameter("beginTime", request);
080        String endTime = getParameter("endTime", request);
081
082        Appointment appointment = new Appointment(description, beginTime, endTime);
083        book.addAppointment(appointment);
084
085        response.setStatus(HttpServletResponse.SC_OK);
086    }
087
088    /**
089     * Handles an HTTP DELETE request by removing all key/value pairs.  This
090     * behavior is exposed for testing purposes only.  It's probably not
091     * something that you'd want a real application to expose.
092     */
093    @Override
094    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
095        response.setContentType("text/plain");
096
097        this.appointmentBooks.clear();
098
099        PrintWriter pw = response.getWriter();
100        pw.println(Messages.allMappingsDeleted());
101        pw.flush();
102
103        response.setStatus(HttpServletResponse.SC_OK);
104
105    }
106
107    /**
108     * Writes an error message about a missing parameter to the HTTP response.
109     *
110     * The text of the error message is created by {@link Messages#missingRequiredParameter(String)}
111     */
112    private void missingRequiredParameter( HttpServletResponse response, String parameterName )
113        throws IOException
114    {
115        String message = Messages.missingRequiredParameter(parameterName);
116        response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED, message);
117    }
118
119    /**
120     * Returns the value of the HTTP request parameter with the given name.
121     *
122     * @return <code>null</code> if the value of the parameter is
123     *         <code>null</code> or is the empty string
124     */
125    private String getParameter(String name, HttpServletRequest request) {
126      String value = request.getParameter(name);
127      if (value == null || "".equals(value)) {
128        return null;
129
130      } else {
131        return value;
132      }
133    }
134
135    @VisibleForTesting
136    String getValueForKey(String key) {
137        throw new UnsupportedOperationException("I don't work anymore!");
138    }
139}