edu.duke.cabig.c3pr.infrastructure.interceptor.NotificationInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for edu.duke.cabig.c3pr.infrastructure.interceptor.NotificationInterceptor.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.infrastructure.interceptor;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.EmptyInterceptor;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.type.Type;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.DataAccessResourceFailureException;

import edu.duke.cabig.c3pr.constants.ContactMechanismType;
import edu.duke.cabig.c3pr.constants.CoordinatingCenterStudyStatus;
import edu.duke.cabig.c3pr.constants.NotificationEventTypeEnum;
import edu.duke.cabig.c3pr.constants.RegistrationWorkFlowStatus;
import edu.duke.cabig.c3pr.constants.SiteStudyStatus;
import edu.duke.cabig.c3pr.dao.HealthcareSiteDao;
import edu.duke.cabig.c3pr.domain.ContactMechanismBasedRecipient;
import edu.duke.cabig.c3pr.domain.Correspondence;
import edu.duke.cabig.c3pr.domain.HealthcareSite;
import edu.duke.cabig.c3pr.domain.Participant;
import edu.duke.cabig.c3pr.domain.PersonUser;
import edu.duke.cabig.c3pr.domain.PlannedNotification;
import edu.duke.cabig.c3pr.domain.SiteStatusHistory;
import edu.duke.cabig.c3pr.domain.Study;
import edu.duke.cabig.c3pr.domain.StudyOrganization;
import edu.duke.cabig.c3pr.domain.StudySite;
import edu.duke.cabig.c3pr.domain.StudySubject;
import edu.duke.cabig.c3pr.domain.StudySubjectDemographics;
import edu.duke.cabig.c3pr.domain.StudySubjectStudyVersion;
import edu.duke.cabig.c3pr.domain.UserBasedRecipient;
import edu.duke.cabig.c3pr.service.impl.RulesDelegationServiceImpl;
import edu.duke.cabig.c3pr.tools.Configuration;
import edu.duke.cabig.c3pr.utils.StringUtils;

public class NotificationInterceptor extends EmptyInterceptor implements ApplicationContextAware {

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

    RulesDelegationServiceImpl rulesDelegationService;

    private ApplicationContext applicationContext;

    private Configuration configuration;

    private HealthcareSiteDao healthcareSiteDao;

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    /**
     * Gets the planned notifications for the list of sites that are passed in.
     * This method access the db using a new session from the hibernate session factory.
     * 
     * @param hcsList the hcs list
     * @return the planned notifications
     */
    public List<PlannedNotification> getPlannedNotifications(List<HealthcareSite> hcsList) {
        List<PlannedNotification> result;
        List<String> nciCodeList = new ArrayList<String>();
        for (HealthcareSite hcs : hcsList) {
            if (hcs != null) {
                nciCodeList.add(hcs.getPrimaryIdentifier());
            }
        }

        SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean("sessionFactory");
        Session session = sessionFactory.openSession(sessionFactory.getCurrentSession().connection());
        session.setFlushMode(FlushMode.MANUAL);
        result = new ArrayList<PlannedNotification>();
        try {
            Query query = session.createQuery(
                    "select p from PlannedNotification p, HealthcareSite o, Identifier i where p = any elements(o.plannedNotificationsInternal) and "
                            + "i = any elements(o.identifiersAssignedToOrganization) and i.primaryIndicator = 'true' and "
                            + "i.value in (:nciCodeList)")
                    .setParameterList("nciCodeList", nciCodeList);

            result = query.list();
        } catch (DataAccessResourceFailureException e) {
            log.error(e.getMessage());
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (HibernateException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            session.close();
        }
        return result;
    }

    /**
     * Gets the planned notifications for the list of sites that are passed in.
     * This method access the db using a new session from the hibernate session factory.
     * 
     * @param hcsList the hcs list
     * @return the planned notifications
     */
    public List<PlannedNotification> getPlannedNotificationsForUpdateMasterSubject() {
        List<PlannedNotification> result;

        SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean("sessionFactory");
        Session session = sessionFactory.openSession(sessionFactory.getCurrentSession().connection());
        session.setFlushMode(FlushMode.MANUAL);
        result = new ArrayList<PlannedNotification>();
        try {
            Query query = session.createQuery("from PlannedNotification p where p.eventName = :var")
                    .setString("var", NotificationEventTypeEnum.MASTER_SUBJECT_UPDATED_EVENT.toString());

            result = query.list();
        } catch (DataAccessResourceFailureException e) {
            log.error(e.getMessage());
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (HibernateException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            session.close();
        }
        return result;
    }

    public List<PlannedNotification> getPlannedNotificationsForCorrespondence() {
        List<PlannedNotification> result;

        SessionFactory sessionFactory = (SessionFactory) applicationContext.getBean("sessionFactory");
        Session session = sessionFactory.openSession(sessionFactory.getCurrentSession().connection());
        session.setFlushMode(FlushMode.MANUAL);
        result = new ArrayList<PlannedNotification>();
        try {
            Query query = session.createQuery(
                    "from PlannedNotification p left join fetch p.userBasedRecipientInternal where p.eventName = :var")
                    .setString("var", NotificationEventTypeEnum.CORRESPONDENCE_CREATED_OR_UPDATED_EVENT.toString());

            result = query.list().subList(0, 1);
        } catch (DataAccessResourceFailureException e) {
            log.error(e.getMessage());
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (HibernateException e) {
            log.error(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            session.close();
        }
        return result;
    }

    /*
     *  Return true only if the state is modified in anyway.
     */
    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        log.debug(this.getClass().getName() + ": Entering onSave()");

        //Every new registration is handled here.
        if (entity instanceof StudySubjectStudyVersion) {
            handleNewStudySubjectSaved(null,
                    ((StudySubjectStudyVersion) entity).getStudySubject().getRegWorkflowStatus(), entity);
        }
        /*      if(entity instanceof StudySubject){         
                 handleNewStudySubjectSaved(null,((StudySubject)entity).getRegWorkflowStatus(), entity);
              }*/
        //Every new study...notification is onyl sent if new stuayd status is Active
        if (entity instanceof Study) {
            handleStudyStatusChange(null, ((Study) entity).getCoordinatingCenterStudyStatus(), entity);
        }
        //New Study Site .....currently not implemented
        if (entity instanceof SiteStatusHistory) {
            StudySite studySite = ((SiteStatusHistory) entity).getStudySite();
            handleStudySiteStatusChange(null, studySite.getSiteStudyStatus(), studySite);
        }

        //saving correspondence activate rules only if follow_up is needed and either person_spoken_to or notified_study_personnel is present

        /*if(entity instanceof Correspondence && ((Correspondence)entity).getFollowUpNeeded() && 
        (((Correspondence)entity).getPersonSpokenTo()!=null || ((Correspondence)entity).getNotifiedStudyPersonnel().size()>0)){
           activateRulesForNewOrUpdatedCorrespondence((Correspondence)entity);
        }*/
        log.debug(this.getClass().getName() + ": Exiting onSave()");
        return false;
    }

    /*
     * This call back intercepts all updates to the database.
     * return true only if the current state is modified in anyway. Do NOT modify the previousState.
     */
    @Override
    public boolean onFlushDirty(final Object entity, Serializable id, final Object[] currentState,
            final Object[] previousState, String[] propertyNames, Type[] types) {

        log.debug(this.getClass().getName() + ": Entering onFlushDirty()");

        //Study status changes are spotted here for activating rules.
        if (entity instanceof Study) {
            for (int i = 0; i < propertyNames.length; i++) {
                if (propertyNames[i].equals("coordinatingCenterStudyStatus") && previousState != null
                        && currentState != null) {
                    handleStudyStatusChange(previousState[i], currentState[i], entity);
                }
            }
        }

        //StudySite status changes are spotted here for activating rules.
        if (entity instanceof SiteStatusHistory) {
            StudySite studySite = ((SiteStatusHistory) entity).getStudySite();
            for (int i = 0; i < propertyNames.length; i++) {
                if (propertyNames[i].equals("siteStudyStatus")) {
                    if (previousState != null && currentState != null) {
                        handleStudySiteStatusChange(previousState[i], currentState[i], studySite);
                    }
                }
            }
        }

        //When Reg status changes to Reserved or Registered
        if (entity instanceof StudySubject) {
            for (int i = 0; i < propertyNames.length; i++) {
                if (propertyNames[i].equals("regWorkflowStatus")) {
                    if (currentState != null) {
                        if (previousState != null) {
                            handleNewStudySubjectSaved(previousState[i], currentState[i], entity);
                        } else {
                            handleNewStudySubjectSaved(null, currentState[i], entity);
                        }
                    }
                }
            }
        }
        // Update Subject

        if (entity instanceof Participant && ((Participant) entity).getVersion() > 0) {
            activateRulesForUpdatingMasterSubject((Participant) entity);
        }

        //update correspondence activate rules only if follow_up is needed and either person_spoken_to or notified_study_personnel is present

        /*if(entity instanceof Correspondence && ((Correspondence)entity).getFollowUpNeeded() && 
        (((Correspondence)entity).getPersonSpokenTo()!=null || ((Correspondence)entity).getNotifiedStudyPersonnel().size()>0)){
           activateRulesForNewOrUpdatedCorrespondence((Correspondence)entity);
        }*/
        log.debug(this.getClass().getName() + ": Exiting onFlushDirty()");
        return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
    }

    /**
     * Handle new study subject saved. Activates rules for the NEW_REGISTRATION_EVENT & REGISTATION_STATUS_CHANGE
     * 
     * @param previousState the previous state
     * @param currentState the current state
     * @param studySubject the study subject
     */
    public void handleNewStudySubjectSaved(final Object previousState, final Object currentState,
            final Object studySubject) {
        RegistrationWorkFlowStatus previousRegStatus = null;
        RegistrationWorkFlowStatus currentRegStatus = null;
        NotificationEventTypeEnum event = null;

        List<Object> objects = new ArrayList<Object>();
        objects.add(studySubject);

        if (previousState != null && previousState instanceof RegistrationWorkFlowStatus) {
            previousRegStatus = (RegistrationWorkFlowStatus) previousState;
        }
        if (currentState != null && currentState instanceof RegistrationWorkFlowStatus) {
            currentRegStatus = (RegistrationWorkFlowStatus) currentState;
        }

        //figure out the event and then fire the rules
        if (previousRegStatus != null && previousRegStatus.getCode().equals(currentRegStatus.getCode())) {
            //no status change...do nothing
        } else {
            //if the prev status is null or pendign and current status is registered then its a new registration
            //else its a reg status change.
            if (currentRegStatus.equals(RegistrationWorkFlowStatus.ON_STUDY)
                    && (previousRegStatus == null || previousRegStatus.equals(RegistrationWorkFlowStatus.PENDING)
                            || previousRegStatus.equals(RegistrationWorkFlowStatus.PENDING_ON_STUDY)
                            || previousRegStatus.equals(RegistrationWorkFlowStatus.RESERVED))) {
                event = NotificationEventTypeEnum.NEW_REGISTRATION_EVENT;
                //run rules seperately for the accruals use case
                activateRulesForAccruals(studySubject);
            } else if (currentRegStatus.equals(RegistrationWorkFlowStatus.OFF_STUDY)) {
                event = NotificationEventTypeEnum.SUBJECT_REMOVED_OFF_STUDY;
            } else {
                event = NotificationEventTypeEnum.REGISTATION_STATUS_CHANGE;
            }
            List<HealthcareSite> hcsList = getSites(studySubject);

            for (PlannedNotification pn : getPlannedNotifications(hcsList)) {
                if (pn.getEventName().equals(event)) {
                    objects.add(pn);
                    rulesDelegationService.activateRules(event, objects);
                    objects.remove(pn);
                }
                //activate rules if the event occured is a new Registration event and we have a stored planned notification for
                //registration status changes. In other words...new Reg event shud send out Reg status changed notification.
                if (pn.getEventName().equals(NotificationEventTypeEnum.REGISTATION_STATUS_CHANGE)
                        && event.equals(NotificationEventTypeEnum.NEW_REGISTRATION_EVENT)) {
                    objects.add(pn);
                    rulesDelegationService.activateRules(NotificationEventTypeEnum.REGISTATION_STATUS_CHANGE,
                            objects);
                    objects.remove(pn);
                }
            }
        }
        log.debug(this.getClass().getName() + ": exiting handleNewStudySubjectSaved()");
    }

    /**
     * Handle study site status change. Actives rules for the STUDY_SITE_STATUS_CHANGED_EVENT
     * 
     * @param previousState the previous state
     * @param currentState the current state
     * @param entity the entity
     */
    public void handleStudySiteStatusChange(final Object previousState, final Object currentState,
            final Object entity) {

        SiteStudyStatus previousSiteStudyStatus = null;
        SiteStudyStatus currentSiteStudyStatus = null;
        NotificationEventTypeEnum event = null;

        List<Object> objects = new ArrayList<Object>();
        objects.add(entity);

        if (previousState != null && previousState instanceof SiteStudyStatus) {
            previousSiteStudyStatus = (SiteStudyStatus) previousState;
        }
        if (currentState != null && currentState instanceof SiteStudyStatus) {
            currentSiteStudyStatus = (SiteStudyStatus) currentState;
        }

        // don't do anything when the study site is newly created in which case it's previous state will be null
        if (previousSiteStudyStatus == null || (previousSiteStudyStatus != null
                && previousSiteStudyStatus.getCode().equals(currentSiteStudyStatus.getCode()))) {
            //no status change...do nothing
        } else {
            //there is some status change and event is configured in plannedNotifs
            //for study site we only have ths study site status changed event
            event = NotificationEventTypeEnum.STUDY_SITE_STATUS_CHANGED_EVENT;
            List<HealthcareSite> hcsList = getSites(entity);
            for (PlannedNotification pn : getPlannedNotifications(hcsList)) {
                if (pn.getEventName().equals(event)) {
                    objects.add(pn);
                    rulesDelegationService.activateRules(event, objects);
                    objects.remove(pn);
                }
            }
        }
    }

    /**
     * Handle study status change. Activates rules for the NEW_STUDY_SAVED_EVENT & STUDY_STATUS_CHANGED_EVENT
     * 
     * @param previousState the previous state
     * @param currentState the current state
     * @param entity the entity
     */
    public void handleStudyStatusChange(final Object previousState, final Object currentState,
            final Object entity) {

        log.debug(this.getClass().getName() + ": Entering handleStudyStatusChange()");
        CoordinatingCenterStudyStatus previousCoordinatingCenterStudyStatus = null;
        CoordinatingCenterStudyStatus currentCoordinatingCenterStudyStatus = null;
        NotificationEventTypeEnum event = null;

        List<Object> objects = new ArrayList<Object>();
        objects.add(entity);

        if (previousState != null && previousState instanceof CoordinatingCenterStudyStatus) {
            previousCoordinatingCenterStudyStatus = (CoordinatingCenterStudyStatus) previousState;
        }
        if (currentState != null && currentState instanceof CoordinatingCenterStudyStatus) {
            currentCoordinatingCenterStudyStatus = (CoordinatingCenterStudyStatus) currentState;
        }

        //figure out the event and then fire the rules
        //removed......currentCoordinatingCenterStudyStatus.equals(CoordinatingCenterStudyStatus.PENDING) ||
        if (currentCoordinatingCenterStudyStatus != null
                && currentCoordinatingCenterStudyStatus.equals(previousCoordinatingCenterStudyStatus)) {
            log.debug("There is no change in the study's status");
            //do nothing if the final status is same as the previous status.
        } else {
            //if the prev status is ready to open and current status is active then its a new study
            //else its a study status change.
            if (currentCoordinatingCenterStudyStatus.equals(CoordinatingCenterStudyStatus.OPEN)
                    && (previousCoordinatingCenterStudyStatus == null
                            || previousCoordinatingCenterStudyStatus
                                    .equals(CoordinatingCenterStudyStatus.READY_TO_OPEN)
                            || previousCoordinatingCenterStudyStatus
                                    .equals(CoordinatingCenterStudyStatus.PENDING))) {
                event = NotificationEventTypeEnum.NEW_STUDY_SAVED_EVENT;
                log.debug("Creating a new study event in the interceptor");
            } else {
                event = NotificationEventTypeEnum.STUDY_STATUS_CHANGED_EVENT;
                log.debug("Creating a study status changed event in the interceptor");
            }
            List<HealthcareSite> hcsList = getSites(entity);
            for (PlannedNotification pn : getPlannedNotifications(hcsList)) {
                //there is some status change and event is configured in plannedNotifs...activate RulesService
                if (pn.getEventName().equals(event)) {
                    objects.add(pn);
                    rulesDelegationService.activateRules(event, objects);
                    objects.remove(pn);
                }
            }
        }
        log.debug(this.getClass().getName() + ": exiting handleStudyStatusChange()");
    }

    /**
     * Activate rules for accruals. Called for new registrations only. 
     * Checks if accrual notifications are configured. Fires rules if thresholds are met.
     * 
     * @param studySubjectObj the study subject obj
     */
    private void activateRulesForAccruals(Object studySubjectObj) {
        StudySubject studySubject = null;
        StudyOrganization studyOrg = null;
        StudySite studySite = null;

        if (studySubjectObj instanceof StudySubject) {
            studySubject = (StudySubject) studySubjectObj;
        } else {
            return;
        }

        List<Object> objects = new ArrayList<Object>();
        objects.add(studySubject);
        int studyAccruals = 0;
        int threshold = 0;
        List<HealthcareSite> hcsList = getSites(studySubject);
        for (PlannedNotification pn : getPlannedNotifications(hcsList)) {
            if (pn.getEventName().equals(NotificationEventTypeEnum.STUDY_ACCRUAL_EVENT)) {
                Iterator<StudyOrganization> iter = studySubject.getStudySite().getStudy().getStudyOrganizations()
                        .iterator();
                while (iter.hasNext()) {
                    studyOrg = iter.next();
                    //ensure that the host org is in the studyOrg list for the study
                    if (studyOrg.getHealthcareSite().getPrimaryIdentifier()
                            .equalsIgnoreCase(configuration.get(Configuration.LOCAL_NCI_INSTITUTE_CODE))) {
                        studyAccruals = calculateStudyAccrual(studySubject);
                        threshold = studySubject.getStudySite().getStudy().getTargetAccrualNumber().intValue();
                        //if accruals exceed specified threshold value then send out email
                        if (studyAccruals * 100 / threshold >= pn.getStudyThreshold()) {
                            objects.add(pn);
                            rulesDelegationService.activateRules(NotificationEventTypeEnum.STUDY_ACCRUAL_EVENT,
                                    objects);
                        }
                    }
                }
            }
            if (pn.getEventName().equals(NotificationEventTypeEnum.STUDY_SITE_ACCRUAL_EVENT)) {
                studySite = studySubject.getStudySite();
                //ensure that the host org is in the studySite list for the study
                if (studySite.getHealthcareSite().getPrimaryIdentifier()
                        .equalsIgnoreCase(configuration.get(Configuration.LOCAL_NCI_INSTITUTE_CODE))) {
                    studyAccruals = calculateStudySiteAccrual(studySubject);
                    threshold = studySubject.getStudySite().getTargetAccrualNumber().intValue();
                    //if accruals exceed specified threshold value then send out email
                    if ((studyAccruals / threshold) * 100 >= pn.getStudySiteThreshold()) {
                        objects.add(pn);
                        rulesDelegationService.activateRules(NotificationEventTypeEnum.STUDY_SITE_ACCRUAL_EVENT,
                                objects);
                    }
                }
            }
        }
    }

    /**
     * Gets the sites. Returns the list of sites associated with the study/studySite/studySubject(depending on the event).
     * 
     * @param entity the entity
     * @return the sites
     */
    private List<HealthcareSite> getSites(Object entity) {

        List<HealthcareSite> hcsList = new ArrayList<HealthcareSite>();
        if (entity instanceof StudySubject) {
            //         Original code, commented out for the time-being.
            /*if(((StudySubject)entity).getStudySite() != null){
               hcsList.add(((StudySubject)entity).getStudySite().getHealthcareSite());
               hcsList.add(((StudySubject)entity).getStudySite().getStudy().getStudyCoordinatingCenter().getHealthcareSite());
                   
            }*/

            //Try this if the above doesn't work
            StudySubject studySubject = (StudySubject) entity;
            if (studySubject.getStudySubjectStudyVersion() != null
                    && studySubject.getStudySubjectStudyVersion().getStudySiteStudyVersion() != null) {
                hcsList.add(studySubject.getStudySubjectStudyVersion().getStudySiteStudyVersion().getStudySite()
                        .getHealthcareSite());
                hcsList.add(studySubject.getStudySiteVersion().getStudyVersion().getStudy()
                        .getStudyCoordinatingCenter().getHealthcareSite());
            }
        }
        if (entity instanceof StudySubjectStudyVersion) {
            StudySubjectStudyVersion studySubjectStudyVersion = (StudySubjectStudyVersion) entity;
            hcsList.add(studySubjectStudyVersion.getStudySiteStudyVersion().getStudySite().getHealthcareSite());
            hcsList.add(studySubjectStudyVersion.getStudySiteStudyVersion().getStudySite().getStudy()
                    .getStudyCoordinatingCenter().getHealthcareSite());
        }

        if (entity instanceof SiteStatusHistory) {
            hcsList.add(((SiteStatusHistory) entity).getStudySite().getHealthcareSite());
            hcsList.add(((SiteStatusHistory) entity).getStudySite().getStudy().getStudyCoordinatingCenter()
                    .getHealthcareSite());
        }
        if (entity instanceof StudySite) {
            hcsList.add(((StudySite) entity).getHealthcareSite());
            hcsList.add(((StudySite) entity).getStudy().getStudyCoordinatingCenter().getHealthcareSite());
        }
        if (entity instanceof Study) {
            for (StudyOrganization so : ((Study) entity).getStudyOrganizations()) {
                hcsList.add(so.getHealthcareSite());
            }
        }
        //defaulting to the hosting site if nothing is found
        if (hcsList.size() == 0) {
            String localNciCode = this.configuration.get(Configuration.LOCAL_NCI_INSTITUTE_CODE);
            hcsList.add(healthcareSiteDao.getByPrimaryIdentifierFromLocal(localNciCode));
        }
        removeDuplicates(hcsList);
        return hcsList;
    }

    /**
    * Removes the duplicate occurrences of any sites that may result in emails being sent out twice.
    * 
    * @param hcsList the hcs list
    */
    private void removeDuplicates(List<HealthcareSite> hcsList) {
        Set<HealthcareSite> set = new HashSet<HealthcareSite>();
        set.addAll(hcsList);
        hcsList.clear();
        hcsList.addAll(set);
    }

    /**
     * Calculate study accrual.
     * 
     * @param studySubject the study subject
     * 
     * @return the int
     */
    private int calculateStudyAccrual(StudySubject studySubject) {
        return studySubject.getStudySite().getStudy().getCurrentAccrualCount().intValue();
    }

    /**
     * Calculate study site accrual.
     * 
     * @param studySubject the study subject
     * 
     * @return the int
     */
    private int calculateStudySiteAccrual(StudySubject studySubject) {
        return studySubject.getStudySite().getCurrentAccrualCount();
    }

    /* Called for updating master subjects only. * fires rules to all registrars on whose sites subject is registered */
    private void activateRulesForUpdatingMasterSubject(Participant participant) {

        List<Object> objects = new ArrayList<Object>();
        objects.add(participant);
        List<HealthcareSite> hcsList = getRegisteredSitesForSubject(participant);
        for (HealthcareSite hcs : hcsList) {
            PlannedNotification plannedNotification = getPlannedNotificationsForUpdateMasterSubject().get(0);
            objects.add(plannedNotification);
            rulesDelegationService.activateRules(NotificationEventTypeEnum.MASTER_SUBJECT_UPDATED_EVENT, objects);
            objects.remove(plannedNotification);
        }
    }

    /* Called for updating master subjects only. * fires rules to all registrars on whose sites subject is registered */
    private void activateRulesForNewOrUpdatedCorrespondence(Correspondence correspondence) {

        List<Object> objects = new ArrayList<Object>();
        objects.add(correspondence);
        PlannedNotification plannedNotification = getPlannedNotificationsForCorrespondence().get(0);
        plannedNotification.getUserBasedRecipient().clear();
        if (correspondence.getPersonSpokenTo() != null) {
            String email = correspondence.getPersonSpokenTo().getEmail();
            if (!StringUtils.isBlank(email)) {
                UserBasedRecipient ubr = new UserBasedRecipient();
                ubr.setPersonUser(correspondence.getPersonSpokenTo());
                ubr.setEmailAddress(email);
                plannedNotification.getUserBasedRecipient().add(ubr);
            }
        }

        for (PersonUser notifiedPersonUser : correspondence.getNotifiedStudyPersonnel()) {
            String email = notifiedPersonUser.getEmail();
            if (!StringUtils.isBlank(email)) {
                UserBasedRecipient ubr = new UserBasedRecipient();
                ubr.setPersonUser(notifiedPersonUser);
                ubr.setEmailAddress(email);
                plannedNotification.getUserBasedRecipient().add(ubr);
            }
        }

        objects.add(plannedNotification);
        rulesDelegationService.activateRules(NotificationEventTypeEnum.CORRESPONDENCE_CREATED_OR_UPDATED_EVENT,
                objects);
        objects.remove(plannedNotification);
    }

    public List<HealthcareSite> getRegisteredSitesForSubject(Participant participant) {
        List<HealthcareSite> registeredSites = new ArrayList<HealthcareSite>();

        for (StudySubjectDemographics studySubjectDemographics : participant.getStudySubjectDemographics()) {
            for (StudySubject registration : studySubjectDemographics.getRegistrations()) {
                registeredSites.add(registration.getStudySite().getHealthcareSite());
            }
        }
        return registeredSites;
    }

    public RulesDelegationServiceImpl getRulesDelegationService() {
        return rulesDelegationService;
    }

    public void setRulesDelegationService(RulesDelegationServiceImpl rulesDelegationService) {
        this.rulesDelegationService = rulesDelegationService;
    }

    public Configuration getConfiguration() {
        return configuration;
    }

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

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

}