com.sfs.whichdoctor.dao.PersonDAOImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.sfs.whichdoctor.dao.PersonDAOImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2009 David Harrison.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * Contributors:
 *     David Harrison - initial API and implementation
 ******************************************************************************/
package com.sfs.whichdoctor.dao;

import com.sfs.DataFilter;
import com.sfs.beans.BuilderBean;
import com.sfs.beans.ObjectTypeBean;
import com.sfs.beans.PrivilegesBean;
import com.sfs.beans.UserBean;
import com.sfs.whichdoctor.analysis.FinancialSummaryAnalysisDAO;
import com.sfs.whichdoctor.beans.DebitBean;
import com.sfs.whichdoctor.beans.ExamBean;
import com.sfs.whichdoctor.beans.FinancialSummaryBean;
import com.sfs.whichdoctor.beans.GroupBean;
import com.sfs.whichdoctor.beans.IsbEntityBean;
import com.sfs.whichdoctor.beans.IsbTransactionBean;
import com.sfs.whichdoctor.beans.ItemBean;
import com.sfs.whichdoctor.beans.MembershipBean;
import com.sfs.whichdoctor.beans.PersonBean;
import com.sfs.whichdoctor.beans.ProjectBean;
import com.sfs.whichdoctor.beans.QualificationBean;
import com.sfs.whichdoctor.beans.ReimbursementBean;
import com.sfs.whichdoctor.beans.RotationBean;
import com.sfs.whichdoctor.beans.SearchBean;
import com.sfs.whichdoctor.beans.SearchResultsBean;
import com.sfs.whichdoctor.beans.SupervisorBean;
import com.sfs.whichdoctor.beans.TransactionSummaryBean;
import com.sfs.whichdoctor.beans.WorkshopBean;
import com.sfs.whichdoctor.search.WhichDoctorSearchDaoException;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

/**
 * The Class PersonDAOImpl.
 */
public class PersonDAOImpl extends WhichDoctorCoreObjectDAOImpl implements PersonDAO {

    /** The data logger. */
    private static Logger dataLogger = Logger.getLogger(PersonDAOImpl.class);

    /** The isb transaction dao. */
    @Resource
    private IsbTransactionDAO isbTransactionDAO;

    /** The accreditation dao. */
    @Resource
    private AccreditationDAO accreditationDAO;

    /** The exam dao. */
    @Resource
    private ExamDAO examDAO;

    /** The isb entity dao. */
    @Resource
    private IsbEntityDAO isbEntityDAO;

    /** The membership dao. */
    @Resource
    private MembershipDAO membershipDAO;

    /** The online tools dao. */
    @Resource
    private OnlineToolDAO onlineToolDAO;

    /** The project dao. */
    @Resource
    private ProjectDAO projectDAO;

    /** The qualification dao. */
    @Resource
    private QualificationDAO qualificationDAO;

    /** The relationship dao. */
    @Resource
    private RelationshipDAO relationshipDAO;

    /** The rotation dao. */
    @Resource
    private RotationDAO rotationDAO;

    /** The workshop dao. */
    @Resource
    private WorkshopDAO workshopDAO;

    /** The financial summary analysis dao. */
    @Resource
    private FinancialSummaryAnalysisDAO financialSummaryAnalysisDAO;

    /** The default training status. */
    private String defaultTrainingStatus = "Not in training";

    /** The person identifier class. */
    private String personIdentifierClass = "Member";

    /**
     * Sets the default training status.
     *
     * @param defaultTrainingStatusVal the new default training status
     */
    public final void setDefaultTrainingStatus(final String defaultTrainingStatusVal) {
        this.defaultTrainingStatus = defaultTrainingStatusVal;
    }

    /**
     * Sets the person identifier class.
     *
     * @param personIdentifierClassVal the new person identifier class
     */
    public final void setPersonIdentifierClass(final String personIdentifierClassVal) {
        this.personIdentifierClass = personIdentifierClassVal;
    }

    /**
     * Load a PersonBean for the specified personId.
     *
     * @param personId the person id
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean load(final int personId) throws WhichDoctorDaoException {
        return load(personId, new BuilderBean(), false);
    }

    /**
     * Load a PersonBean for the specified personId using the load options
     * provided.
     *
     * @param personId the person id
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean load(final int personId, final BuilderBean loadDetails) throws WhichDoctorDaoException {
        return load(personId, loadDetails, false);
    }

    /**
     * Load a PersonBean for a specified personId using the load options
     * provided. A boolean parameter identifies whether to use the default
     * reader connection or optional writer connection datasource
     *
     * @param personId the person id
     * @param loadDetails the load details
     * @param useWriterConn the use writer conn
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    private PersonBean load(final int personId, final BuilderBean loadDetails, final boolean useWriterConn)
            throws WhichDoctorDaoException {

        PersonBean person = null;

        final String loadPersonId = getSQL().getValue("person/load") + " AND people.PersonId = ?";

        JdbcTemplate jdbcTemplate = this.getJdbcTemplateReader();
        if (useWriterConn) {
            jdbcTemplate = this.getJdbcTemplateWriter();
        }

        try {
            person = (PersonBean) jdbcTemplate.queryForObject(loadPersonId, new Object[] { personId },
                    new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadPerson(rs, loadDetails);
                        }
                    });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        return person;
    }

    /**
     * Load a PersonBean for the specified name.
     *
     * @param strPerson the str person
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean load(final String strPerson) throws WhichDoctorDaoException {
        return load(strPerson, new BuilderBean());
    }

    /**
     * Load a PersonBean for a specified name using the load options provided.
     *
     * @param strPerson the str person
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean load(final String strPerson, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {

        dataLogger.info("Person Name: " + strPerson + " requested");

        int personGUID = 0;

        final String loadSQL = getSQL().getValue("person/loadName");

        try {
            personGUID = this.getJdbcTemplateReader().queryForInt(loadSQL, new Object[] { strPerson });
        } catch (DataAccessException de) {
            dataLogger.error("Error getting guid for supplied person: " + de.getMessage());
        }
        if (personGUID > 0) {
            return loadGUID(personGUID, loadDetails);
        } else {
            throw new WhichDoctorDaoException("Sorry no person matching those " + "details could be identified");
        }
    }

    /**
     * Load a PersonBean for a specified identifier.
     *
     * @param identifier the identifier
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean loadIdentifier(final int identifier) throws WhichDoctorDaoException {
        return loadIdentifier(identifier, new BuilderBean());
    }

    /**
     * Load a PersonBean for a specified identifier using the load options
     * provided.
     *
     * @param identifier the identifier
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final PersonBean loadIdentifier(final int identifier, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {

        PersonBean person = null;

        final String loadIdentifier = getSQL().getValue("person/load")
                + " AND people.Active = true AND people.PersonIdentifier = ?";

        try {
            person = (PersonBean) this.getJdbcTemplateReader().queryForObject(loadIdentifier,
                    new Object[] { identifier }, new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadPerson(rs, loadDetails);
                        }
                    });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        return person;
    }

    /**
     * Load a PersonBean for a specified GUID.
     *
     * @param guid the guid
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean loadGUID(final int guid) throws WhichDoctorDaoException {
        return loadGUID(guid, new BuilderBean());
    }

    /**
     * Load a PersonBean for a specified GUID and the load options provided.
     *
     * @param guid the guid
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final PersonBean loadGUID(final int guid, final BuilderBean loadDetails) throws WhichDoctorDaoException {

        PersonBean person = null;

        final String loadGUID = getSQL().getValue("person/load") + " AND people.Active = true AND people.GUID = ?";

        try {
            person = (PersonBean) this.getJdbcTemplateReader().queryForObject(loadGUID, new Object[] { guid },
                    new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadPerson(rs, loadDetails);
                        }
                    });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        return person;
    }

    /**
     * Load a PersonBean for a specified, anonymous, candidate number.
     *
     * @param candidateNumber the candidate number
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean loadCandidateNumber(final int candidateNumber) throws WhichDoctorDaoException {
        return loadCandidateNumber(candidateNumber, new BuilderBean());
    }

    /**
     * Load a PersonBean for a specified, anonymous, candidate number using the
     * load options provided.
     *
     * @param candidateNumber the candidate number
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean loadCandidateNumber(final int candidateNumber, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {
        dataLogger.info("Candidate Number: " + candidateNumber + " requested");

        int personGUID = 0;

        final String loadSQL = getSQL().getValue("person/loadCandidate");

        try {
            personGUID = this.getJdbcTemplateReader().queryForInt(loadSQL, new Object[] { candidateNumber });
        } catch (DataAccessException de) {
            dataLogger.error("Error getting guid for supplied candidate: " + de.getMessage());
        }
        if (personGUID > 0) {
            return loadGUID(personGUID, loadDetails);
        } else {
            throw new WhichDoctorDaoException("Sorry no person matching those " + "details could be identified");
        }
    }

    /**
     * Load all active people.
     *
     * @return the collection< person bean>
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final Collection<PersonBean> loadActivePeople() throws WhichDoctorDaoException {

        Collection<PersonBean> people = new ArrayList<PersonBean>();

        SearchBean search = this.getSearchDAO().initiate("person", null);
        search.setLimit(0);

        Collection<Object> results = null;
        try {
            results = this.getSearchDAO().search(search).getSearchResults();
        } catch (Exception e) {
            dataLogger.error("Error searching for active people: " + e.getMessage());
            throw new WhichDoctorDaoException("Error searching for active people: " + e.getMessage());
        }

        if (results != null) {
            for (Object objPerson : results) {
                if (objPerson != null) {
                    people.add((PersonBean) objPerson);
                }
            }
        }
        return people;
    }

    /**
     * Creates the person.
     *
     * @param person the person
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean create(final PersonBean person, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {
        person.setActive(true);
        final int personId = save(person, checkUser, privileges, "create");

        return load(personId, new BuilderBean(), true);
    }

    /**
     * Modify the PersonBean.
     *
     * @param person the person
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return the person bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final PersonBean modify(final PersonBean person, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {
        person.setActive(true);
        final int personId = save(person, checkUser, privileges, "modify");

        return load(personId, new BuilderBean(), true);
    }

    /**
     * Delete the person.
     *
     * @param person the person
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return true, if successful
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final boolean delete(final PersonBean person, final UserBean checkUser, final PrivilegesBean privileges)
            throws WhichDoctorDaoException {
        boolean success = false;

        // If the user has the right privileges, remove the person from the ISB
        if (privileges.getPrivilege(checkUser, "people", "delete")) {
            try {
                final Collection<IsbEntityBean> isbEntities = isbEntityDAO.loadAll(person.getGUID());
                for (IsbEntityBean isbEntity : isbEntities) {
                    isbEntityDAO.delete(isbEntity, checkUser, privileges, false);
                }
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error deleting ISB entities prior to deletion: " + wde.getMessage());
                throw new WhichDoctorDaoException(
                        "Error deleting ISB entities prior " + "to deletion: " + wde.getMessage());
            }

            // Before deleting the person remove its child objects
            final BuilderBean loadDetails = new BuilderBean();
            loadDetails.setParameter("LOAD_ALL", true);
            try {
                final PersonBean deleteObj = this.loadGUID(person.getGUID(), loadDetails);
                deleteAssociatedObjects(deleteObj, checkUser, privileges);

            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error deleting children: " + wde.getMessage(), wde);
                throw new WhichDoctorDaoException("Error deleting children objects: " + wde.getMessage());
            }
        }

        person.setActive(false);
        int personId = save(person, checkUser, privileges, "delete");
        if (personId > 0) {
            success = true;
        }
        return success;
    }

    /**
     * Save the updated PersonBean.
     *
     * @param person the person
     * @param checkUser the check user
     * @param privileges the privileges
     * @param action the action
     *
     * @return the int
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private int save(final PersonBean person, final UserBean checkUser, final PrivilegesBean privileges,
            final String action) throws WhichDoctorDaoException {

        /* Create person requires all the essential person information */
        if (person.getLastName() == null) {
            throw new WhichDoctorDaoException("Person's last name cannot be null");
        }
        if (person.getLastName().compareTo("") == 0) {
            throw new WhichDoctorDaoException("Person's last name cannot be an empty string");
        }
        if (person.getFirstName() == null) {
            throw new WhichDoctorDaoException("Person's first name cannot be null");
        }
        if (person.getFirstName().compareTo("") == 0) {
            throw new WhichDoctorDaoException("Person's first name cannot be an empty string");
        }
        if (!privileges.getPrivilege(checkUser, "people", action)) {
            throw new WhichDoctorDaoException("Insufficient user credentials to " + action + " person");
        }

        if (person.getPersonIdentifier() == 0) {
            person.setPersonIdentifier(this.generatePersonIdentifier());
        }

        // Get the titleId and trainingStatusId values
        int titleId = 0;
        int trainingStatusId = 0;

        try {
            ObjectTypeBean object = this.getObjectTypeDAO().load("Title", person.getTitle(), person.getGender());
            titleId = object.getObjectTypeId();
        } catch (Exception e) {
            dataLogger.error("Error loading objecttype for title/gender: " + e.getMessage());
            throw new WhichDoctorDaoException("Person requires a valid title");
        }

        if (StringUtils.isBlank(person.getTrainingStatus())) {
            person.setTrainingStatus(this.defaultTrainingStatus);
        }
        try {
            ObjectTypeBean object = this.getObjectTypeDAO().load("Training Status",
                    person.getTrainingStatusDetail(), person.getTrainingStatus());
            trainingStatusId = object.getObjectTypeId();
        } catch (Exception e) {
            dataLogger.error("Error loading objecttype for training status: " + e.getMessage());
            throw new WhichDoctorDaoException("Person requires a valid training status");
        }

        int personId = 0;

        Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis());
        /* Set the Birth date */
        Date birthDate = null;
        if (person.getBirthDate() != null) {
            birthDate = new Date(person.getBirthDate().getTime());
        }
        /* Set the Deceased date */
        Date deceasedDate = null;
        if (person.getDeceasedDate() != null) {
            deceasedDate = new Date(person.getDeceasedDate().getTime());
        }

        ArrayList<Object> parameters = new ArrayList<Object>();
        parameters.add(person.getPersonIdentifier());
        parameters.add(person.getFirstName());
        parameters.add(person.getMiddleName());
        parameters.add(person.getLastName());
        parameters.add(person.getPreferredName());
        parameters.add(person.getMaidenName());
        parameters.add(titleId);
        parameters.add(person.getHonors());
        parameters.add(birthDate);
        parameters.add(deceasedDate);
        parameters.add(trainingStatusId);
        parameters.add(person.getPassword());
        parameters.add(person.getActive());
        parameters.add(sqlTimeStamp);
        parameters.add(checkUser.getDN());
        parameters.add(person.getLogMessage(action));

        /* Begin the ISB transaction */
        IsbTransactionBean isbTransaction = this.isbTransactionDAO.begin(person.getGUID());

        try {
            Integer[] result = this.performUpdate("person", person.getGUID(), parameters, "Person", checkUser,
                    action);
            /* Set the returned guid and id values */
            person.setGUID(result[0]);
            personId = result[1];
        } catch (Exception e) {
            dataLogger.error("Error processing person record: " + e.getMessage());
            throw new WhichDoctorDaoException("Error processing person record: " + e.getMessage());
        }

        if (personId > 0) {

            dataLogger.info(checkUser.getDN() + " created personId: " + String.valueOf(personId));

            /* Commit the ISB transaction */
            this.isbTransactionDAO.commit(isbTransaction);

            /* Update the relevant search indexes */
            updateIndexes(person.getGUID(), action);
        }

        return personId;
    }

    /**
     * Delete the objects associated with the supplied PersonBean.
     *
     * @param deleteObjects the delete objects
     * @param checkUser the check user
     * @param privileges the privileges
     */
    private void deleteAssociatedObjects(final PersonBean deleteObjects, final UserBean checkUser,
            final PrivilegesBean privileges) {

        // Delete the associated membership records
        if (deleteObjects.getMembershipDetails() != null) {
            for (MembershipBean membership : deleteObjects.getMembershipDetails()) {
                try {
                    membership.setLogMessage(membership.getLogMessage("delete"));
                    membershipDAO.delete(membership, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting membership record: " + wde.getMessage());
                }
            }
        }

        // Delete the associated rotation records
        if (deleteObjects.getRotations() != null) {
            for (RotationBean rotation : deleteObjects.getRotations()) {
                try {
                    rotation.setLogMessage(rotation.getLogMessage("delete"));
                    rotationDAO.delete(rotation, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting rotation: " + wde.getMessage());
                }
            }
        }

        // Delete the associated exam records
        if (deleteObjects.getExams() != null) {
            for (ExamBean exam : deleteObjects.getExams()) {
                try {
                    exam.setLogMessage(exam.getLogMessage("delete"));
                    examDAO.delete(exam, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting exam: " + wde.getMessage());
                }
            }
        }

        // Delete the associated project records
        if (deleteObjects.getProjects() != null) {
            for (ProjectBean project : deleteObjects.getProjects()) {
                try {
                    project.setLogMessage(project.getLogMessage("delete"));
                    projectDAO.delete(project, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting project: " + wde.getMessage());
                }
            }
        }

        // Delete the associated employers
        if (deleteObjects.getEmployers() != null) {
            for (ItemBean employer : deleteObjects.getEmployers().values()) {
                try {
                    employer.setLogMessage(employer.getLogMessage("delete"));
                    this.getItemDAO().delete(employer, checkUser, privileges, null);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting employer: " + wde.getMessage());
                }
            }
        }

        // Delete the associated mentors
        if (deleteObjects.getMentors() != null) {
            for (ItemBean mentor : deleteObjects.getMentors().values()) {
                try {
                    mentor.setLogMessage(mentor.getLogMessage("delete"));
                    this.getItemDAO().delete(mentor, checkUser, privileges, null);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting mentor: " + wde.getMessage());
                }
            }
        }

        // Delete the associated qualifications
        if (deleteObjects.getQualifications() != null) {
            for (QualificationBean qualification : deleteObjects.getQualifications()) {
                try {
                    qualification.setLogMessage(qualification.getLogMessage("delete"));
                    qualificationDAO.delete(qualification, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting qualification: " + wde.getMessage());
                }
            }
        }

        // Delete the associated workshops
        if (deleteObjects.getWorkshops() != null) {
            for (WorkshopBean workshop : deleteObjects.getWorkshops()) {
                try {
                    workshop.setLogMessage(workshop.getLogMessage("delete"));
                    workshopDAO.delete(workshop, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting workshop: " + wde.getMessage());
                }
            }
        }

        // Delete the core objects associated to this organisation
        deleteAddresses(deleteObjects, checkUser, privileges);
        deleteEmailAddresses(deleteObjects, checkUser, privileges);
        deletePhoneNumbers(deleteObjects, checkUser, privileges);
        deleteSpecialties(deleteObjects, checkUser, privileges);
        deleteFinancialRecords(deleteObjects, checkUser, privileges);
        deleteMemos(deleteObjects, checkUser, privileges);
        deleteGroups(deleteObjects, checkUser, privileges);
    }

    /**
     * Load person.
     *
     * @param rs the rs
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws SQLException the SQL exception
     */
    private PersonBean loadPerson(final ResultSet rs, final BuilderBean loadDetails) throws SQLException {

        PersonBean person = new PersonBean();

        person.setId(rs.getInt("PersonId"));
        person.setGUID(rs.getInt("GUID"));
        person.setPersonIdentifier(rs.getInt("PersonIdentifier"));

        person.setFirstName(rs.getString("FirstName"));
        person.setMiddleName(rs.getString("MiddleName"));
        person.setLastName(rs.getString("LastName"));
        person.setMaidenName(rs.getString("MaidenName"));
        if (rs.getString("PreferredName") != null) {
            person.setPreferredName(rs.getString("PreferredName"));
        } else {
            person.setPreferredName(person.getFirstName());
        }
        person.setTitle(rs.getString("Title"));
        person.setHonors(rs.getString("Honors"));
        person.setGender(rs.getString("Gender"));
        try {
            person.setBirthDate(rs.getDate("BirthDate"));
        } catch (SQLException e) {
            person.setBirthDate(null);
        }
        try {
            person.setDeceasedDate(rs.getDate("DeceasedDate"));
        } catch (SQLException e) {
            person.setDeceasedDate(null);
        }

        person.setRegion(rs.getString("Region"));
        person.setResidentCountry(rs.getString("ResidentCountry"));
        person.setTrainingStatus(rs.getString("TrainingStatus"));
        person.setTrainingStatusDetail(rs.getString("TrainingStatusDetail"));
        person.setTrainingStatusMapping(rs.getString("TrainingStatusMapping"));

        person.setPassword(rs.getString("Password"));
        person.setActive(rs.getBoolean("Active"));

        if (loadDetails.getBoolean("MEMBERSHIP")) {
            /** Load the membership details **/
            try {
                person.setMembershipDetails(this.membershipDAO.load(person.getGUID(),
                        loadDetails.getBoolean("MEMBERSHIP_FULL"), loadDetails.getString("MEMBERSHIP_CLASS"),
                        loadDetails.getString("MEMBERSHIP_TYPE")));
            } catch (Exception e) {
                dataLogger.error("Error loading memberships for person: " + e.getMessage(), e);
            }
        }

        if (loadDetails.getBoolean("TAGS")) {
            try {
                person.setTags(this.getTagDAO().load(person.getGUID(), loadDetails.getString("USERDN"), true));
            } catch (Exception e) {
                dataLogger.error("Error loading tags for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("QUALIFICATIONS")) {
            try {
                person.setQualifications(this.qualificationDAO.load(person.getGUID(), true));
            } catch (Exception e) {
                dataLogger.error("Error loading qualifications for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("ADDRESS")) {
            try {
                person.setAddress(
                        this.getAddressDAO().load(person.getGUID(), loadDetails.getBoolean("ADDRESS_FULL"),
                                loadDetails.getString("ADDRESS_CLASS"), loadDetails.getString("ADDRESS_TYPE")));
            } catch (Exception e) {
                dataLogger.error("Error loading addresses for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("PHONE")) {
            try {
                person.setPhone(this.getPhoneDAO().load(person.getGUID(), loadDetails.getBoolean("PHONE_FULL")));
            } catch (Exception e) {
                dataLogger.error("Error loading phone numbers for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("EMAIL")) {
            try {
                person.setEmail(this.getEmailDAO().load(person.getGUID(), loadDetails.getBoolean("EMAIL_FULL"),
                        loadDetails.getString("EMAIL_CLASS"), loadDetails.getString("EMAIL_TYPE")));
            } catch (Exception e) {
                dataLogger.error("Error loading email addresses for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("HISTORY")) {
            try {
                person.setCreatedDate(rs.getTimestamp("CreatedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading CreatedDate: " + sqe.getMessage());
            }
            person.setCreatedBy(rs.getString("CreatedBy"));
            try {
                person.setModifiedDate(rs.getTimestamp("ModifiedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading ModifiedDate: " + sqe.getMessage());
            }
            person.setModifiedBy(rs.getString("ModifiedBy"));
            try {
                person.setExportedDate(rs.getTimestamp("ExportedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading ExportedDate: " + sqe.getMessage());
            }
            person.setExportedBy(rs.getString("ExportedBy"));
        }

        if (loadDetails.getBoolean("MEMO")) {
            try {
                person.setMemo(this.getMemoDAO().load(person.getGUID(), loadDetails.getBoolean("MEMO_FULL")));
            } catch (Exception e) {
                dataLogger.error("Error loading memos for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("SPECIALTY")) {
            try {
                person.setSpecialtyList(this.getSpecialtyDAO().load(person.getGUID(), true));
            } catch (Exception e) {
                dataLogger.error("Error loading specialties for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("MENTORS")) {
            try {
                person.setMentors(this.getItemDAO().load(person.getGUID(), true, "Mentor", "Mentors"));
            } catch (Exception e) {
                dataLogger.error("Error loading mentors for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("EMPLOYERS")) {
            try {
                person.setEmployers(this.getItemDAO().load(person.getGUID(), true, "Employer", "Employers", 0,
                        loadDetails.getString("EMPLOYERS_STARTDATE"), loadDetails.getString("EMPLOYERS_ENDDATE")));
            } catch (Exception e) {
                dataLogger.info("Error loading employers for this person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("TRAINING_BASIC")) {
            /* Load the person's Basic Training summary */
            try {
                person.setTrainingSummary("Basic Training",
                        this.accreditationDAO.getTrainingSummary(person.getGUID(), "Basic Training"));
            } catch (Exception e) {
                dataLogger.error("Error loading accrediation summary: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("TRAINING_ADVANCED")) {
            /* Load the person's Advanced Training summary */
            try {
                person.setTrainingSummary("Advanced Training",
                        this.accreditationDAO.getTrainingSummary(person.getGUID(), "Advanced Training"));
            } catch (Exception e) {
                dataLogger.error("Error loading accrediation summary: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("TRAINING_POSTFRACP")) {
            /* Load the person's Post-FRACP Training summary */
            try {
                person.setTrainingSummary("Post-FRACP Training",
                        this.accreditationDAO.getTrainingSummary(person.getGUID(), "Post-FRACP Training"));
            } catch (Exception e) {
                dataLogger.error("Error loading accrediation summary: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("EXAMS")) {
            try {
                person.setExams(this.examDAO.load(person.getGUID(), false));
            } catch (Exception e) {
                dataLogger.error("Error loading exams for person: " + e.getMessage());
            }
            person.setExamDeadline(this.examDAO.calculateExamDeadline(person.getExams()));
        }

        if (loadDetails.getBoolean("PROJECTS")) {
            try {
                person.setProjects(this.projectDAO.load(person.getGUID(), false));
            } catch (Exception e) {
                dataLogger.error("Error loading projects for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("WORKSHOPS")) {
            try {
                person.setWorkshops(this.workshopDAO.load(person.getGUID(), false));
            } catch (Exception e) {
                dataLogger.error("Error loading workshops for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("ONLINETOOLS")) {
            try {
                person.setOnlineTools(this.onlineToolDAO.load(person.getGUID()));
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error loading online tools for person: " + wde.getMessage());
            }
        }

        if (loadDetails.getBoolean("TRAINING_ROTATIONS")) {
            // Find all Rotations for the person
            SearchBean search = this.getSearchDAO().initiate("rotation", null);
            RotationBean searchCriteria = (RotationBean) search.getSearchCriteria();
            RotationBean consts = (RotationBean) search.getSearchConstraints();
            searchCriteria.setPersonId(person.getGUID());

            if (!loadDetails.getBoolean("LOAD_ALL") && loadDetails.getBoolean("CURRENT_ROTATION")) {
                Calendar currentDate = Calendar.getInstance();

                searchCriteria.setStartDate(currentDate.getTime());
                searchCriteria.setEndDate(currentDate.getTime());

                consts.setStartDate(DataFilter.parseDate("1/1/1900", false));
                consts.setEndDate(DataFilter.parseDate("31/12/2050", false));

                search.setSearchConstraints(consts);
            }

            search.setSearchCriteria(searchCriteria);
            search.setLimit(0);

            BuilderBean loadRotation = new BuilderBean();
            loadRotation.setParameter("ASSESSMENTS", true);
            loadRotation.setParameter("ONLINETOOLS", true);
            loadRotation.setParameter("ACCREDITATIONS", true);
            loadRotation.setParameter("SUPERVISORS", true);
            loadRotation.setParameter("MEMO", true);
            loadRotation.setParameter("MEMO_FULL", true);
            try {
                final Collection<Object> results = this.getSearchDAO().search(search, loadRotation)
                        .getSearchResults();

                if (results != null) {
                    Collection<RotationBean> rotations = new ArrayList<RotationBean>();
                    for (Object rotationObj : results) {
                        rotations.add((RotationBean) rotationObj);
                    }
                    person.setRotations(rotations);
                    dataLogger.info("Successfully loaded for rotation information");
                }
            } catch (Exception e) {
                dataLogger.error("Error loading person rotations: " + e.getMessage());
            }
        }

        /** Only perform this search if no rotations have been loaded above **/
        if (loadDetails.getBoolean("LAST_ROTATION") && person.getRotations().size() == 0) {
            // Find the last rotation this person undertook
            SearchBean search = this.getSearchDAO().initiate("rotation", null);
            RotationBean searchCriteria = (RotationBean) search.getSearchCriteria();
            searchCriteria.setPersonId(person.getGUID());

            search.setSearchCriteria(searchCriteria);
            search.setLimit(1);
            search.setOrderColumn("rotation.EndDate");
            search.setOrderAscending(false);

            try {
                final Collection<Object> results = this.getSearchDAO().search(search).getSearchResults();

                if (results != null) {
                    Collection<RotationBean> rotations = new ArrayList<RotationBean>();
                    for (Object rotationObj : results) {
                        rotations.add((RotationBean) rotationObj);
                    }
                    person.setRotations(rotations);
                    dataLogger.info("Successfully loaded last rotation for person");
                }
            } catch (Exception e) {
                dataLogger.error("Error loading last rotation for person: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("REIMBURSEMENTS")) {
            SearchBean search = this.getSearchDAO().initiate("reimbursement", null);
            ReimbursementBean searchCriteria = (ReimbursementBean) search.getSearchCriteria();

            searchCriteria.setPersonId(person.getGUID());
            search.setLimit(0);
            search.setSearchCriteria(searchCriteria);

            try {
                final Collection<Object> results = this.getSearchDAO().search(search).getSearchResults();

                if (results != null) {
                    Collection<ReimbursementBean> reimbursements = new ArrayList<ReimbursementBean>();
                    for (Object reimbursementObj : results) {
                        reimbursements.add((ReimbursementBean) reimbursementObj);
                    }
                    person.setReimbursements(reimbursements);
                }
                dataLogger.info("Successfully loaded reimbursement information");
            } catch (Exception e) {
                dataLogger.error("ERROR searching database: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("FINANCIAL_SUMMARY")) {

            FinancialSummaryBean search = new FinancialSummaryBean();
            search.setLimit(0);
            search.setRequestedPage(1);
            search.addPerson(person);
            search.setSecurity("Standard");

            search.setOpeningDate(DataFilter.parseDate(loadDetails.getString("FINANCIAL_SUMMARY_OPENING"), false));
            search.setClosingDate(DataFilter.parseDate(loadDetails.getString("FINANCIAL_SUMMARY_CLOSING"), true));

            BuilderBean summaryDetails = new BuilderBean();
            summaryDetails.setParameter("LOAD_DETAILS", loadDetails.getBoolean("FINANCIAL_SUMMARY_TRANSACTIONS"));
            summaryDetails.setParameter("SHOW_CANCELLED", loadDetails.getBoolean("FINANCIAL_SUMMARY_USER"));
            summaryDetails.setParameter("RESULT_COUNT", true);

            FinancialSummaryBean results = null;

            try {
                results = this.financialSummaryAnalysisDAO.search(search, summaryDetails);
            } catch (Exception e) {
                dataLogger.error("Error loading financial summary results: " + e.getMessage());
            }

            if (results != null && loadDetails.getBoolean("FINANCIAL_SUMMARY_LASTTEN")) {
                /* Limit to the last 10 results */
                if (results.getTotalResults() > 10) {
                    ArrayList<TransactionSummaryBean> limitedResults = new ArrayList<TransactionSummaryBean>();
                    ArrayList<TransactionSummaryBean> transactions = new ArrayList<TransactionSummaryBean>();

                    for (TransactionSummaryBean transaction : results.getTransactions()) {
                        transactions.add(transaction);
                    }

                    for (int i = transactions.size() - 11; i < transactions.size(); i++) {
                        try {
                            TransactionSummaryBean transaction = (TransactionSummaryBean) transactions.get(i);
                            if (i == transactions.size() - 11) {
                                /* Get total and set as opening balance */
                                results.setBalanceBroughtForward(transaction.getTotal());
                            } else {
                                limitedResults.add(transaction);
                            }
                        } catch (Exception e) {
                            dataLogger.error("Error getting last ten financial entries:" + e.getMessage());
                        }
                    }
                    results.setTransactions(limitedResults);
                }
            }
            person.setFinancialSummary(results);

            if (loadDetails.getBoolean("FINANCIAL_SUMMARY_USER")) {
                FinancialSummaryBean securedFinancialSearch = search;
                securedFinancialSearch.setSecurity("Restricted");

                try {
                    person.setRestrictedFinancialSummary(
                            this.financialSummaryAnalysisDAO.search(securedFinancialSearch, summaryDetails));
                    dataLogger.info("Successfully loaded restricted" + " financial summary information");
                } catch (Exception e) {
                    dataLogger.error("Error loading restricted" + " financial summary results: " + e.getMessage());
                }
            }

            if (loadDetails.getBoolean("FINANCIAL_SUMMARY_OUTSTANDING")) {
                double balance = 0;
                if (person.getFinancialSummary() != null) {
                    balance += person.getFinancialSummary().getClosingBalance();
                }
                if (person.getRestrictedFinancialSummary() != null) {
                    balance += person.getRestrictedFinancialSummary().getClosingBalance();
                }
                if (balance > 0) {
                    // Perform a search for outstanding debits associated with person
                    SearchBean dbSearch = this.getSearchDAO().initiate("debit", null);
                    DebitBean dbCriteria = (DebitBean) dbSearch.getSearchCriteria();
                    DebitBean dbConstraints = (DebitBean) dbSearch.getSearchConstraints();
                    dbCriteria.setPersonId(person.getGUID());
                    dbCriteria.setOutstandingValue(0.01);
                    dbConstraints.setOutstandingValue(10000000);

                    dbSearch.setSearchCriteria(dbCriteria);
                    dbSearch.setSearchConstraints(dbConstraints);
                    dbSearch.setLimit(0);

                    SearchResultsBean dbResults = new SearchResultsBean();
                    try {
                        dbResults = this.getSearchDAO().search(dbSearch);
                    } catch (WhichDoctorSearchDaoException wde) {
                        dataLogger.error("Error searching for outstanding debits: " + wde.getMessage());
                    }

                    Collection<DebitBean> debits = new ArrayList<DebitBean>();
                    for (Object debit : dbResults.getSearchResults()) {
                        debits.add((DebitBean) debit);
                    }
                    person.setDebits(debits);
                }
            }
        }

        if (loadDetails.getBoolean("GROUPS")) {
            // Create new SearchBean of type Member and default values
            SearchResultsBean results = new SearchResultsBean();
            SearchBean groupSearch = this.getSearchDAO().initiate("group", null);
            groupSearch.setLimit(0);

            GroupBean searchCriteria = (GroupBean) groupSearch.getSearchCriteria();
            searchCriteria.setObjectType("Members");
            ItemBean item = new ItemBean();
            item.setObject2GUID(person.getGUID());
            TreeMap<String, ItemBean> items = new TreeMap<String, ItemBean>();
            items.put("Supervisor", item);
            searchCriteria.setItems(items);

            groupSearch.setSearchCriteria(searchCriteria);

            try {
                BuilderBean loadGroup = new BuilderBean();
                loadGroup.setParameter("ITEMS", true);
                loadGroup.setParameter("REFERENCEID", String.valueOf(person.getGUID()));
                results = this.getSearchDAO().search(groupSearch, loadGroup);
            } catch (WhichDoctorSearchDaoException wdse) {
                dataLogger.error("Error loading groups for person: " + wdse.getMessage());
            }

            Collection<GroupBean> groups = new ArrayList<GroupBean>();
            for (Object group : results.getSearchResults()) {
                groups.add((GroupBean) group);
            }
            person.setGroups(groups);
        }

        if (loadDetails.getBoolean("RELATIONSHIPS")) {
            BuilderBean loadRelationships = new BuilderBean();
            if (loadDetails.getBoolean("RELATIONSHIPS_OBJECTS")) {
                loadRelationships.setParameter("RELATED_PERSON", true);
            }
            try {
                person.setRelationships(this.relationshipDAO.load(person.getGUID(), loadRelationships));
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error loading relationships for person: " + wde.getMessage());
            }
        }

        if (this.getFunctionality().isEnabled("Region Representatives")
                && loadDetails.getBoolean("REPRESENTATIVES")) {
            // Load the region representatives associated to this person
            if (StringUtils.isNotBlank(person.getRegion())) {
                ArrayList<PersonBean> representatives = new ArrayList<PersonBean>();

                // Create new SearchBean of type Member and default values
                SearchBean search = this.getSearchDAO().initiate("person", null);
                PersonBean searchCriteria = (PersonBean) search.getSearchCriteria();

                /* Set first and last name requirements */
                MembershipBean membershipCriteria = this.membershipDAO.getDefaultInstance();

                ObjectTypeBean object = new ObjectTypeBean();
                object.setClassName(person.getRegion());
                membershipCriteria.setField("Region Representative", object);
                ArrayList<MembershipBean> membershipCriteriaDetails = new ArrayList<MembershipBean>();

                membershipCriteriaDetails.add(membershipCriteria);
                searchCriteria.setMembershipDetails(membershipCriteriaDetails);

                search.setSearchCriteria(searchCriteria);

                SearchResultsBean results = new SearchResultsBean();
                try {
                    results = this.getSearchDAO().search(search);
                } catch (Exception e) {
                    dataLogger.error("Error searching for representatives: " + e.getMessage());
                }

                if (results.getSearchResults() != null) {
                    for (Object representative : results.getSearchResults()) {
                        representatives.add((PersonBean) representative);
                    }
                }
                person.setRegionRepresentatives(representatives);
            }
        }

        if (loadDetails.getBoolean("ISBENTITIES")) {
            // Load the ISB entity references this person has
            try {
                final Collection<IsbEntityBean> isbEntities = this.isbEntityDAO.loadAll(person.getGUID());
                person.setIsbEntities(isbEntities);
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error loading ISB entities: " + wde.getMessage());
            }
        }

        if (loadDetails.getBoolean("SUPERVISED")) {
            final HashMap<String, ArrayList<PersonBean>> supervised = loadSupervisedPeople(person.getGUID(),
                    loadDetails.getBoolean("SUPERVISED_ALLROTATIONS"));

            person.setCurrentlySupervising(supervised.get("current"));
            person.setPreviouslySupervised(supervised.get("previous"));
        }

        if (loadDetails.getBoolean("CREATED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("CreatedBy"));
            user.setPreferredName(rs.getString("CreatedFirstName"));
            user.setLastName(rs.getString("CreatedLastName"));
            person.setCreatedUser(user);
        }
        if (loadDetails.getBoolean("MODIFIED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("ModifiedBy"));
            user.setPreferredName(rs.getString("ModifiedFirstName"));
            user.setLastName(rs.getString("ModifiedLastName"));
            person.setModifiedUser(user);
        }
        if (loadDetails.getBoolean("EXPORTED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("ExportedBy"));
            user.setPreferredName(rs.getString("ExportedFirstName"));
            user.setLastName(rs.getString("ExportedLastName"));
            person.setExportedUser(user);
        }

        return person;
    }

    /**
     * Update the relevant search indexes.
     *
     * @param guid the guid
     * @param action the action
     */
    private void updateIndexes(final int guid, final String action) {

        try {
            updateRegion(guid);
        } catch (Exception e) {
            dataLogger.error("Error updating person region: " + e.getMessage());
        }
        try {
            updateResidentCountry(guid);
        } catch (Exception e) {
            dataLogger.error("Error updating person resident country: " + e.getMessage());
        }
        try {
            updateAddressIndex(guid, action);
        } catch (Exception e) {
            dataLogger.error("Error updating person city index: " + e.getMessage());
        }
        // Update the accreditation summary
        try {
            this.rotationDAO.recalculateAccreditationForPerson(guid);
        } catch (Exception e) {
            dataLogger.error("Error recalculating person training summary: " + e.getMessage());
        }
    }

    /**
     * Update the address index for person.
     *
     * @param guid the guid
     * @param action the action
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private void updateAddressIndex(final int guid, final String action) throws WhichDoctorDaoException {

        BuilderBean loadDetails = new BuilderBean();
        loadDetails.setParameter("ADDRESS", true);
        PersonBean person = loadGUID(guid, loadDetails);

        if (person != null && person.getFirstAddress() != null) {
            this.getAddressDAO().updateAddressIndexes(person.getFirstAddress(), action);
        }
    }

    /**
     * Update the region index for this person.
     *
     * @param guid the guid
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void updateRegion(final int guid) throws WhichDoctorDaoException {

        int regionId = 0;

        try {
            final Date currentDate = new Date(Calendar.getInstance().getTimeInMillis());

            regionId = this.getJdbcTemplateReader().queryForInt(this.getSQL().getValue("person/loadEmployerRegion"),
                    new Object[] { currentDate, currentDate, guid });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        // If no region id found, search to get the region for the person's address
        if (regionId == 0) {
            regionId = this.getAddressDAO().getRegionId(guid);
        }

        try {
            this.getSearchIndexDAO().update(guid, "Region", 0, 0, regionId);
        } catch (Exception e) {
            dataLogger.error("Error updating region index: " + e.getMessage());
        }
    }

    /**
     * Update the resident country index for this person.
     *
     * @param guid the guid
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void updateResidentCountry(final int guid) throws WhichDoctorDaoException {

        int stateCountryId = 0;

        try {
            final Date currentDate = new Date(Calendar.getInstance().getTimeInMillis());

            stateCountryId = this.getJdbcTemplateReader().queryForInt(
                    this.getSQL().getValue("person/loadEmployerCountry"),
                    new Object[] { currentDate, currentDate, guid });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        // If no state/country id found, search to get the id for the person's address
        if (stateCountryId == 0) {
            stateCountryId = this.getAddressDAO().getStateCountryId(guid);
        }

        try {
            this.getSearchIndexDAO().update(guid, "Resident Country", 0, 0, stateCountryId);
        } catch (Exception e) {
            dataLogger.error("Error updating resident country index: " + e.getMessage());
        }
    }

    /**
     * Recalculate all location search indexes.
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void recalculateAllLocationIndexes() throws WhichDoctorDaoException {

        dataLogger.info("Rebuilding search indexes for locations");

        Collection<PersonBean> people = this.loadActivePeople();

        for (PersonBean person : people) {
            try {
                updateAddressIndex(person.getGUID(), "update");
                updateRegion(person.getGUID());
                updateResidentCountry(person.getGUID());
                dataLogger.error("Refreshed location index for guid: " + person.getGUID());
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error(
                        "Error rebuilding person index for GUID: " + person.getGUID() + ", " + wde.getMessage());
            }
        }
    }

    /**
     * Recalculate all financial search indexes.
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void recalculateAllFinancialIndexes() throws WhichDoctorDaoException {

        dataLogger.info("Rebuilding search indexes for finance");

        Collection<PersonBean> people = this.loadActivePeople();

        for (PersonBean person : people) {
            try {
                this.getSearchIndexDAO().updateCurrentBalanceIndex(person.getGUID(), "person");
                dataLogger.error("Refreshed current balance index for guid: " + person.getGUID());
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error rebuilding current balance index for person: " + person.getGUID() + ", "
                        + wde.getMessage());
            }
        }
    }

    /**
     * Recalculates all training search indexes.
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void recalculateAllTrainingIndexes() throws WhichDoctorDaoException {

        dataLogger.info("Rebuilding search indexes for training");

        Collection<PersonBean> people = this.loadActivePeople();

        for (PersonBean person : people) {
            try {
                this.rotationDAO.recalculateAccreditationForPerson(person.getGUID());
                dataLogger.error("Refreshed training index for guid: " + person.getGUID());
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error rebuilding training index for person: " + person.getGUID() + ", "
                        + wde.getMessage());
            }
        }
    }

    /**
     * Generate personal identifier.
     *
     * @return the personal identifier
     */
    private final int generatePersonIdentifier() {

        int personalIdentifier = 0;

        try {
            personalIdentifier = this.getJdbcTemplateReader().queryForInt(
                    this.getSQL().getValue("person/findMaxPersonIdentifier"),
                    new Object[] { this.personIdentifierClass });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for search: " + ie.getMessage());
        }

        boolean unique = false;

        while (!unique) {
            personalIdentifier++;

            try {
                this.getJdbcTemplateReader().queryForInt(this.getSQL().getValue("person/uniquePersonIdentifier"),
                        new Object[] { personalIdentifier });

            } catch (IncorrectResultSizeDataAccessException ie) {
                unique = true;
            }
        }

        return personalIdentifier;
    }

    /**
     * Load a list of people this person has supervised in the past.
     *
     * @param guid the guid
     * @param allRotations the all rotations
     * @return the collection
     */
    private HashMap<String, ArrayList<PersonBean>> loadSupervisedPeople(final int guid,
            final boolean allRotations) {

        HashMap<String, ArrayList<PersonBean>> supervisedPeople = new HashMap<String, ArrayList<PersonBean>>();

        // Create new SearchBean of with default values
        SearchBean searchRotations = this.getSearchDAO().initiate("rotation", null);
        searchRotations.setLimit(0);

        RotationBean rotationParam = (RotationBean) searchRotations.getSearchCriteria();
        SupervisorBean supervisor = new SupervisorBean();
        supervisor.setPersonGUID(guid);
        rotationParam.addSupervisor(supervisor);

        BuilderBean loadDetails = new BuilderBean();
        loadDetails.setParameter("ASSESSMENTS", true);
        loadDetails.setParameter("SUPERVISORS", true);

        searchRotations.setSearchCriteria(rotationParam);
        searchRotations.setOrderColumn("rotation.StartDate");
        searchRotations.setOrderColumn2("people.LastName");
        searchRotations.setOrderAscending(false);

        SearchResultsBean studentsSupervised = new SearchResultsBean();
        try {
            studentsSupervised = this.getSearchDAO().search(searchRotations, loadDetails);
        } catch (Exception e) {
            dataLogger.error("Error searching for supervised people: " + e.getMessage());
        }

        final Calendar currentDate = Calendar.getInstance();

        final TreeMap<String, ArrayList<RotationBean>> currentlySupervising = new TreeMap<String, ArrayList<RotationBean>>();
        final TreeMap<String, ArrayList<RotationBean>> previouslySupervised = new TreeMap<String, ArrayList<RotationBean>>();
        final HashMap<String, PersonBean> personMap = new HashMap<String, PersonBean>();

        for (Object rotationObj : studentsSupervised.getSearchResults()) {
            final RotationBean rotation = (RotationBean) rotationObj;

            boolean currentlyTakingPlace = false;

            if (rotation.getStartDate().before(currentDate.getTime())
                    && rotation.getEndDate().after(currentDate.getTime())) {
                currentlyTakingPlace = true;
            }

            if (rotation.getPerson() != null) {
                final PersonBean person = rotation.getPerson();

                final String index = person.getLastName() + " " + person.getPreferredName() + " "
                        + person.getPersonIdentifier();

                boolean processed = false;

                if (currentlySupervising.containsKey(index)) {
                    // The person exists in the currently supervising list.
                    ArrayList<RotationBean> tneRots = currentlySupervising.get(index);
                    if (allRotations || currentlyTakingPlace) {
                        tneRots.add(rotation);
                    }
                    currentlySupervising.put(index, tneRots);
                    processed = true;
                }
                if (previouslySupervised.containsKey(index)) {
                    // The person exists in the previously supervised list
                    ArrayList<RotationBean> tneRots = previouslySupervised.get(index);
                    if (allRotations || currentlyTakingPlace) {
                        tneRots.add(rotation);
                    }
                    if (currentlyTakingPlace) {
                        // This is a current rotation, remove from the previously
                        // supervised list and add to currently supervising.
                        previouslySupervised.remove(index);
                        currentlySupervising.put(index, tneRots);
                    } else {
                        previouslySupervised.put(index, tneRots);
                    }
                    processed = true;
                }

                if (!processed) {
                    // This person has not been encountered yet.
                    personMap.put(index, person);

                    ArrayList<RotationBean> tneRots = new ArrayList<RotationBean>();
                    if (allRotations || currentlyTakingPlace) {
                        tneRots.add(rotation);
                    }
                    if (currentlyTakingPlace) {
                        currentlySupervising.put(index, tneRots);
                    } else {
                        previouslySupervised.put(index, tneRots);
                    }
                }
            }
        }

        final ArrayList<PersonBean> currentPeople = new ArrayList<PersonBean>();
        final ArrayList<PersonBean> previousPeople = new ArrayList<PersonBean>();

        for (String index : currentlySupervising.keySet()) {
            final PersonBean person = personMap.get(index);
            final ArrayList<RotationBean> tneRots = currentlySupervising.get(index);
            person.setRotations(tneRots);
            currentPeople.add(person);
        }
        for (String index : previouslySupervised.keySet()) {
            final PersonBean person = personMap.get(index);
            final ArrayList<RotationBean> tneRots = previouslySupervised.get(index);
            person.setRotations(tneRots);
            previousPeople.add(person);
        }

        supervisedPeople.put("current", currentPeople);
        supervisedPeople.put("previous", previousPeople);

        return supervisedPeople;
    }
}