edu.duke.cabig.c3pr.web.admin.CreateNotificationController.java Source code

Java tutorial

Introduction

Here is the source code for edu.duke.cabig.c3pr.web.admin.CreateNotificationController.java

Source

/*******************************************************************************
 * Copyright Duke Comprehensive Cancer Center and SemanticBits
 * 
 * Distributed under the OSI-approved BSD 3-Clause License.
 * See http://ncip.github.com/c3pr/LICENSE.txt for details.
 ******************************************************************************/
package edu.duke.cabig.c3pr.web.admin;

import java.io.PrintWriter;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.web.util.WebUtils;

import edu.duke.cabig.c3pr.constants.ContactMechanismType;
import edu.duke.cabig.c3pr.constants.NotificationEventTypeEnum;
import edu.duke.cabig.c3pr.constants.NotificationFrequencyEnum;
import edu.duke.cabig.c3pr.dao.HealthcareSiteDao;
import edu.duke.cabig.c3pr.dao.InvestigatorDao;
import edu.duke.cabig.c3pr.dao.PersonUserDao;
import edu.duke.cabig.c3pr.dao.PlannedNotificationDao;
import edu.duke.cabig.c3pr.dao.UserDao;
import edu.duke.cabig.c3pr.domain.ContactMechanism;
import edu.duke.cabig.c3pr.domain.ContactMechanismBasedRecipient;
import edu.duke.cabig.c3pr.domain.HealthcareSite;
import edu.duke.cabig.c3pr.domain.Investigator;
import edu.duke.cabig.c3pr.domain.PersonUser;
import edu.duke.cabig.c3pr.domain.PlannedNotification;
import edu.duke.cabig.c3pr.domain.UserBasedRecipient;
import edu.duke.cabig.c3pr.domain.repository.impl.CSMUserRepositoryImpl.C3PRNoSuchUserException;
import edu.duke.cabig.c3pr.domain.scheduler.runtime.job.ScheduledNotificationJob;
import edu.duke.cabig.c3pr.service.OrganizationService;
import edu.duke.cabig.c3pr.tools.Configuration;
import edu.duke.cabig.c3pr.utils.ConfigurationProperty;
import edu.duke.cabig.c3pr.utils.StringUtils;
import edu.duke.cabig.c3pr.utils.web.propertyeditors.CustomDaoEditor;
import edu.duke.cabig.c3pr.utils.web.propertyeditors.EnumByNameEditor;
import edu.duke.cabig.c3pr.utils.web.spring.tabbedflow.InPlaceEditableTab;

/*
 * @author Vinay Gangoli
 * 
 * This controller persists the created Notification to the planned_notfns table.
 * called from the admin/createNotification flow.
 * Uses the Organization as the mapped hibernate object for persistence.
 */
public class CreateNotificationController extends SimpleFormController {

    private static Log log = LogFactory.getLog(CreateNotificationController.class);

    private HealthcareSiteDao healthcareSiteDao;
    private PersonUserDao personUserDao;
    private InvestigatorDao investigatorDao;
    private PlannedNotificationDao plannedNotificationDao;

    private OrganizationService organizationService;

    private ConfigurationProperty configurationProperty;

    private Configuration configuration;

    private UserDao userDao;

    private InPlaceEditableTab<NotificationWrapper> page;

    //constants for the Cron Triggers
    public static final String WEEKLY = "0 00 12 ? * FRI";
    public static final String MONTHLY = "0 0 12 L * ?";
    public static final String ANNUAL = "0 0 12 L DEC ?";

    public static final Long REPEAT_INTERVAL_IN_MILLI_SECONDS = 10 * 60 * 1000L;
    public static final Integer REPEAT_COUNT = 3;

    //job related declarations
    private Scheduler scheduler;

    protected Object formBackingObject(HttpServletRequest request) throws Exception {
        NotificationWrapper wrapper = new NotificationWrapper();
        gov.nih.nci.security.authorization.domainobjects.User user = (gov.nih.nci.security.authorization.domainobjects.User) request
                .getSession().getAttribute("userObject");
        try {
            if (WebUtils.hasSubmitParameter(request, "organization")) {
                HealthcareSite healthcareSite = healthcareSiteDao
                        .getById(Integer.parseInt(request.getParameter("organization")));
                wrapper.setHealthcareSite(healthcareSite);
            } else {
                //get the logged in users site.If the logged in user is not yet associated to a site then get the hosting site.
                PersonUser personUser = (PersonUser) userDao.getByLoginId(user.getUserId().longValue());
                if (personUser.getHealthcareSites().size() > 0) {
                    wrapper.setHealthcareSite(personUser.getHealthcareSites().get(0));
                } else {
                    log.debug(
                            "Logged in User is not associated to a site, so getting the hosting site organization");
                    String localNciCode = this.configuration.get(Configuration.LOCAL_NCI_INSTITUTE_CODE);
                    HealthcareSite hcs = healthcareSiteDao.getByPrimaryIdentifier(localNciCode);
                    wrapper.setHealthcareSite(hcs);
                }
            }
        } catch (C3PRNoSuchUserException e) {
            log.debug(e.getMessage());
            //if logged in user has no site(in future) get the hosting site.
            String localNciCode = this.configuration.get(Configuration.LOCAL_NCI_INSTITUTE_CODE);
            HealthcareSite hcs = healthcareSiteDao.getByPrimaryIdentifier(localNciCode);
            wrapper.setHealthcareSite(hcs);
        }
        return wrapper;
    }

    protected Map referenceData(HttpServletRequest request, Object command, Errors errors) throws Exception {
        Map<String, Object> configMap = configurationProperty.getMap();
        Map<String, Object> refdata = new HashMap<String, Object>();
        refdata.put("notificationEventsRefData", configMap.get("notificationEventsRefData"));
        refdata.put("notificationFrequencyRefData", configMap.get("notificationFrequencyRefData"));
        refdata.put("notificationPersonnelRoleRefData", configMap.get("notificationPersonnelRoleRefData"));
        refdata.put("notificationEmailSubstitutionVariablesRefData",
                configMap.get("notificationEmailSubstitutionVariablesRefData"));
        refdata.put("notificationStudyAccrualRefData", configMap.get("notificationStudyAccrualRefData"));
        refdata.put("notificationStudySiteAccrualRefData", configMap.get("notificationStudySiteAccrualRefData"));
        refdata.put("notificationReportEventsRefData", configMap.get("notificationReportEventsRefData"));
        gov.nih.nci.security.authorization.domainobjects.User user = (gov.nih.nci.security.authorization.domainobjects.User) request
                .getSession().getAttribute("userObject");
        PersonUser personUser = (PersonUser) userDao.getByLoginId(user.getUserId().longValue());
        refdata.put("assignedIdentifier", personUser.getAssignedIdentifier());
        return refdata;
    }

    @Override
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        super.initBinder(request, binder);
        binder.registerCustomEditor(NotificationEventTypeEnum.class,
                new EnumByNameEditor(NotificationEventTypeEnum.class));
        binder.registerCustomEditor(HealthcareSite.class, new CustomDaoEditor(healthcareSiteDao));
        binder.registerCustomEditor(PersonUser.class, new CustomDaoEditor(personUserDao));
    }

    /*
     * This is the method that gets called on form submission. All it does it cast the command into
     * Organization and call the service to persist.
     * On successful submission it sets the type attribute to confirm which is used to show the
     * confirmation screen.
     */
    protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response,
            Object command, BindException errors) throws Exception {

        //       gov.nih.nci.security.authorization.domainobjects.User user = (gov.nih.nci.security.authorization.domainobjects.User) request
        //                                                      .getSession().getAttribute("userObject");
        //       PersonUser personUser = null;
        NotificationWrapper notificationWrapper = (NotificationWrapper) command;
        HealthcareSite healthcareSite = notificationWrapper.getHealthcareSite();
        if (isAjaxRequest(request)) {
            request.getParameter("_asynchronous");
            ModelAndView modelAndView = page.postProcessAsynchronous(request, (NotificationWrapper) command,
                    errors);
            if (healthcareSite.getId() != null) {
                notificationWrapper.setHealthcareSite((HealthcareSite) organizationService
                        .merge(((NotificationWrapper) command).getHealthcareSite()));
                command = notificationWrapper;
            } else {
                organizationService.saveNotification(((NotificationWrapper) command).getHealthcareSite());
            }
            request.getSession().setAttribute(getFormSessionAttributeName(), command);
            if (isAjaxResponseFreeText(modelAndView)) {
                respondAjaxFreeText(modelAndView, response);
                return null;
            }
            return modelAndView;
        } else {

            //assign the Rs or Inv to the userBasedRecpients
            PersonUser rs = null;
            Investigator investigator = null;
            Trigger trigger = null;

            PlannedNotification pn = null;
            HealthcareSite hcs = null;

            for (int i = 0; i < healthcareSite.getPlannedNotifications().size(); i++) {
                pn = healthcareSite.getPlannedNotifications().get(i);
                if (pn.getHealthcareSite() == null && hcs != null) {
                    pn.setHealthcareSite(hcs);
                }
                //set the freq to Immediate as default. It is null sometimes when the select is manipulated by the javascript.
                //fix this so the javascript manipulation doesnt nullify the freq value.
                if (pn.getFrequency() == null) {
                    pn.setFrequency(NotificationFrequencyEnum.IMMEDIATE);
                }

                //set the contactMechnism Type for the contactMechanismBasedRecipient Emails 
                if (pn.getContactMechanismBasedRecipient() != null) {
                    for (ContactMechanismBasedRecipient cmbr : pn.getContactMechanismBasedRecipient()) {
                        for (ContactMechanism cm : cmbr.getContactMechanisms()) {
                            if (cm != null && cm.getValue() != null) {
                                cm.setType(ContactMechanismType.EMAIL);
                            }
                        }
                    }
                }

                for (UserBasedRecipient ubr : pn.getUserBasedRecipient()) {
                    if (!StringUtils.isBlank(ubr.getEmailAddress())) {
                        //TODO: This method is removed from researchstaff dao. Check CPR-1570.
                        //rs = personUserDao.getByEmailAddressFromLocal(ubr.getEmailAddress());

                        //TODO: This method is removed from investigator dao. Check CPR-1568. 
                        //investigator = investigatorDao.getByEmailAddressFromLocal(ubr.getEmailAddress());
                    }
                    if (rs != null) {
                        ubr.setPersonUser(rs);
                    } else if (investigator != null) {
                        ubr.setInvestigator(investigator);
                    }
                }

                if (pn.getFrequency() != NotificationFrequencyEnum.IMMEDIATE && pn.getId() == null) {
                    //generate the cron Triggers and jobs for Report based events if the pn is new.

                    plannedNotificationDao.saveOrUpdate(pn);
                    trigger = generateTriggerForReportBasedEvents(pn);
                    scheduleJobsForReportBasedEvents(pn, trigger);
                } else {
                    //do not create triggers/jobs if the pn was pre-existing
                    plannedNotificationDao.saveOrUpdate(pn);
                }
            }

            Map<String, Object> map = errors.getModel();
            map.put("command", notificationWrapper);
            ModelAndView mv = new ModelAndView(getSuccessView(), map);
            return mv;
        }

    }

    /*   Create the Cron Triggers for (non-event based)report notifications.
     */
    private Trigger generateTriggerForReportBasedEvents(PlannedNotification pn) {
        Trigger t = null;
        try {
            if (pn.getFrequency().equals(NotificationFrequencyEnum.WEEKLY)) {
                //all ids are of the form  "TW:Event-Freq-id:"
                //every Friday at 12:00pm
                t = new CronTrigger("TW: " + getUniqueIdForTrigger(pn), "TGW" + getUniqueIdForTrigger(pn), WEEKLY);
            }
            if (pn.getFrequency().equals(NotificationFrequencyEnum.MONTHLY)) {
                //every last day of month at 12:00pm
                t = new CronTrigger("TM" + getUniqueIdForTrigger(pn), "TGM" + getUniqueIdForTrigger(pn), MONTHLY);
            }
            if (pn.getFrequency().equals(NotificationFrequencyEnum.ANNUAL)) {
                //every last day December at 12:00pm
                t = new CronTrigger("TA" + getUniqueIdForTrigger(pn), "TGA" + getUniqueIdForTrigger(pn), ANNUAL);
            }
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return t;
    }

    /*
     * Generates the unique key for Trigger based on plannedNotification Object
     */
    private String getUniqueIdForTrigger(PlannedNotification pn) {
        return pn.getEventName().getDisplayName() + "-" + pn.getFrequency().getDisplayName() + "-"
                + pn.getId().toString();
    }

    private void scheduleJobsForReportBasedEvents(PlannedNotification pn, Trigger trigger) {
        // create job detail and set the map values
        String jobName = "J:" + pn.getEventName().getDisplayName() + "-" + pn.getFrequency().getDisplayName() + "-"
                + pn.getId().toString();
        String jobGroupName = "JG:" + pn.getEventName().getDisplayName() + "-" + pn.getFrequency().getDisplayName()
                + "-" + pn.getId().toString();
        JobDetail jobDetail = new JobDetail(jobName, jobGroupName, ScheduledNotificationJob.class);

        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        jobDataMap.put("plannedNotificationId", pn.getId());

        // schedule the jobs
        log.info("Scheduling the job (jobFullName : " + jobDetail.getFullName() + ")");
        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            log.error(e.getMessage());
        }
    }

    public OrganizationService getOrganizationService() {
        return organizationService;
    }

    public void setOrganizationService(OrganizationService organizationService) {
        this.organizationService = organizationService;
    }

    public ConfigurationProperty getConfigurationProperty() {
        return configurationProperty;
    }

    public void setConfigurationProperty(ConfigurationProperty configurationProperty) {
        this.configurationProperty = configurationProperty;
    }

    public Configuration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }

    public InPlaceEditableTab<NotificationWrapper> getPage() {
        return page;
    }

    public void setPage(InPlaceEditableTab<NotificationWrapper> page) {
        this.page = page;
    }

    protected ModelAndView onSynchronousSubmit(HttpServletRequest request, HttpServletResponse response,
            Object command, BindException errors) throws Exception {
        if (getSuccessView() == null) {
            throw new ServletException("successView isn't set");
        }
        return new ModelAndView(getSuccessView(), errors.getModel());
    }

    protected boolean isAjaxRequest(HttpServletRequest request) {
        if ("true".equalsIgnoreCase(request.getParameter(getAjaxRequestParamName()))) {
            return true;
        }
        return false;
    }

    protected void setAjaxModelAndView(HttpServletRequest request, ModelAndView modelAndView) {
        request.setAttribute(getAjaxModelAndViewAttr(), modelAndView);
    }

    protected ModelAndView getAjaxModelAndView(HttpServletRequest request) {
        return (ModelAndView) request.getAttribute(getAjaxModelAndViewAttr());
    }

    protected boolean isAjaxResponseFreeText(ModelAndView modelAndView) {
        if (StringUtils.isBlank(modelAndView.getViewName())) {
            return true;
        }
        return false;
    }

    protected void respondAjaxFreeText(ModelAndView modelAndView, HttpServletResponse response) throws Exception {
        PrintWriter pr = response.getWriter();
        pr.println(modelAndView.getModel().get(getFreeTextModelName()));
        pr.flush();
    }

    protected String getAjaxRequestParamName() {
        return "_asynchronous";
    }

    protected String getAjaxModelAndViewAttr() {
        return "async_model_and_view";
    }

    protected String getFreeTextModelName() {
        return "free_text";
    }

    protected ModelAndView postProcessAsynchronous(HttpServletRequest request, NotificationWrapper command,
            Errors error) throws Exception {
        return new ModelAndView(getAjaxViewName(request));
    }

    protected String getAjaxViewName(HttpServletRequest request) {
        return request.getParameter(getAjaxViewParamName());
    }

    protected String getAjaxViewParamName() {
        return "_asyncViewName";
    }

    protected boolean shouldSave(HttpServletRequest request, NotificationWrapper command) {
        return true;
    }

    public InvestigatorDao getInvestigatorDao() {
        return investigatorDao;
    }

    public void setInvestigatorDao(InvestigatorDao investigatorDao) {
        this.investigatorDao = investigatorDao;
    }

    public PersonUserDao getPersonUserDao() {
        return personUserDao;
    }

    public void setPersonUserDao(PersonUserDao personUserDao) {
        this.personUserDao = personUserDao;
    }

    public PlannedNotificationDao getPlannedNotificationDao() {
        return plannedNotificationDao;
    }

    public void setPlannedNotificationDao(PlannedNotificationDao plannedNotificationDao) {
        this.plannedNotificationDao = plannedNotificationDao;
    }

    public HealthcareSiteDao getHealthcareSiteDao() {
        return healthcareSiteDao;
    }

    public void setHealthcareSiteDao(HealthcareSiteDao healthcareSiteDao) {
        this.healthcareSiteDao = healthcareSiteDao;
    }

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

}