csns.web.controller.SubmissionController.java Source code

Java tutorial

Introduction

Here is the source code for csns.web.controller.SubmissionController.java

Source

/*
 * This file is part of the CSNetwork Services (CSNS) project.
 * 
 * Copyright 2012-2014, Chengyu Sun (csun@calstatela.edu).
 * 
 * CSNS 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.
 * 
 * CSNS 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 CSNS. If not, see http://www.gnu.org/licenses/agpl.html.
 */
package csns.web.controller;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.ui.velocity.VelocityEngineUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
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.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile;

import csns.model.academics.Assignment;
import csns.model.academics.Enrollment;
import csns.model.academics.OnlineAssignment;
import csns.model.academics.OnlineSubmission;
import csns.model.academics.Submission;
import csns.model.academics.dao.AssignmentDao;
import csns.model.academics.dao.SubmissionDao;
import csns.model.core.File;
import csns.model.core.User;
import csns.model.core.dao.FileDao;
import csns.security.SecurityUtils;
import csns.util.FileIO;
import csns.web.editor.CalendarPropertyEditor;

@Controller
public class SubmissionController {

    @Autowired
    private FileDao fileDao;

    @Autowired
    private AssignmentDao assignmentDao;

    @Autowired
    private SubmissionDao submissionDao;

    @Autowired
    private FileIO fileIO;

    @Autowired
    private MailSender mailSender;

    @Autowired
    private VelocityEngine velocityEngine;

    @Value("#{applicationProperties.encoding}")
    private String appEncoding;

    private static final Logger logger = LoggerFactory.getLogger(SubmissionController.class);

    @InitBinder
    public void initBinder(WebDataBinder binder, WebRequest request) {
        binder.registerCustomEditor(Calendar.class, new CalendarPropertyEditor("MM/dd/yyyy HH:mm:ss"));
    }

    @RequestMapping(value = "/submission/view", params = "id")
    public String view1(@RequestParam Long id, ModelMap models) {
        models.put("submission", submissionDao.getSubmission(id));
        return "submission/view";
    }

    @RequestMapping(value = "/submission/view", params = "assignmentId")
    public String view2(@RequestParam Long assignmentId, ModelMap models) {
        User user = SecurityUtils.getUser();
        Assignment assignment = assignmentDao.getAssignment(assignmentId);
        Submission submission = submissionDao.getSubmission(user, assignment);
        if (submission == null)
            submission = submissionDao.saveSubmission(new Submission(user, assignment));

        models.put("submission", submission);
        return "submission/view";
    }

    @RequestMapping(value = "/submission/description")
    public String description(@RequestParam Long assignmentId, ModelMap models, HttpServletResponse response) {
        Assignment assignment = assignmentDao.getAssignment(assignmentId);
        if (!assignment.isPublished()) {
            models.put("message", "error.assignment.unpublished");
            return "error";
        }
        if (assignment.isPastDue() && !assignment.isAvailableAfterDueDate()) {
            models.put("message", "error.assignment.unavailable");
            return "error";
        }

        switch (assignment.getDescription().getType()) {
        case TEXT:
            models.put("assignment", assignment);
            return "submission/description";

        case FILE:
            fileIO.write(assignment.getDescription().getFile(), response);
            return null;

        case URL:
            return "redirect:" + assignment.getDescription().getUrl();

        default:
            logger.warn("Invalid resource type: " + assignment.getDescription().getType());
            models.put("message", "error.resource.type.invalid");
            return "error";
        }
    }

    @RequestMapping(value = "/submission/add", method = RequestMethod.GET)
    public String upload(@RequestParam Long id, ModelMap models) {
        models.put("submission", submissionDao.getSubmission(id));
        return "submission/add";
    }

    @RequestMapping(value = "/submission/upload", method = RequestMethod.POST)
    public String upload(@RequestParam Long id, @RequestParam boolean additional,
            @RequestParam MultipartFile uploadedFile, ModelMap models) {
        User user = SecurityUtils.getUser();
        Submission submission = submissionDao.getSubmission(id);
        boolean isInstructor = submission.getAssignment().getSection().isInstructor(user);
        String view = additional && isInstructor ? "/submission/add?id=" + id : "/submission/view?id=" + id;

        if (!isInstructor && submission.isPastDue()) {
            models.put("message", "error.assignment.pastdue");
            models.put("backUrl", view);
            return "error";
        }

        if (!uploadedFile.isEmpty()) {
            String fileName = uploadedFile.getOriginalFilename();
            if (!isInstructor
                    && !submission.getAssignment().isFileExtensionAllowed(File.getFileExtension(fileName))) {
                models.put("message", "error.assignment.file.type");
                models.put("backUrl", view);
                return "error";
            }

            File file = new File();
            file.setName(fileName);
            file.setType(uploadedFile.getContentType());
            file.setSize(uploadedFile.getSize());
            file.setDate(new Date());
            file.setOwner(submission.getStudent());
            file.setSubmission(submission);
            file = fileDao.saveFile(file);
            fileIO.save(file, uploadedFile);

            submission.incrementFileCount();
            submissionDao.saveSubmission(submission);

            logger.info(user.getUsername() + " uploaded file " + file.getId());
        }

        return "redirect:" + view;
    }

    @RequestMapping("/submission/remove")
    public @ResponseBody String remove(@RequestParam Long fileId) {
        User user = SecurityUtils.getUser();
        File file = fileDao.getFile(fileId);
        Submission submission = file.getSubmission();
        if (!submission.isPastDue() || submission.getAssignment().getSection().isInstructor(user)) {
            file.setSubmission(null);
            if (submission.getFiles().remove(file))
                submission.decrementFileCount();
            submissionDao.saveSubmission(submission);
        }

        logger.info(
                user.getUsername() + " removed file " + file.getId() + " from submission " + submission.getId());

        return "";
    }

    @RequestMapping("/submission/list")
    public String list(@RequestParam Long assignmentId, ModelMap models) {
        Assignment assignment = assignmentDao.getAssignment(assignmentId);

        Set<User> students = new HashSet<User>();
        for (Enrollment enrollment : assignment.getSection().getEnrollments())
            students.add(enrollment.getStudent());

        // we need to remove the submissions from the students who already
        // dropped the class
        Iterator<Submission> i = assignment.getSubmissions().iterator();
        while (i.hasNext()) {
            Submission submission = i.next();
            if (!students.contains(submission.getStudent()))
                i.remove();
            else
                students.remove(submission.getStudent());
        }

        // we then add a submission for each student who is in the class but
        // didn't have a submission for this assignment.
        for (User student : students) {
            Submission submission = assignment.isOnline()
                    ? new OnlineSubmission(student, (OnlineAssignment) assignment)
                    : new Submission(student, assignment);
            assignment.getSubmissions().add(submission);
        }
        assignment = assignmentDao.saveAssignment(assignment);

        models.put("assignment", assignment);
        return "submission/list";
    }

    @RequestMapping("/submission/grade")
    public String grade(@RequestParam Long id, ModelMap models) {
        models.put("submission", submissionDao.getSubmission(id));
        return "submission/grade";
    }

    @RequestMapping(value = "/submission/edit", params = "dueDate")
    public String editDueDate(@RequestParam Long id, @RequestParam Calendar dueDate) {
        Submission submission = submissionDao.getSubmission(id);
        submission.setDueDate(dueDate);
        submissionDao.saveSubmission(submission);

        return submission.isOnline() ? "redirect:/submission/online/grade?id=" + id
                : "redirect:/submission/grade?id=" + id;
    }

    @RequestMapping(value = "/submission/edit", params = "grade")
    public String editGrade(@RequestParam Long id, @RequestParam String grade, HttpServletResponse response)
            throws IOException {
        grade = grade.trim();
        Submission submission = submissionDao.getSubmission(id);
        String oldGrade = submission.getGrade();
        if (oldGrade == null || !oldGrade.equals(grade)) {
            submission.setGrade(grade);
            submission.setGradeMailed(false);
            submissionDao.saveSubmission(submission);
        }

        response.setContentType("text/plain");
        response.getWriter().print(submission.getGrade());
        return null;
    }

    @RequestMapping(value = "/submission/edit", params = "comments")
    public String editComments(@RequestParam Long id, @RequestParam String comments, HttpServletResponse response)
            throws IOException {
        Submission submission = submissionDao.getSubmission(id);
        submission.setComments(comments);
        submissionDao.saveSubmission(submission);

        response.setContentType("text/plain");
        response.getWriter().print(submission.getComments());
        return null;
    }

    private void emailGrade(Submission submission) {
        if (!StringUtils.hasText(submission.getGrade()) || submission.isGradeMailed())
            return;

        User instructor = SecurityUtils.getUser();
        User student = submission.getStudent();

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(instructor.getEmail());
        message.setTo(student.getEmail());

        String subject = submission.getAssignment().getSection().getCourse().getCode() + " "
                + submission.getAssignment().getName() + " Grade";
        message.setSubject(subject);

        Map<String, Object> vModels = new HashMap<String, Object>();
        vModels.put("grade", submission.getGrade());
        String comments = submission.getComments();
        vModels.put("comments", comments != null ? comments : "");
        String text = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "email.submission.grade.vm",
                appEncoding, vModels);
        message.setText(text);

        try {
            mailSender.send(message);
            submission.setGradeMailed(true);
            submissionDao.saveSubmission(submission);
            logger.info(instructor.getUsername() + " sent grade to " + student.getEmail());
        } catch (MailException e) {
            logger.warn(instructor.getUsername() + " failed to send grade to " + student.getEmail());
            logger.debug(e.getMessage());
        }
    }

    @RequestMapping(value = "/submission/email", params = "submissionId")
    public String emailGrade(@RequestParam Long submissionId) {
        Submission submission = submissionDao.getSubmission(submissionId);
        emailGrade(submission);
        return submission.isOnline() ? "redirect:/submission/online/grade?id=" + submissionId
                : "redirect:/submission/grade?id=" + submissionId;
    }

    @RequestMapping(value = "/submission/email", params = "assignmentId")
    public String emailGrades(@RequestParam Long assignmentId) {
        Assignment assignment = assignmentDao.getAssignment(assignmentId);
        for (Submission submission : assignment.getSubmissions())
            emailGrade(submission);
        return "redirect:/submission/list?assignmentId=" + assignmentId;
    }

}