com.jd.survey.web.settings.InvitationController.java Source code

Java tutorial

Introduction

Here is the source code for com.jd.survey.web.settings.InvitationController.java

Source

/*Copyright (C) 2014  JD Software, Inc.
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.jd.survey.web.settings;

import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import au.com.bytecode.opencsv.CSVReader;

import com.jd.survey.domain.security.User;
import com.jd.survey.domain.settings.Invitation;
import com.jd.survey.domain.settings.SurveyDefinition;
import com.jd.survey.service.security.SecurityService;
import com.jd.survey.service.security.UserService;
import com.jd.survey.service.settings.SurveySettingsService;

@RequestMapping("/settings/invitations")
@Controller
public class InvitationController {
    private static final Log log = LogFactory.getLog(InvitationController.class);
    @Autowired
    private MessageSource messageSource;
    @Autowired
    private UserService userService;
    @Autowired
    private SurveySettingsService surveySettingsService;
    @Autowired
    private SecurityService securityService;

    private static final String FIRST_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.firstname_label";
    private static final String MIDDLE_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.middlename_label";
    private static final String LAST_NAME_MESSAGE = "com.jd.survey.domain.settings.invitation.lastname_label";
    private static final String EMAIL_MESSAGE = "com.jd.survey.domain.settings.invitation.email_label";

    private static final String INVITATION_EMAIL_TITLE = "invitation_email_title";

    private static final String INVITEE_FULLNAME_PARAMETER_NAME = "invitee_fullname_parameter_name";
    private static final String SURVEY_NAME = "survey_name";

    private static final String INVITE_FILL_SURVEY_LINK_PARAMETER_NAME = "invite_fill_survey_link_parameter_name";
    private static final String INVITE_FILL_SURVEY_LINK_LABEL = "invite_fill_survey_link_label";

    //private static final String INTERNAL_SITE_BASE_URL="internal_site_base_url";
    //private static final String EXTERNAL_SITE_BASE_URL="external_site_base_url";
    @Value("${external.base.url}")
    String externalBaseUrl;
    @Value("${internal.base.url}")
    String internalBaseUrl;

    /**
     *  exports a sample invitations comma delimited file
     * @param dataSetId
     * @param principal
     * @param response
     */
    @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" })
    @RequestMapping(value = "/example", produces = "text/html")
    public void getExampleCsvFile(Principal principal, HttpServletResponse response) {
        try {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(messageSource.getMessage(FIRST_NAME_MESSAGE, null, LocaleContextHolder.getLocale())
                    .replace(",", ""));
            stringBuilder.append(",");
            stringBuilder.append(messageSource
                    .getMessage(MIDDLE_NAME_MESSAGE, null, LocaleContextHolder.getLocale()).replace(",", ""));
            stringBuilder.append(",");
            stringBuilder.append(messageSource.getMessage(LAST_NAME_MESSAGE, null, LocaleContextHolder.getLocale())
                    .replace(",", ""));
            stringBuilder.append(",");
            stringBuilder.append(messageSource.getMessage(EMAIL_MESSAGE, null, LocaleContextHolder.getLocale())
                    .replace(",", ""));
            stringBuilder.append("\n");
            stringBuilder.append("a,b,c,abc@jdsoft.com\n");
            //response.setContentType("text/html; charset=utf-8");
            response.setContentType("application/octet-stream");
            // Set standard HTTP/1.1 no-cache headers.
            response.setHeader("Cache-Control", "no-store, no-cache,must-revalidate");
            // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            // Set standard HTTP/1.0 no-cache header.
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Content-Disposition", "inline;filename=Invitationsexample.csv");
            ServletOutputStream servletOutputStream = response.getOutputStream();
            servletOutputStream.write(stringBuilder.toString().getBytes("UTF-8"));
            servletOutputStream.flush();

        }

        catch (Exception e) {
            log.error(e.getMessage(), e);
            throw (new RuntimeException(e));
        }
    }

    /**
     * Shows a list of completed Survey Definitions for the user 
     * @param surveyId
     * @param principal
     * @param uiModel
     * @param httpServletRequest
     * @return
     */
    @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" })
    @RequestMapping(produces = "text/html", method = RequestMethod.GET)
    public String listSurveys(Model uiModel, Principal principal) {

        try {
            User user = userService.user_findByLogin(principal.getName());
            Set<SurveyDefinition> surveyDefinitions = surveySettingsService
                    .surveyDefinition_findAllCompletedInternal(user);
            uiModel.addAttribute("surveyDefinitions", surveyDefinitions);
            return "settings/invitations/invitations";
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw (new RuntimeException(e));
        }
    }

    /**
     * Shows the list of Survey Invitations for a Survey Definition, Supports Paging 
     * @param surveyId
     * @param principal
     * @param uiModel
     * @param httpServletRequest
     * @return
     */
    @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" })
    @RequestMapping(value = "/list", produces = "text/html", method = RequestMethod.GET)
    public String listSurveyInvitations(@RequestParam(value = "id", required = true) Long surveyDefinitionId,
            @RequestParam(value = "page", required = false) Integer page,
            @RequestParam(value = "size", required = false) Integer size,
            @RequestParam(value = "fileContentError", required = false) boolean contentError, Model uiModel,
            Principal principal, HttpServletRequest httpServletRequest) {

        try {
            User user = userService.user_findByLogin(principal.getName());

            if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) {
                log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo()
                        + " attempted by user login:" + principal.getName() + "from IP:"
                        + httpServletRequest.getLocalAddr());
                return "accessDenied";
            }
            Set<SurveyDefinition> surveyDefinitions = surveySettingsService
                    .surveyDefinition_findAllCompletedInternal(user);
            uiModel.addAttribute("surveyDefinitions", surveyDefinitions);
            uiModel.addAttribute("surveyDefinition",
                    surveySettingsService.surveyDefinition_findById(surveyDefinitionId));
            Long surveyInvitationsCount = surveySettingsService.invitation_getSurveyCount(surveyDefinitionId);
            uiModel.addAttribute("surveyInvitationsCount", surveyInvitationsCount);
            uiModel.addAttribute("surveyInvitationsOpenedCount",
                    surveySettingsService.invitation_getSurveyOpenedCount(surveyDefinitionId));

            int sizeNo = size == null ? 25 : size.intValue();
            final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
            Set<Invitation> invitations = surveySettingsService.invitation_findSurveyAll(surveyDefinitionId,
                    firstResult, sizeNo);
            float nrOfPages = (float) surveyInvitationsCount / sizeNo;
            int maxPages = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
            uiModel.addAttribute("maxPages", maxPages);
            uiModel.addAttribute("invitations", invitations);
            uiModel.addAttribute("fileContentError", contentError);// Used to carry error from file upload over and make it available to the view
            return "settings/invitations/invitations";
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw (new RuntimeException(e));
        }
    }

    /**
     * prepares the page to import invitations from a csv file       
     * @param dataSetId
     * @param principal
     * @param uiModel
     * @param httpServletRequest
     * @return
     */
    @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" })
    @RequestMapping(value = "/import", produces = "text/html")
    public String prepareForImport(@RequestParam(value = "id", required = false) Long surveyDefinitionId,
            Principal principal, Model uiModel, HttpServletRequest httpServletRequest) {
        try {
            User user = userService.user_findByLogin(principal.getName());
            Set<SurveyDefinition> surveyDefinitions = surveySettingsService
                    .surveyDefinition_findAllCompletedInternal(user);
            uiModel.addAttribute("surveyDefinitions", surveyDefinitions);
            if (surveyDefinitionId != null) {
                if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) {
                    log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo()
                            + " attempted by user login:" + principal.getName() + "from IP:"
                            + httpServletRequest.getLocalAddr());
                    return "accessDenied";
                }
                uiModel.addAttribute("surveyDefinition",
                        surveySettingsService.surveyDefinition_findById(surveyDefinitionId));
            }
            return "settings/invitations/upload";
        }

        catch (Exception e) {
            log.error(e.getMessage(), e);
            throw (new RuntimeException(e));
        }
    }

    /**
     * Sends email invitations to the list of invitees from csv file.  
     * @param file
     * @param surveyDefinitionId
     * @param proceed
     * @param principal
     * @param uiModel
     * @param httpServletRequest
     * @return
     */
    @SuppressWarnings("unchecked")
    @Secured({ "ROLE_ADMIN", "ROLE_SURVEY_ADMIN" })
    @RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html")
    public String sendInvitations(@RequestParam("file") MultipartFile file,
            @RequestParam("id") Long surveyDefinitionId,
            @RequestParam(value = "_proceed", required = false) String proceed, Principal principal, Model uiModel,
            HttpServletRequest httpServletRequest) {
        try {
            short firstNameFieldIndex = 0;
            short middleNameFieldIndex = 1;
            short lastNameFieldIndex = 2;
            short emailNameFieldIndex = 3;

            if (proceed != null) {
                //prepare the base url links
                String emailSubject = messageSource.getMessage(INVITATION_EMAIL_TITLE, null,
                        LocaleContextHolder.getLocale());
                //String surveyLink =messageSource.getMessage(EXTERNAL_SITE_BASE_URL, null, LocaleContextHolder.getLocale());
                String surveyLink = externalBaseUrl;
                //String trackingImageLink =messageSource.getMessage(INTERNAL_SITE_BASE_URL, null, LocaleContextHolder.getLocale());
                String trackingImageLink = internalBaseUrl;

                SurveyDefinition surveyDefinition = surveySettingsService
                        .surveyDefinition_findById(surveyDefinitionId);

                User user = userService.user_findByLogin(principal.getName());
                Set<SurveyDefinition> surveyDefinitions = surveySettingsService
                        .surveyDefinition_findAllCompletedInternal(user);
                //Check if the user is authorized
                if (!securityService.userIsAuthorizedToManageSurvey(surveyDefinitionId, user)) {
                    log.warn("Unauthorized access to url path " + httpServletRequest.getPathInfo()
                            + " attempted by user login:" + principal.getName() + "from IP:"
                            + httpServletRequest.getLocalAddr());
                    return "accessDenied";
                }

                if (trackingImageLink.endsWith("/")) {
                    trackingImageLink = trackingImageLink + "public/w/";
                } else {
                    trackingImageLink = trackingImageLink + "/public/w/";
                }

                if (surveyDefinition.getIsPublic()) {
                    if (surveyLink.endsWith("/")) {
                        surveyLink = surveyLink + "open/";
                    } else {
                        surveyLink = surveyLink + "/open/";
                    }
                } else {
                    if (surveyLink.endsWith("/")) {
                        surveyLink = surveyLink + "private/";
                    } else {
                        surveyLink = surveyLink + "/private/";
                    }
                }

                String emailContent;

                if (!file.isEmpty() && ((file.getContentType().equalsIgnoreCase("application/vnd.ms-excel"))
                        || (file.getContentType().equalsIgnoreCase("text/csv"))
                        || (file.getContentType().equalsIgnoreCase("text/plain")))) {
                    CSVReader csvReader = new CSVReader(new InputStreamReader(file.getInputStream()));
                    String[] nextLine;
                    nextLine = csvReader.readNext(); //skip the first row the continue on with loop

                    while ((nextLine = csvReader.readNext()) != null) {
                        emailContent = "";
                        StringWriter sw = new StringWriter();

                        // Prevents IndexOutOfBoundException by skipping line if there are not enough elements in the array nextLine. 
                        if (nextLine.length < 4) {
                            //Continues if a blank line is present without setting an error message (if a new line character is present CSVReader will return and array with one empty string at index 0).
                            if (nextLine.length == 1 && nextLine[0].isEmpty()) {
                                continue;
                            }
                            uiModel.addAttribute("fileContentError", true);
                            continue;
                        }
                        //Prevents exception from attempting to send an email with an empty string for an email address.
                        if (nextLine[3].isEmpty()) {
                            uiModel.addAttribute("fileContentError", true);
                            continue;
                        }
                        //creating the Invitation
                        Invitation invitation = new Invitation(nextLine[firstNameFieldIndex].trim(),
                                nextLine[middleNameFieldIndex].trim(), nextLine[lastNameFieldIndex].trim(),
                                nextLine[emailNameFieldIndex].trim(), surveyDefinition);

                        Map model = new HashMap();
                        //survey name
                        model.put(messageSource.getMessage(SURVEY_NAME, null, LocaleContextHolder.getLocale())
                                .replace("${", "").replace("}", ""), surveyDefinition.getName());
                        //full name
                        model.put(
                                messageSource.getMessage(INVITEE_FULLNAME_PARAMETER_NAME, null,
                                        LocaleContextHolder.getLocale()).replace("${", "").replace("}", ""),
                                invitation.getFullName());
                        //survey link
                        model.put(
                                messageSource.getMessage(INVITE_FILL_SURVEY_LINK_PARAMETER_NAME, null,
                                        LocaleContextHolder.getLocale()).replace("${", "").replace("}", ""),
                                "<a href='" + surveyLink + surveyDefinition.getId() + "?list'>"
                                        + messageSource.getMessage(INVITE_FILL_SURVEY_LINK_LABEL, null,
                                                LocaleContextHolder.getLocale())
                                        + "</a>");

                        VelocityContext velocityContext = new VelocityContext(model);
                        Velocity.evaluate(velocityContext, sw, "velocity-log",
                                surveyDefinition.getEmailInvitationTemplate());
                        emailContent = sw.toString().trim();

                        if (emailContent.length() > 14 && emailContent.substring(emailContent.length() - 14)
                                .toUpperCase().equalsIgnoreCase("</BODY></HTML>")) {
                            emailContent = emailContent.substring(0, emailContent.length() - 14) + "<img src='"
                                    + trackingImageLink + invitation.getUuid() + "'/></BODY></HTML>";
                            emailContent = "<BODY><HTML>" + emailContent;
                        } else {
                            // template is incorrect or not html do not include tracking white gif
                            emailContent = emailContent + "<img src='" + trackingImageLink + invitation.getUuid()
                                    + "'/></BODY></HTML>";

                        }

                        surveySettingsService.invitation_send(invitation, emailSubject, emailContent);
                    }

                    return "redirect:/settings/invitations/list?id="
                            + encodeUrlPathSegment(surveyDefinitionId.toString(), httpServletRequest);
                } else {
                    uiModel.addAttribute("surveyDefinitions", surveyDefinitions);
                    uiModel.addAttribute("surveyDefinition", surveyDefinition);
                    uiModel.addAttribute("emptyFileError", true);
                    return "settings/invitations/upload";
                }
            } else {
                return "redirect:/settings/invitations/list?id="
                        + encodeUrlPathSegment(surveyDefinitionId.toString(), httpServletRequest);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
        log.info("encodeUrlPathSegment()");
        try {
            String enc = httpServletRequest.getCharacterEncoding();
            if (enc == null) {
                enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
            }
            try {
                pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
            } catch (UnsupportedEncodingException uee) {
                log.error(uee);
            }
            return pathSegment;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw (new RuntimeException(e));
        }
    }

    @ExceptionHandler(RuntimeException.class)
    public String handleRuntimeException(RuntimeException ex, HttpServletRequest request) {
        log.error(ex);
        log.error("redirect to /uncaughtException");
        return "redirect:/uncaughtException";
    }

}