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

Java tutorial

Introduction

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

Source

/*******************************************************************************
 * Copyright (c) 2012 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 java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.annotation.Resource;

import com.sfs.beans.BuilderBean;
import com.sfs.beans.PrivilegesBean;
import com.sfs.beans.UserBean;
import com.sfs.whichdoctor.beans.OnlineToolBean;
import com.sfs.whichdoctor.beans.PersonBean;
import com.sfs.whichdoctor.beans.RotationBean;
import com.sfs.whichdoctor.beans.SearchBean;
import com.sfs.whichdoctor.beans.SearchResultsBean;
import com.sfs.whichdoctor.search.SearchDAO;
import com.sfs.whichdoctor.search.WhichDoctorSearchDaoException;
import com.sfs.whichdoctor.webservice.OnlineToolsQuery;
import com.sfs.whichdoctor.webservice.WhichDoctorWebserviceException;

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

/**
 * The Class OnlineToolDAOImpl.
 *
 * @author David Harrison
 */
public class OnlineToolDAOImpl extends BaseDAOImpl implements OnlineToolDAO {

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

    /** The online tools query. */
    @Resource
    private OnlineToolsQuery onlineToolsQuery;

    /** The person dao. */
    @Resource
    private PersonDAO personDAO;

    /** The search dao. */
    @Resource
    private SearchDAO searchDAO;

    /** The training status dao. */
    @Resource
    private TrainingStatusDAO trainingStatusDAO;

    /**
     * Loads the requested online tool bean based on its id.
     *
     * @param referenceGUID the reference GUID
     *
     * @return the collection< online tool bean>
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final OnlineToolBean loadId(final int onlineToolId) throws WhichDoctorDaoException {

        OnlineToolBean onlineTool = null;

        try {
            onlineTool = this.getJdbcTemplateReader().queryForObject(this.getSQL().getValue("onlineTool/loadId"),
                    new Object[] { onlineToolId }, new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadOnlineTool(rs);
                        }
                    });

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

        return onlineTool;
    }

    /**
     * Loads an array of online tool beans for the supplied reference GUID.
     *
     * @param referenceGUID the reference GUID
     *
     * @return the collection< online tool bean>
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final Collection<OnlineToolBean> load(final int referenceGUID) throws WhichDoctorDaoException {

        Collection<OnlineToolBean> onlineTools = new ArrayList<OnlineToolBean>();

        try {
            onlineTools = this.getJdbcTemplateReader().query(this.getSQL().getValue("onlineTool/load"),
                    new Object[] { referenceGUID }, new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadOnlineTool(rs);
                        }
                    });

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

        return onlineTools;
    }

    /**
     * Loads an array of online tool beans for the supplied rotation GUID.
     *
     * @param rotationGUID the rotation GUID
     *
     * @return the collection< online tool bean>
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final Collection<OnlineToolBean> loadRotation(final int rotationGUID) throws WhichDoctorDaoException {

        Collection<OnlineToolBean> onlineTools = new ArrayList<OnlineToolBean>();

        try {
            onlineTools = this.getJdbcTemplateReader().query(this.getSQL().getValue("onlineTool/loadRotation"),
                    new Object[] { rotationGUID }, new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadOnlineTool(rs);
                        }
                    });

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

        return onlineTools;
    }

    /**
     * Loads all of the online tool beans.
     *
     * @return the collection< online tool bean>
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    @SuppressWarnings("unchecked")
    public final Collection<OnlineToolBean> loadAll() throws WhichDoctorDaoException {

        Collection<OnlineToolBean> onlineTools = new ArrayList<OnlineToolBean>();

        try {
            onlineTools = this.getJdbcTemplateReader().query(this.getSQL().getValue("onlineTool/loadAll"),
                    new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadOnlineTool(rs);
                        }
                    });

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

        return onlineTools;
    }

    /**
     * This method creates a new online tool record.
     *
     * @param onlineTool the online tool bean
     *
     * @return the new online tool record
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final OnlineToolBean create(final OnlineToolBean onlineTool) throws WhichDoctorDaoException {

        if (onlineTool == null) {
            throw new WhichDoctorDaoException("The online tool cannot be null");
        }
        if (onlineTool.getReferenceGUID() == 0) {
            throw new WhichDoctorDaoException("The online tool requires a valid reference GUID");
        }
        if (StringUtils.isBlank(onlineTool.getName())) {
            throw new WhichDoctorDaoException("The online tool requires a name");
        }
        onlineTool.setRotationGUID(determineRotationGUID(onlineTool));

        OnlineToolBean ot = null;

        try {
            int createCount = this.getJdbcTemplateWriter().update(this.getSQL().getValue("onlineTool/create"),
                    new Object[] { onlineTool.getReferenceGUID(), onlineTool.getRotationGUID(),
                            onlineTool.getRotationOverridden(), onlineTool.getName(), onlineTool.getShortName(),
                            onlineTool.getCourse(), onlineTool.getStartDate(), onlineTool.getEndDate(),
                            onlineTool.getStatus(), onlineTool.getSubmitted(), onlineTool.getCompleted(),
                            onlineTool.getYear() });

            if (createCount > 0) {
                // Get the highest id
                int id = this.getJdbcTemplateReader().queryForInt(this.getSQL().getValue("onlineTool/findMax"));

                ot = this.loadId(id);
            }

        } catch (Exception e) {
            dataLogger.error("Error creating online tool record: " + e.getMessage());
            throw new WhichDoctorDaoException("Error creating online tool record: " + e.getMessage());
        }

        return ot;
    }

    /**
     * This method modifies an online tool record.
     *
     * @param onlineTool the online tool bean
     * @param checkUser the check user
     * @param privileges the privileges
     * @return the modified online tool record
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final OnlineToolBean modify(final OnlineToolBean onlineTool, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {

        OnlineToolBean ot = null;

        if (!privileges.getPrivilege(checkUser, "assessments", "modify")) {
            throw new WhichDoctorDaoException("Insufficient user credentials to " + " modify online tool");
        }

        if (onlineTool != null && onlineTool.getId() > 0) {
            ot = loadId(onlineTool.getId());

            if (ot != null) {
                // For now only allow changing of the rotation details
                ot.setRotationGUID(onlineTool.getRotationGUID());
                ot.setRotationOverridden(onlineTool.getRotationOverridden());

                try {
                    int modifyCount = this.getJdbcTemplateWriter().update(
                            this.getSQL().getValue("onlineTool/modify"),
                            new Object[] { onlineTool.getRotationGUID(), onlineTool.getRotationOverridden(),
                                    onlineTool.getId() });

                    if (modifyCount == 0) {
                        // The online tool was not updated, invalidate
                        ot = null;
                    }
                } catch (Exception e) {
                    dataLogger.error("Error updating online tool record: " + e.getMessage());
                    throw new WhichDoctorDaoException("Error updating online tool record: " + e.getMessage());
                }
            }
        }

        return ot;
    }

    /**
     * This method deletes an online tool record.
     *
     * @param onlineTool the onlineTool
     *
     * @return true, if delete
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final boolean delete(final OnlineToolBean onlineTool) throws WhichDoctorDaoException {

        if (onlineTool == null) {
            throw new WhichDoctorDaoException("The online tool cannot be null");
        }
        if (onlineTool.getId() == 0) {
            throw new WhichDoctorDaoException("A valid online tool id is required");
        }

        boolean success = false;

        try {
            int deleteCount = this.getJdbcTemplateWriter().update(this.getSQL().getValue("onlineTool/delete"),
                    new Object[] { onlineTool.getId() });

            if (deleteCount > 0) {
                success = true;
            }
        } catch (Exception e) {
            dataLogger.error("Error deleting online tool record (" + onlineTool.getId() + "): " + e.getMessage());
            throw new WhichDoctorDaoException("Error deleting online tool record: " + e.getMessage());
        }

        return success;
    }

    /**
     * This method deletes the online tools associated with the supplied reference GUID.
     *
     * @param referenceGUID the reference GUID
     *
     * @return true, if delete
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final boolean delete(final int referenceGUID) throws WhichDoctorDaoException {

        if (referenceGUID == 0) {
            throw new WhichDoctorDaoException("A valid reference GUID is required");
        }

        boolean success = false;

        try {
            int deleteCount = this.getJdbcTemplateWriter().update(this.getSQL().getValue("onlineTool/deleteGUID"),
                    new Object[] { referenceGUID });

            if (deleteCount > 0) {
                success = true;
            }
        } catch (Exception e) {
            dataLogger.error(
                    "Error deleting online tools for reference GUID (" + referenceGUID + "): " + e.getMessage());
            throw new WhichDoctorDaoException("Error deleting online tool records: " + e.getMessage());
        }

        return success;
    }

    /**
     * This method deletes all of the recorded online tool information.
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void deleteAll() throws WhichDoctorDaoException {

        try {
            this.getJdbcTemplateWriter().update(this.getSQL().getValue("onlineTool/deleteAll"));

        } catch (Exception e) {
            dataLogger.error("Error deleting all online tool records: " + e.getMessage());
            throw new WhichDoctorDaoException("Error deleting all online tool records: " + e.getMessage());
        }
    }

    /**
     * Rebuild the cache of online tool data for the supplied reference GUID.
     *
     * @param person the person bean
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final void rebuildCache(final PersonBean person) {

        try {
            Collection<OnlineToolBean> tools = this.onlineToolsQuery
                    .getToolsDetailInfo(person.getPersonIdentifier());

            // Delete any existing tools
            this.delete(person.getGUID());

            if (tools != null) {
                for (OnlineToolBean tool : tools) {
                    try {
                        this.create(tool);
                    } catch (WhichDoctorDaoException wde) {
                        dataLogger.error(
                                "Error recording tool for person (" + person.getGUID() + "): " + wde.getMessage());
                    }
                }
            }
            // Recalculate the person's training status based on the new tool cache
            this.trainingStatusDAO.calculate(person.getGUID());

        } catch (WhichDoctorWebserviceException wse) {
            dataLogger.error("Error loading tool info for person (" + person.getGUID() + "): " + wse.getMessage());
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error(
                    "Error deleting existing tools for person (" + person.getGUID() + "): " + wde.getMessage());
        }
    }

    /**
     * Rebuild all of the online tool caches.
     */
    public final void rebuildAllCaches() {

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

        try {
            people = personDAO.loadActivePeople();
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error("Error loading all active people: " + wde.getMessage());
        }
        if (people != null) {
            for (PersonBean person : people) {
                rebuildCache(person);
            }
        }
    }

    /**
     * Rebuild all the active trainee caches.
     */
    public final void rebuildAllActiveTraineeCaches() {

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

        // Load the people who are 'active'
        // and have a training status that is not 'Not in training'
        SearchBean findPeople = this.searchDAO.initiate("person", new UserBean());
        findPeople.setLimit(0);
        findPeople.setAction("Subtract");

        PersonBean criteria = (PersonBean) findPeople.getSearchCriteria();
        criteria.setTrainingStatus("Not in training");
        findPeople.setSearchCriteria(criteria);

        try {
            SearchResultsBean personResults = this.searchDAO.search(findPeople);

            if (personResults != null) {
                people = new ArrayList<PersonBean>();
                for (Object result : personResults.getSearchResults()) {
                    people.add((PersonBean) result);
                }
            }
        } catch (WhichDoctorSearchDaoException wse) {
            dataLogger.error("Error loading all current trainees: " + wse.getMessage());
        }

        dataLogger.error("Trainees found: " + people.size());

        if (people != null) {
            for (PersonBean person : people) {
                rebuildCache(person);
            }
        }
    }

    /**
     * Rebuild the rotation GUID relationships for the supplied person GUID.
     * Note - Skipped if the RotationOverridden flag is set to true for the online tool.
     *
     * @param personGUID the person GUID
     * @param checkUser the user
     * @param privileges the privileges
     */
    public final void rebuildRotationRelationships(final int personGUID, final UserBean checkUser,
            final PrivilegesBean privileges) {

        Collection<OnlineToolBean> onlineTools = null;

        try {
            onlineTools = load(personGUID);
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error("Error loading online tools for person GUID " + personGUID + ": " + wde.getMessage());
        }

        updateOnlineToolsRelationships(onlineTools, checkUser, privileges);
    }

    /**
     * Rebuild all the rotation GUID relationships.
     * Note - Skipped if the RotationOverridden flag is set to true for the online tool.
     *
     * @param checkUser the user
     * @param privileges the privileges
     */
    public final void rebuildAllRotationRelationships(final UserBean checkUser, final PrivilegesBean privileges) {

        Collection<OnlineToolBean> onlineTools = null;

        try {
            onlineTools = loadAll();
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error("Error loading all online tools: " + wde.getMessage());
        }

        updateOnlineToolsRelationships(onlineTools, checkUser, privileges);
    }

    /**
     * Update online tools relationship.
     *
     * @param onlineTools the online tools
     * @param checkUser the check user
     * @param privileges the privileges
     */
    private void updateOnlineToolsRelationships(final Collection<OnlineToolBean> onlineTools,
            final UserBean checkUser, final PrivilegesBean privileges) {

        if (onlineTools != null) {
            for (OnlineToolBean ot : onlineTools) {
                if (!ot.getRotationOverridden()) {
                    ot.setRotationGUID(determineRotationGUID(ot));
                    try {
                        modify(ot, checkUser, privileges);
                    } catch (WhichDoctorDaoException wde) {
                        dataLogger.error("Error updating online tool: " + wde.getMessage());
                    }
                }
            }
        }
    }

    /**
     * Determine the rotation guid. If the rotation overridden flag
     * is set the existing GUID (if any) is returned.
     *
     * @param ot the online tool
     * @return the int
     */
    private int determineRotationGUID(final OnlineToolBean ot) {

        int rotationGUID = 0;

        if (ot != null) {
            if (ot.getRotationOverridden()) {
                rotationGUID = ot.getRotationGUID();
            } else {
                // Identify the relevant rotations
                Map<String, RotationBean> rts = new TreeMap<String, RotationBean>();

                if (ot.getReferenceGUID() > 0) {
                    try {
                        BuilderBean loadDetails = new BuilderBean();
                        loadDetails.setParameter("TRAINING_ROTATIONS", true);

                        PersonBean person = this.personDAO.loadGUID(ot.getReferenceGUID(), loadDetails);

                        if (person != null && person.getRotations() != null) {

                            dataLogger.info("Person " + person.getGUID() + " associated with rotation");

                            for (RotationBean r : person.getRotations()) {
                                Date[] dates = { ot.getStartDate(), ot.getEndDate(), ot.getSubmitted(),
                                        ot.getCompleted() };

                                for (Date date : dates) {
                                    if (date != null) {
                                        dataLogger.info("Tool date: " + date);

                                        if (date.compareTo(r.getStartDate()) >= 0
                                                && date.compareTo(r.getEndDate()) <= 0) {
                                            rts.put(buildKey(r.getStartDate(), r.getGUID()), r);

                                            dataLogger.info("Date after rotation " + r.getGUID()
                                                    + " start date and before its end");
                                        }
                                    }
                                }
                            }
                        }
                    } catch (WhichDoctorDaoException wde) {
                        dataLogger.error("Error checking for relevant rotations: " + wde.getMessage());
                    }
                }

                // If rts.size() == 0 then there is no obvious relationship.

                if (rts.size() == 1) {
                    // A single rotation was identified - set the relationship
                    rotationGUID = rts.values().iterator().next().getGUID();
                }

                if (rts.size() > 1) {
                    // More than one rotation was found - determine most appropriate
                    double percentage = 0;

                    for (String key : rts.keySet()) {
                        RotationBean r = rts.get(key);

                        if (rotationGUID == 0) {
                            rotationGUID = r.getGUID();
                        }

                        if (ot.getStartDate() != null) {
                            // Determine what percentage of the online tool was
                            // undertaken during the rotation.
                            double rPercentage = 0;
                            long otTime = 0;
                            Date pStartDate = new Date(ot.getStartDate().getTime());
                            Date pEndDate = new Date(r.getEndDate().getTime());

                            Date[] dates = { ot.getSubmitted(), ot.getEndDate(), ot.getCompleted() };

                            if (r.getStartDate().compareTo(ot.getStartDate()) > 0) {
                                pStartDate = new Date(r.getStartDate().getTime());
                            }

                            for (Date date : dates) {
                                if (date != null) {
                                    otTime = date.getTime() - ot.getStartDate().getTime();

                                    if (r.getEndDate().compareTo(date) > 0) {
                                        pEndDate = new Date(date.getTime());
                                    }
                                }
                            }

                            if (otTime > 0) {
                                rPercentage = (pEndDate.getTime() - pStartDate.getTime()) / otTime;

                                dataLogger.info("Calculated percentage: " + rPercentage);
                            }

                            if (rPercentage > percentage) {
                                dataLogger.info("Current percentage higher than " + percentage);

                                percentage = rPercentage;
                                rotationGUID = r.getGUID();
                            }
                        }
                    }
                }
            }
        }

        dataLogger.info("Rotation GUID " + rotationGUID + " identified");
        return rotationGUID;
    }

    /**
     * Load online tool bean from the result set.
     *
     * @param rs the rs
     * @return the online tool bean
     * @throws SQLException the sQL exception
     */
    private OnlineToolBean loadOnlineTool(final ResultSet rs) throws SQLException {

        OnlineToolBean onlineTool = new OnlineToolBean();

        onlineTool.setId(rs.getInt("OnlineToolId"));
        onlineTool.setReferenceGUID(rs.getInt("ReferenceGUID"));
        onlineTool.setRotationGUID(rs.getInt("RotationGUID"));
        onlineTool.setRotationOverridden(rs.getBoolean("RotationOverridden"));
        onlineTool.setName(rs.getString("Name"));
        onlineTool.setShortName(rs.getString("ShortName"));
        onlineTool.setCourse(rs.getString("Course"));
        onlineTool.setStatus(rs.getString("Status"));
        onlineTool.setYear(rs.getInt("Year"));
        onlineTool.setRotationName(rs.getString("RotationName"));

        try {
            onlineTool.setStartDate(rs.getTimestamp("StartDate"));
        } catch (SQLException sqe) {
            dataLogger.debug("Error reading StartDate: " + sqe.getMessage());
        }

        try {
            onlineTool.setEndDate(rs.getTimestamp("EndDate"));
        } catch (SQLException sqe) {
            dataLogger.debug("Error reading EndDate: " + sqe.getMessage());
        }

        try {
            onlineTool.setSubmitted(rs.getTimestamp("Submitted"));
        } catch (SQLException sqe) {
            dataLogger.debug("Error reading SubmittedDate: " + sqe.getMessage());
        }

        try {
            onlineTool.setCompleted(rs.getTimestamp("Completed"));
        } catch (SQLException sqe) {
            dataLogger.debug("Error reading CompletedDate: " + sqe.getMessage());
        }

        return onlineTool;
    }

    /**
     * Build the rotation key
     * @param date the date
     * @param guid the GUID
     * @return a string key
     */
    private final String buildKey(final Date date, final Integer guid) {
        return date.getTime() + "_" + guid;
    }

}