Java tutorial
/******************************************************************************* * 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; } }