com.techngage.smartbin.Controller.java Source code

Java tutorial

Introduction

Here is the source code for com.techngage.smartbin.Controller.java

Source

/*
 * Copyright 2013-2015 MongoDB 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 com.techngage.smartbin;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoDatabase;
import com.sun.xml.internal.bind.v2.runtime.Location;
import freemarker.template.Configuration;
import freemarker.template.SimpleHash;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringEscapeUtils;
import org.bson.Document;
import spark.Request;
import spark.Response;
import spark.Route;
import spark.Spark;

import javax.servlet.http.Cookie;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import static spark.Spark.get;
import static spark.Spark.post;
import static spark.Spark.setPort;

/**
 * This class is a controller for this smartbin web application.  It established all interaction with MongoDB
 * to three Data Access Objects (DAOs).
 *
 * It is also the entry point into the web application.
 */
public class Controller {
    private final Configuration cfg;
    private final UserDAO userDAO;
    private final SessionDAO sessionDAO;
    private final RouteDAO routeDAO;
    private final TruckDAO truckDAO;
    private final LocationDAO locationDAO;

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            new Controller("mongodb://localhost");
        } else {
            new Controller(args[0]);
        }
    }

    public Controller(String mongoURIString) throws IOException {
        final MongoClient mongoClient = new MongoClient(new MongoClientURI(mongoURIString));
        final MongoDatabase smartbinDatabase = mongoClient.getDatabase("smartbin");

        userDAO = new UserDAO(smartbinDatabase);
        sessionDAO = new SessionDAO(smartbinDatabase);
        routeDAO = new RouteDAO(smartbinDatabase);
        truckDAO = new TruckDAO(smartbinDatabase);
        locationDAO = new LocationDAO(smartbinDatabase);

        cfg = createFreemarkerConfiguration();
        setPort(8082);
        Spark.staticFileLocation("/public");
        initializeRoutes();
    }

    abstract class FreemarkerBasedRoute extends Route {
        final Template template;

        /**
         * Constructor
         *
         * @param path The route path which is used for matching. (e.g. /hello, users/:name)
         */
        protected FreemarkerBasedRoute(final String path, final String templateName) throws IOException {
            super(path);
            template = cfg.getTemplate(templateName);
        }

        @Override
        public Object handle(Request request, Response response) {
            StringWriter writer = new StringWriter();
            try {
                doHandle(request, response, writer);
            } catch (Exception e) {
                e.printStackTrace();
                response.redirect("/internal_error");
            }
            return writer;
        }

        protected abstract void doHandle(final Request request, final Response response, final Writer writer)
                throws IOException, TemplateException;

    }

    private void initializeRoutes() throws IOException {

        // Get all the available truck ids
        get(new Route("/truck") {
            @Override
            public Object handle(Request request, Response response) {
                List<Document> truckList = truckDAO.getTruckIds();
                String truckStr = "";
                String truckStrTmp = "";
                for (int i = 0; i < truckList.size(); i++) {
                    truckStr = (String) truckList.get(i).get("truckid");
                    if (i == truckList.size() - 1) {
                        truckStrTmp = truckStrTmp + truckStr;
                    } else {
                        truckStrTmp = truckStrTmp + truckStr + ";";
                    }
                }
                return truckStrTmp;
            }
        });

        // present signup form for smartbin app
        get(new Route("/unassign") {
            @Override
            public Object handle(Request request, Response response) {
                // Unassign route to truck.
                int routeId = Integer.parseInt(request.queryParams("routeid"));
                String truckId = request.queryParams("truckid");
                String status = routeDAO.unassignRoute(truckId, routeId);
                truckDAO.updateTruckAsUnAssigned(truckId, routeDAO.checkRouteAssigned(truckId));
                return status;
            }
        });

        // present signup form for smartbin app
        get(new Route("/assign") {
            @Override
            public Object handle(Request request, Response response) {
                // Assign route to truck.
                int routeId = Integer.parseInt(request.queryParams("routeid"));
                String truckId = request.queryParams("truckid");
                String status = routeDAO.assignRoute(truckId, routeId);
                truckDAO.updateTruckAsAssigned(truckId);
                return status;
            }
        });

        // insert location and coordinates, public api called from micro-controller
        post(new Route("/insert") {
            @Override
            public Object handle(Request request, Response response) {
                String cookie = getSessionCookie(request);
                String username = sessionDAO.findUserNameBySessionId(cookie);

                if (username == null) {
                    System.out.println("You are not authorized");
                    response.status(403);
                } else {
                    // Insert route.
                    String location = request.queryParams("location");
                    String coordinates = request.queryParams("coordinates");
                    boolean isDuplicate = locationDAO.checkDuplicateRoute(coordinates);
                    if (location != null && coordinates != null && !isDuplicate) {
                        locationDAO.insertRoute(location, coordinates);
                    }
                }
                return null;
            }
        });

        // handle the signup to smartbin web app
        post(new FreemarkerBasedRoute("/signup", "signup.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {
                String email = request.queryParams("email");
                String username = request.queryParams("username");
                String password = request.queryParams("password");
                String verify = request.queryParams("verify");

                HashMap<String, String> root = new HashMap<String, String>();
                root.put("username", StringEscapeUtils.escapeHtml4(username));
                root.put("email", StringEscapeUtils.escapeHtml4(email));

                if (validateSignup(username, password, verify, email, root)) {
                    // good user
                    System.out.println("Signup: Creating user with: " + username + " " + password);
                    if (!userDAO.addUser(username, password, email)) {
                        // duplicate user
                        root.put("username_error", "Username already in use, Please choose another");
                        template.process(root, writer);
                    } else {
                        // good user, let's start a session
                        String sessionID = sessionDAO.startSession(username);
                        System.out.println("Session ID is" + sessionID);

                        response.raw().addCookie(new Cookie("session", sessionID));
                        response.redirect("/dashboard");
                    }
                } else {
                    // bad signup
                    System.out.println("User Registration did not validate");
                    template.process(root, writer);
                }
            }
        });

        // present signup form for smartbin app
        get(new FreemarkerBasedRoute("/signup", "signup.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {

                SimpleHash root = new SimpleHash();

                // initialize values for the form.
                root.put("username", "");
                root.put("password", "");
                root.put("email", "");
                root.put("password_error", "");
                root.put("username_error", "");
                root.put("email_error", "");
                root.put("verify_error", "");

                template.process(root, writer);
            }
        });

        get(new FreemarkerBasedRoute("/dashboard", "dashboard.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {

                String cookie = getSessionCookie(request);
                String username = sessionDAO.findUserNameBySessionId(cookie);

                if (username == null) {
                    System.out.println("dashboard() can't identify the user, redirecting to signup");
                    response.redirect("/login");

                } else {
                    SimpleHash root = new SimpleHash();
                    int totRoutes = 3;
                    List<Document> routes = routeDAO.getRoutes(totRoutes);
                    root.put("username", username);
                    root.put("names", routeDAO.getRoute());
                    root.put("myroutes", routes);
                    root.put("totallimitedroutes", totRoutes);
                    root.put("totalescalatedroutes", routeDAO.getEscalatedRoutes().size());
                    root.put("totalcompletedroutes", routeDAO.getCompletedRoutes().size());
                    root.put("totalinprogressroutes", routeDAO.getEscalatedRoutes().size());

                    List<Document> truckList = truckDAO.getTruckIds();
                    /*String truckStr = "";
                    String truckStrTmp = "";
                    for(int i=0;i<truckList.size();i++){
                    truckStr = (String)truckList.get(i).get("truckid");
                    if(i == truckList.size()-1){
                        truckStrTmp = truckStrTmp + truckStr;
                    } else {
                        truckStrTmp = truckStrTmp + truckStr + ";";
                    }
                    }*/
                    root.put("trucklist", truckList);

                    template.process(root, writer);
                }
            }
        });

        // present the login page
        get(new FreemarkerBasedRoute("/login", "login.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {
                SimpleHash root = new SimpleHash();

                root.put("username", "");
                root.put("login_error", "");

                template.process(root, writer);
            }
        });

        // process output coming from login form. On success redirect folks to the dashboard
        // on failure, just return an error and let them try again.
        post(new FreemarkerBasedRoute("/login", "login.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {

                String username = request.queryParams("username");
                String password = request.queryParams("password");

                System.out.println("Login: User submitted: " + username + "  " + password);

                Document user = userDAO.validateLogin(username, password);

                if (user != null) {

                    // valid user, let's log them in
                    String sessionID = sessionDAO.startSession(user.get("_id").toString());

                    if (sessionID == null) {
                        response.redirect("/internal_error");
                    } else {
                        // set the cookie for the user's browser
                        response.raw().addCookie(new Cookie("session", sessionID));

                        response.redirect("/dashboard");
                    }
                } else {
                    SimpleHash root = new SimpleHash();

                    root.put("username", StringEscapeUtils.escapeHtml4(username));
                    root.put("password", "");
                    root.put("login_error", "Invalid Login");
                    template.process(root, writer);
                }
            }
        });

        // allows the user to logout of the smartbin app
        get(new FreemarkerBasedRoute("/logout", "signup.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {

                String sessionID = getSessionCookie(request);
                if (sessionID == null) {
                    // no session to end
                    response.redirect("/login");
                } else {
                    // deletes from session table
                    sessionDAO.endSession(sessionID);

                    // this should delete the cookie
                    Cookie c = getSessionCookieActual(request);
                    c.setMaxAge(0);

                    response.raw().addCookie(c);

                    response.redirect("/login");
                }
            }
        });

        // used to process internal errors
        get(new FreemarkerBasedRoute("/internal_error", "error_template.ftl") {
            @Override
            protected void doHandle(Request request, Response response, Writer writer)
                    throws IOException, TemplateException {
                SimpleHash root = new SimpleHash();

                root.put("error", "System has encountered an error.");
                template.process(root, writer);
            }
        });
    }

    // helper function to get session cookie as string
    private String getSessionCookie(final Request request) {
        if (request.raw().getCookies() == null) {
            return null;
        }
        for (Cookie cookie : request.raw().getCookies()) {
            if (cookie.getName().equals("session")) {
                return cookie.getValue();
            }
        }
        return null;
    }

    // helper function to get session cookie as string
    private Cookie getSessionCookieActual(final Request request) {
        if (request.raw().getCookies() == null) {
            return null;
        }
        for (Cookie cookie : request.raw().getCookies()) {
            if (cookie.getName().equals("session")) {
                return cookie;
            }
        }
        return null;
    }

    // tags the tags string and put it into an array
    private ArrayList<String> extractTags(String tags) {

        tags = tags.replaceAll("\\s", "");
        String tagArray[] = tags.split(",");

        // let's clean it up, removing the empty string and removing dups
        ArrayList<String> cleaned = new ArrayList<String>();
        for (String tag : tagArray) {
            if (!tag.equals("") && !cleaned.contains(tag)) {
                cleaned.add(tag);
            }
        }

        return cleaned;
    }

    // validates that the registration form has been filled out right and username conforms
    public boolean validateSignup(String username, String password, String verify, String email,
            HashMap<String, String> errors) {
        String USER_RE = "^[a-zA-Z0-9_-]{3,20}$";
        String PASS_RE = "^.{3,20}$";
        String EMAIL_RE = "^[\\S]+@[\\S]+\\.[\\S]+$";

        errors.put("username_error", "");
        errors.put("password_error", "");
        errors.put("verify_error", "");
        errors.put("email_error", "");

        if (!username.matches(USER_RE)) {
            errors.put("username_error", "invalid username. try just letters and numbers");
            return false;
        }

        if (!password.matches(PASS_RE)) {
            errors.put("password_error", "invalid password.");
            return false;
        }

        if (!password.equals(verify)) {
            errors.put("verify_error", "password must match");
            return false;
        }

        return true;
    }

    private Configuration createFreemarkerConfiguration() {
        Configuration retVal = new Configuration();
        retVal.setClassForTemplateLoading(Controller.class, "/freemarker");
        return retVal;

        //End of method
    }
}