org.wise.portal.presentation.web.controllers.teacher.run.ShareProjectRunController.java Source code

Java tutorial

Introduction

Here is the source code for org.wise.portal.presentation.web.controllers.teacher.run.ShareProjectRunController.java

Source

/**
 * Copyright (c) 2008-2015 Regents of the University of California (Regents).
 * Created by WISE, Graduate School of Education, University of California, Berkeley.
 * 
 * This software is distributed under the GNU General Public License, v3,
 * or (at your option) any later version.
 * 
 * Permission is hereby granted, without written agreement and without license
 * or royalty fees, to use, copy, modify, and distribute this software and its
 * documentation for any purpose, provided that the above copyright notice and
 * the following two paragraphs appear in all copies of this software.
 * 
 * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
 * HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 * 
 * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 * REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.wise.portal.presentation.web.controllers.teacher.run;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.wise.portal.dao.ObjectNotFoundException;
import org.wise.portal.domain.authentication.impl.TeacherUserDetails;
import org.wise.portal.domain.impl.AddSharedTeacherParameters;
import org.wise.portal.domain.run.Run;
import org.wise.portal.domain.user.User;
import org.wise.portal.presentation.web.controllers.ControllerUtil;
import org.wise.portal.presentation.web.exception.NotAuthorizedException;
import org.wise.portal.service.acl.AclService;
import org.wise.portal.service.authentication.UserDetailsService;
import org.wise.portal.service.mail.IMailFacade;
import org.wise.portal.service.offering.RunService;
import org.wise.portal.service.user.UserService;
import org.wise.portal.service.workgroup.WorkgroupService;

/**
 * Controller for handling requests to grant/modify permissions on
 * Project runs.
 * 
 * @author Hiroki Terashima
 * @author Patrick Lawler
 * @author Matt Fishbach
 */
@Controller
@SessionAttributes("addSharedTeacherParameters")
@RequestMapping("/teacher/run/shareprojectrun.html")
public class ShareProjectRunController {

    @Autowired
    private RunService runService;

    @Autowired
    private WorkgroupService workgroupService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AclService<Run> aclService;

    @Autowired
    private IMailFacade mailService;

    @Autowired
    protected Properties wiseProperties;

    @Autowired
    private MessageSource messageSource;

    protected static final String RUNID_PARAM_NAME = "runId";

    protected static final String RUN_PARAM_NAME = "run";

    private static final String ALL_TEACHER_USERNAMES = "teacher_usernames";

    //the path to this form view
    private String formView = "teacher/run/shareprojectrun";

    //the path to the success view
    private String successView = "teacher/run/shareprojectrun";

    /* change this to true if you are testing and do not want to send mail to
       the actual groups */
    private static final Boolean DEBUG = false;

    //set this to your email
    private static final String DEBUG_EMAIL = "youremail@email.com";

    /**
     * Called before the page is loaded to initialize values.
    * Adds the AddSharedTeacherParameters object as a form-backing
    * object. This object will be filled out and submitted for adding
    * new teachers to the shared teachers list.
     * @param model the model object that contains values for the page to use when rendering the view
     * @param request the http request object
     * @return the path of the view to display
     */
    @RequestMapping(method = RequestMethod.GET)
    public String initializeForm(ModelMap modelMap, HttpServletRequest request) throws Exception {
        //get the signed in user
        User user = ControllerUtil.getSignedInUser();

        //get the run
        Run run = runService.retrieveById(Long.parseLong(request.getParameter(RUNID_PARAM_NAME)));

        //get the message if any
        String message = request.getParameter("message");

        //set the necessary objects into the model
        populateModel(modelMap, user, run, message);

        return formView;
    }

    /**
     * Set the run, teacher names, and shared owners into the model
     * @param modelMap the model to add the objects to
     * @param user the signed in user
     * @param run the run
     * @param message the message to display
     * @return the populated model map
     * @throws Exception
     */
    private Map<String, Object> populateModel(Map<String, Object> modelMap, User user, Run run, String message)
            throws Exception {
        //check if the user is an admin or is the owner of the run
        if (user.isAdmin() || this.aclService.hasPermission(run, BasePermission.ADMINISTRATION, user)) {
            //add the message if it is provided
            if (message != null) {
                modelMap.put("message", message);
            }
            //get all the teacher user names in WISE in alphabetical order
            List<String> allTeacherUsernames = userDetailsService.retrieveAllUsernames("TeacherUserDetails");

            //remove the owner from the user names
            allTeacherUsernames.remove(user.getUserDetails().getUsername());

            //get the shared owners of the run
            Set<User> sharedowners = run.getSharedowners();

            //loop through all the shared owners
            for (User sharedowner : sharedowners) {
                //get the permissions of the shared owner for the run
                String sharedTeacherRole = runService.getSharedTeacherRole(run, sharedowner);

                //get the user name of the shared owner
                String userName = sharedowner.getUserDetails().getUsername();

                //remove the shared owner from the user names
                allTeacherUsernames.remove(userName);

                //create the object that will contain the information for the shared owner
                AddSharedTeacherParameters addSharedTeacherParameters = new AddSharedTeacherParameters();
                addSharedTeacherParameters.setPermission(sharedTeacherRole);
                addSharedTeacherParameters.setRun(run);
                addSharedTeacherParameters.setSharedOwnerUsername(userName);

                //add the shared owner to the model
                modelMap.put(userName, addSharedTeacherParameters);
            }

            //add the run and run id to the model
            modelMap.put(RUN_PARAM_NAME, run);
            modelMap.put(RUNID_PARAM_NAME, run.getId());

            AlphabeticalStringComparator alphabeticalStringComparator = new AlphabeticalStringComparator();
            Collections.sort(allTeacherUsernames, alphabeticalStringComparator);
            String allTeacherUsernameString = StringUtils.join(allTeacherUsernames.iterator(), ":");

            //add all the teacher user names to the model
            modelMap.put(ALL_TEACHER_USERNAMES, allTeacherUsernameString);

            //create the params object and add it to the model
            AddSharedTeacherParameters params = new AddSharedTeacherParameters();
            params.setRun(run);
            params.setPermission(UserDetailsService.RUN_READ_ROLE);
            modelMap.put("addSharedTeacherParameters", params);
        } else {
            throw new NotAuthorizedException("You do not have permission to share this run.");
        }

        return modelMap;
    }

    /**
     * On submission of the AddSharedTeacherParameters, the specified
     * teacher is granted the specified permission to the specified run.
     * Only teachers can be added as a shared teacher to a run.
     * @param params the model object that contains values for the page to use when rendering the view
     * @param bindingResult the object used for validation in which errors will be stored
     * @param request the http request object
     * @param model the object that contains values to be displayed on the page
     * @param sessionStatus the session status object
     * @return the path of the view to display
     */
    @RequestMapping(method = RequestMethod.POST)
    protected String onSubmit(@ModelAttribute("addSharedTeacherParameters") AddSharedTeacherParameters params,
            BindingResult bindingResult, HttpServletRequest request, Model model, SessionStatus sessionStatus) {
        String view = formView;

        //get the signed in user
        User signedInUser = ControllerUtil.getSignedInUser();

        //get the run
        Run run = params.getRun();

        //get run id
        Long runId = run.getId();

        try {
            //get the run
            run = runService.retrieveById(runId);
            params.setRun(run);
        } catch (ObjectNotFoundException e1) {
            e1.printStackTrace();
        }

        //the error message to display to the user if any
        String message = null;

        //get the user that we will share the run with
        User retrievedUser = userService.retrieveUserByUsername(params.getSharedOwnerUsername());

        if (retrievedUser == null) {
            //we could not find the user name
            message = "Username not recognized. Make sure to use the exact spelling of the username.";
            view = formView;
        } else if (!retrievedUser.getUserDetails().hasGrantedAuthority(UserDetailsService.TEACHER_ROLE)) {
            //the user name entered is not a teacher
            message = "The user is not a teacher and thus cannot be added as a shared teacher.";
            view = formView;
        } else {
            try {
                // first check if we're removing a shared teacher
                String removeUserFromRun = request.getParameter("removeUserFromRun");
                if (removeUserFromRun != null && Boolean.valueOf(removeUserFromRun)) {
                    //remove the shared teacher
                    runService.removeSharedTeacherFromRun(params.getSharedOwnerUsername(), run.getId());
                } else {
                    // we're adding a new shared teacher or changing her permissions

                    if (run.getSharedowners().contains(retrievedUser)) {
                        //the user is already a shared owner so we will update their permissions
                        runService.updateSharedTeacherForRun(params);
                    } else {
                        //the user is not a shared owner yet so we will add them as a shared teacher

                        //add the shared teacher to the run
                        runService.addSharedTeacherToRun(params);

                        // make a workgroup for this shared teacher for this run
                        String sharedOwnerUsername = params.getSharedOwnerUsername();
                        User sharedOwner = userService.retrieveUserByUsername(sharedOwnerUsername);
                        Set<User> sharedOwners = new HashSet<User>();
                        sharedOwners.add(sharedOwner);
                        workgroupService.createWISEWorkgroup("teacher", sharedOwners, run, null);

                        //send an email to the new shared owner
                        Locale locale = request.getLocale();
                        ProjectRunEmailService emailService = new ProjectRunEmailService(signedInUser,
                                retrievedUser, run, locale);
                        Thread thread = new Thread(emailService);
                        thread.start();
                    }
                }
            } catch (ObjectNotFoundException e) {
                view = formView;
            }

            //sessionStatus.setComplete();
            view = successView;
        }

        //get the model as a map so we can add objects to it
        Map<String, Object> asMap = model.asMap();
        try {
            //add the project, teacher names, and shared owners into the model 
            populateModel(asMap, signedInUser, run, message);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }

    class ProjectRunEmailService implements Runnable {

        private User sharer;
        private User sharee;
        private Run run;
        private Locale locale;

        public ProjectRunEmailService(User sharer, User sharee, Run run, Locale locale) {
            this.sharer = sharer;
            this.sharee = sharee;
            this.run = run;
            this.locale = locale;
        }

        public void run() {
            this.sendEmail();
        }

        /**
          * Sends an email to individuals to notify them that the run has been shared
          * On exception sending the email, ignore.
          * @param sharee user that the run was shared with
          * @param run the run that was shared
          */
        private void sendEmail() {

            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMMMM d, yyyy");

            TeacherUserDetails sharerUserDetails = (TeacherUserDetails) sharer.getUserDetails();
            String sharerName = sharerUserDetails.getFirstname() + " " + sharerUserDetails.getLastname();
            String sharerEmailAddress = sharerUserDetails.getEmailAddress();

            TeacherUserDetails shareeDetails = (TeacherUserDetails) sharee.getUserDetails();

            String[] shareeEmailAddress = { shareeDetails.getEmailAddress() };

            String[] recipients = (String[]) ArrayUtils.addAll(shareeEmailAddress,
                    wiseProperties.getProperty("uber_admin").split(","));

            String defaultSubject = messageSource.getMessage(
                    "presentation.web.controllers.teacher.run.ShareProjectRunController.shareProjectRunConfirmationEmailSubject",
                    new Object[] { sharerName }, Locale.US);
            String subject = messageSource.getMessage(
                    "presentation.web.controllers.teacher.run.ShareProjectRunController.shareProjectRunConfirmationEmailSubject",
                    new Object[] { sharerName }, defaultSubject, this.locale);

            String defaultMessage = messageSource.getMessage(
                    "presentation.web.controllers.teacher.run.ShareProjectRunController.shareProjectRunConfirmationEmailBody",
                    new Object[] { sharerName }, Locale.US);
            String message = messageSource.getMessage(
                    "presentation.web.controllers.teacher.run.ShareProjectRunController.shareProjectRunConfirmationEmailBody",
                    new Object[] { sharerName, run.getName(), run.getId(), run.getProject().getName(),
                            run.getProject().getId(), shareeDetails.getUsername(), sdf.format(date) },
                    defaultMessage, this.locale);

            if (wiseProperties.containsKey("discourse_url")) {
                String discourseURL = wiseProperties.getProperty("discourse_url");
                if (discourseURL != null && !discourseURL.isEmpty()) {
                    // if this WISE instance uses discourse for teacher community, append link to it in the P.S. section of the email
                    String defaultPS = messageSource.getMessage("teacherEmailPSCommunity",
                            new Object[] { discourseURL }, Locale.US);
                    String pS = messageSource.getMessage("teacherEmailPSCommunity", new Object[] { discourseURL },
                            defaultPS, this.locale);
                    message += "\n\n" + pS;
                }
            }

            String fromEmail = sharerEmailAddress;

            //for testing out the email functionality without spamming the groups
            if (DEBUG) {
                recipients[0] = DEBUG_EMAIL;
            }

            //sends the email to the recipients
            try {
                mailService.postMail(recipients, subject, message, fromEmail);
            } catch (MessagingException e) {
                // do nothing, no notification to uber_admin required.
                e.printStackTrace();
            }
        }
    }

    /**
     * Comparator used to order strings alphabetically
     */
    public static class AlphabeticalStringComparator implements Comparator<String> {

        /**
         * Compares two strings
         * @param string1 a string
         * @param string2 a string
         * @return
         * -1 if string1 comes before string2
         * 0 if string1 is the same as string2
         * 1 if string1 comes after string2
         */
        @Override
        public int compare(String string1, String string2) {
            int result = 0;

            if (string1 != null && string2 != null) {
                String string1LowerCase = string1.toLowerCase();
                String string2LowerCase = string2.toLowerCase();
                result = string1LowerCase.compareTo(string2LowerCase);
            }

            return result;
        }
    }
}