package todo; import static java.util.Collections.singletonMap; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.nate.Encoder; import org.nate.Engine; import org.nate.Nate; public class ToDoServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final Encoder HTML_ENCODER = Nate.encoders().encoderFor("XML"); private Engine LAYOUT; private Engine ADD; private Engine LIST; private ToDoRepository toDoRepository = new ToDoRepository(); private enum Action {GetTodos, NewTodo, AddTodo, DeleteTodo}; @Override public void init(ServletConfig config) throws ServletException { super.init(config); LAYOUT = createEngineFor(config, "/WEB-INF/templates/layout.html"); ADD = createEngineFor(config, "/WEB-INF/templates/add.html").select("## #content"); LIST = createEngineFor(config, "/WEB-INF/templates/list.html").select("## #content"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); resp.setStatus(HttpServletResponse.SC_OK); Action action = extractAction(req); if (action == Action.GetTodos) { resp.getWriter().println(getToDos()); } else { resp.getWriter().println(newToDo()); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); Action action = extractAction(req); if (action == Action.AddTodo) { addToDo(req); } else { removeToDo(req); } resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); resp.setHeader("Location", "/todo"); } private void removeToDo(HttpServletRequest req) { long id = Long.valueOf(req.getParameter("id")); toDoRepository.delete(id); } private void addToDo(HttpServletRequest req) { String title = req.getParameter("title"); toDoRepository.add(new ToDo(title)); } private String newToDo() { return LAYOUT.inject(singletonMap("#content", ADD)).render(); } private String getToDos() { List<ToDo> toDos = toDoRepository.all(); List<Map<String, Object>> todoData = new ArrayList<Map<String,Object>>(); for (ToDo toDo : toDos) { Map<String, Object> todoMap = new HashMap<String, Object>(); todoMap.put(".title", toDo.getTitle()); todoMap.put("input[name=id]", singletonMap("@@value", toDo.getId())); todoData.add(todoMap); } Object data = singletonMap(".todo", todoData); Engine list = LIST.inject(singletonMap(".todolist", data)); return LAYOUT.inject(singletonMap("#content", list)).render(); } private Action extractAction(HttpServletRequest req) { String requestURI = req.getRequestURI(); if (requestURI.endsWith("new")) { return Action.NewTodo; } if (requestURI.endsWith("add")) { return Action.AddTodo; } if (requestURI.endsWith("finished")) { return Action.DeleteTodo; } return Action.GetTodos; } private Engine createEngineFor(ServletConfig config, String source) { InputStream inputStream = new BufferedInputStream(config.getServletContext().getResourceAsStream(source)); try { return Nate.newWith(inputStream, HTML_ENCODER); } finally { try { inputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } } } }