Java tutorial
/******************************************************************************* * Copyright (c) 2010 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.beans.ObjectTypeBean; import com.sfs.beans.PrivilegesBean; import com.sfs.beans.UserBean; import com.sfs.dao.SFSDaoException; import com.sfs.whichdoctor.beans.PersonBean; import com.sfs.whichdoctor.beans.OnlineApplicationBean; import com.sfs.whichdoctor.dao.onlineapplication.OnlineApplicationHandler; import java.io.IOException; import java.io.StringReader; 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.Map; import java.util.TreeMap; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.input.SAXBuilder; import org.springframework.dao.DataAccessException; import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.jdbc.core.RowMapper; /** * The Class OnlineApplicationDAOImpl. */ public class OnlineApplicationDAOImpl extends BaseDAOImpl implements OnlineApplicationDAO { /** The data logger. */ private static Logger dataLogger = Logger.getLogger(OnlineApplicationDAOImpl.class); /** The default status. */ private String defaultStatus; /** The default type. */ private String defaultType; /** The online application handlers. */ private Map<String, OnlineApplicationHandler> onlineApplicationHandlers; /** The PROCESSED_ORDER_ID. */ private static final int PROCESSED_ORDER_ID = 999; /** * Sets the default status. * * @param status the new default status */ public final void setDefaultStatus(final String status) { this.defaultStatus = status; } /** * Sets the default type. * * @param type the new default type */ public final void setDefaultType(final String type) { this.defaultType = type; } /** * Sets the online application handlers. * * @param onlineApplicationHandlerMap the online application handlers */ public final void setApplicationHandlers( final Map<String, OnlineApplicationHandler> onlineApplicationHandlerMap) { this.onlineApplicationHandlers = onlineApplicationHandlerMap; } /** * Used to get a OnlineApplicationBean for the the specified online application id. * Returns null if no online application found * * @param onlineApplicationId the online application id * * @return the online application bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final OnlineApplicationBean load(final int onlineApplicationId) throws WhichDoctorDaoException { dataLogger.info("Online application id: " + onlineApplicationId + " requested"); OnlineApplicationBean onlineApplication = null; try { onlineApplication = (OnlineApplicationBean) this.getJdbcTemplateReader().queryForObject( this.getSQL().getValue("onlineapplication/loadId"), new Object[] { onlineApplicationId }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadOnlineApplicationBean(rs); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for this search: " + ie.getMessage()); } return onlineApplication; } /** * Used to get a OnlineApplicationBean for the the specified online application key. * Returns null if no online application found * * @param key the online application key * @param type the online application type * * @return the online application bean * * @throws WhichDoctorDaoException the which doctor dao exception */ public final OnlineApplicationBean load(final String key, final String type) throws WhichDoctorDaoException { dataLogger.info("Online application key: " + key + " requested"); OnlineApplicationBean onlineApplication = null; try { onlineApplication = (OnlineApplicationBean) this.getJdbcTemplateReader().queryForObject( this.getSQL().getValue("onlineapplication/loadKey"), new Object[] { key, type }, new RowMapper() { public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException { return loadOnlineApplicationBean(rs); } }); } catch (IncorrectResultSizeDataAccessException ie) { dataLogger.debug("No results found for this search: " + ie.getMessage()); } return onlineApplication; } /** * Create or update the OnlineApplicationBean. * If an application exists with the same key or id value then update the existing. * * @param onlineApplication the online application * * @return the Id of the created OnlineApplication if successful * * @throws WhichDoctorDaoException the which doctor dao exception */ public final int createOrUpdate(final OnlineApplicationBean onlineApplication) throws WhichDoctorDaoException { if (StringUtils.isBlank(onlineApplication.getKey())) { throw new WhichDoctorDaoException("The online application requires a " + "valid key"); } if (StringUtils.isBlank(onlineApplication.getFirstName())) { throw new WhichDoctorDaoException("The online application requires a " + "valid first name"); } if (StringUtils.isBlank(onlineApplication.getLastName())) { throw new WhichDoctorDaoException("The online application requires a " + "valid last name"); } int onlineApplicationId = 0; boolean updateOperation = false; if (StringUtils.isNotBlank(onlineApplication.getKey())) { // Check to see if an unprocessed online application with this key exists try { final OnlineApplicationBean existingApplication = this.load(onlineApplication.getKey(), onlineApplication.getType()); if (existingApplication != null) { // An online application exists with this key and type, check the id updateOperation = true; if (onlineApplication.getId() == 0) { onlineApplication.setId(existingApplication.getId()); } if (existingApplication.getId() != onlineApplication.getId() && existingApplication.getProcessed()) { // The two applications have different internal identifiers and // the existing application is unprocessed - throw exception. throw new WhichDoctorDaoException("A different online application" + " with the same key already exists - potential conflict" + ", so change not recorded"); } } } catch (WhichDoctorDaoException wde) { dataLogger.error("Error loading online application: " + wde.getMessage()); } } // Load the status and type ids (can throw an exception) Integer[] statusIdDetails = getStatusIdDetails(onlineApplication.getType(), onlineApplication.getStatus(), onlineApplication.getRecordNumber()); // If the order Id = PROCESSED_ORDER_ID then the application is processed int statusId = statusIdDetails[0]; int orderId = statusIdDetails[1]; onlineApplication.setProcessed(false); if (orderId == PROCESSED_ORDER_ID) { onlineApplication.setProcessed(true); } if (updateOperation) { // Update the existing online application entry // Set the timestamp value Timestamp updateTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); try { final int updateCount = this.getJdbcTemplateWriter().update( this.getSQL().getValue("onlineapplication/modify"), new Object[] { onlineApplication.getKey(), onlineApplication.getFirstName(), onlineApplication.getLastName(), onlineApplication.getPersonGUID(), onlineApplication.getApplicationXml(), statusId, onlineApplication.getProcessed(), updateTimeStamp, onlineApplication.getId() }); if (updateCount > 0) { onlineApplicationId = onlineApplication.getId(); } } catch (DataAccessException de) { dataLogger.error("Error updating the online application: " + de.getMessage()); } } else { // Create a new online application entry // Set the timestamp value Timestamp creationTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis()); try { final int createCount = this.getJdbcTemplateWriter().update( this.getSQL().getValue("onlineapplication/create"), new Object[] { onlineApplication.getKey(), onlineApplication.getFirstName(), onlineApplication.getLastName(), onlineApplication.getPersonGUID(), onlineApplication.getApplicationXml(), statusId, onlineApplication.getProcessed(), creationTimeStamp, creationTimeStamp }); if (createCount > 0) { // Get the maximum id onlineApplicationId = this.getJdbcTemplateReader() .queryForInt(this.getSQL().getValue("onlineapplication/findMax")); } } catch (DataAccessException de) { dataLogger.error("Error creating the online application: " + de.getMessage()); } } return onlineApplicationId; } /** * Delete the OnlineApplicationBean. * * @param onlineApplication the online application * @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 OnlineApplicationBean onlineApplication, final UserBean checkUser, final PrivilegesBean privileges) throws WhichDoctorDaoException { if (!privileges.getPrivilege(checkUser, "systemAdmin", "delete")) { throw new WhichDoctorDaoException("Insufficient user credentials " + "to delete online application"); } boolean success = false; final String deleteSQL = this.getSQL().getValue("onlineapplication/delete"); try { final int deleteCount = this.getJdbcTemplateWriter().update(deleteSQL, new Object[] { onlineApplication.getId() }); dataLogger.info("Online application records deleted: " + deleteCount); if (deleteCount > 0) { success = true; } } catch (DataAccessException de) { dataLogger.error("Error deleting online application: " + de.getMessage()); } return success; } /** * Gets the next step for the application. * * @param onlineApplication the online application * @return the next step */ public final String[] getNextStep(final OnlineApplicationBean onlineApplication) { String step = ""; String recordNumber = ""; Collection<ObjectTypeBean> objectTypes = new ArrayList<ObjectTypeBean>(); Map<Integer, String> statuses = new TreeMap<Integer, String>(); try { objectTypes = this.getObjectTypeDAO().load("Application Status"); } catch (SFSDaoException sfe) { dataLogger.error("Error loading list of application statuses: " + sfe.getMessage()); } String type = onlineApplication.getType(); String currentStatus = onlineApplication.getStatus(); String currentRecordId = onlineApplication.getRecordNumber(); if (objectTypes != null) { for (ObjectTypeBean objectType : objectTypes) { if (StringUtils.equalsIgnoreCase(type, objectType.getClassName())) { // This is of the type we are interested in String recordId = ""; if (StringUtils.isNotBlank(objectType.getAbbreviation())) { recordId = objectType.getAbbreviation().trim(); } int orderId = (int) objectType.getValue(); String key = objectType.getName() + "_" + recordId; statuses.put(orderId, key); if (dataLogger.isDebugEnabled()) { dataLogger.debug("Status id: " + orderId); dataLogger.debug("Status key: " + key); } } } } Document xml = null; try { xml = parseXmlApplication(onlineApplication.getApplicationXml()); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error parsing application XML: " + wde.getMessage()); } boolean setNextValue = false; for (Integer orderId : statuses.keySet()) { String value = statuses.get(orderId); String nextStep = StringUtils.substringBefore(value, "_"); String recordId = StringUtils.substringAfter(value, "_"); if (dataLogger.isDebugEnabled()) { dataLogger.debug("Status id: " + orderId); dataLogger.debug("Status raw value: " + value); dataLogger.debug("Next status step: " + nextStep); dataLogger.debug("Record id: '" + recordId + "'"); dataLogger.debug("Current record id: '" + currentRecordId + "'"); } // If the currentStatus == value then the next value is the step if (StringUtils.equalsIgnoreCase(currentStatus, nextStep) && StringUtils.equalsIgnoreCase(currentRecordId, recordId)) { setNextValue = true; dataLogger.debug(nextStep + " is the current status value"); } else { dataLogger.debug("Validating: '" + nextStep + "' - '" + recordId + "'"); // If nextValue is set the next step to the value if (setNextValue && validateNextStep(xml, nextStep, onlineApplication.getType(), recordId)) { step = nextStep; recordNumber = recordId; // Reset to false setNextValue = false; } } if (dataLogger.isDebugEnabled()) { dataLogger.debug("Loop next step value: " + step); dataLogger.debug("Loop record id value: " + recordNumber); } } String[] statusDetails = { step, recordNumber }; return statusDetails; } /** * Validate the next step. * * @param xml the xml * @param nextStep the next step * @param type the type * @param recordNumber the record number * @return true, if successful */ private boolean validateNextStep(final Document xml, final String nextStep, final String type, final String recordNumber) { boolean validStep = false; dataLogger.debug("Validating step: '" + nextStep + "' - '" + recordNumber + "'"); OnlineApplicationHandler hd = null; if (this.onlineApplicationHandlers != null && StringUtils.isNotBlank(type)) { if (this.onlineApplicationHandlers.containsKey(type)) { hd = this.onlineApplicationHandlers.get(type); } } if (hd != null && xml != null) { dataLogger.debug("Using handler to validate the step '" + nextStep + "' - '" + recordNumber + "'"); validStep = hd.validateNextStep(nextStep, xml, recordNumber); dataLogger.info(validStep + " is a valid step"); } return validStep; } /** * Parses the xml application. * * @param applicationXML the application xml * @return the document * @throws WhichDoctorDaoException the which doctor dao exception */ public final Document parseXmlApplication(final String applicationXML) throws WhichDoctorDaoException { Document document = null; try { SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser"); StringReader reader = new StringReader(applicationXML); try { document = builder.build(reader); } catch (Exception e) { throw new IOException(e.getMessage()); } } catch (Exception e) { dataLogger.fatal("Error parsing application XML: " + e.getMessage()); throw new WhichDoctorDaoException("Error parsing application XML: " + e.getMessage()); } return document; } /** * Gets the next JSP key for the application. * * @param onlineApplication the online application * @param user the user * @param privileges the privileges * @return the next step * @throws WhichDoctorDaoException the which doctor dao exception */ public final String getNextJSPKey(final OnlineApplicationBean onlineApplication, final UserBean user, final PrivilegesBean privileges) throws WhichDoctorDaoException { String key = ""; // Get the relevant online application handler if (this.onlineApplicationHandlers != null && onlineApplication != null) { String type = onlineApplication.getType(); if (this.onlineApplicationHandlers.containsKey(type)) { OnlineApplicationHandler hd = this.onlineApplicationHandlers.get(type); key = hd.getNextJSPKey(onlineApplication, user, privileges); } } return key; } /** * Gets the next request. * * @param onlineApplication the online application * @return the map of objects * @throws WhichDoctorDaoException the which doctor dao exception */ public final Map<String, Object> getNextObjects(final OnlineApplicationBean onlineApplication) throws WhichDoctorDaoException { Map<String, Object> objects = null; // Get the relevant online application handler if (this.onlineApplicationHandlers != null && onlineApplication != null) { Document xml = this.parseXmlApplication(onlineApplication.getApplicationXml()); String type = onlineApplication.getType(); if (this.onlineApplicationHandlers.containsKey(type)) { OnlineApplicationHandler hd = this.onlineApplicationHandlers.get(type); objects = hd.getNextObjects(onlineApplication, xml); } } if (objects == null) { objects = new TreeMap<String, Object>(); } return objects; } /** * Gets the existing record, returns null if none exists. * * @param onlineApplication the online application * @return the existing record * @throws WhichDoctorDaoException the which doctor dao exception */ public final PersonBean getExistingRecord(final OnlineApplicationBean onlineApplication) throws WhichDoctorDaoException { PersonBean existingRecord = null; // Get the relevant online application handler if (this.onlineApplicationHandlers != null && onlineApplication != null) { String type = onlineApplication.getType(); if (this.onlineApplicationHandlers.containsKey(type)) { OnlineApplicationHandler hd = this.onlineApplicationHandlers.get(type); Document xml = this.parseXmlApplication(onlineApplication.getApplicationXml()); existingRecord = hd.getExistingRecord(xml); } } return existingRecord; } /** * Gets the existing record, returns "Unprocessed" by default. * * @param onlineApplication the online application * @return the step in an existing record */ public final String[] stepIfExistingRecord(final OnlineApplicationBean onlineApplication) { String[] stepIfExistingRecord = { "Unprocessed", "" }; // Get the relevant online application handler if (this.onlineApplicationHandlers != null && onlineApplication != null) { String type = onlineApplication.getType(); if (this.onlineApplicationHandlers.containsKey(type)) { OnlineApplicationHandler hd = this.onlineApplicationHandlers.get(type); stepIfExistingRecord = hd.stepIfExistingRecord(); } } return stepIfExistingRecord; } /** * Load online application bean. * * @param rs the result set * * @return the online application bean * * @throws SQLException the SQL exception */ private OnlineApplicationBean loadOnlineApplicationBean(final ResultSet rs) throws SQLException { OnlineApplicationBean onlineApplication = new OnlineApplicationBean(); onlineApplication.setId(rs.getInt("OnlineApplicationId")); onlineApplication.setKey(rs.getString("ApplicationKey")); onlineApplication.setFirstName(rs.getString("FirstName")); onlineApplication.setLastName(rs.getString("LastName")); onlineApplication.setPersonGUID(rs.getInt("PersonGUID")); onlineApplication.setApplicationXml(rs.getString("ApplicationXML")); onlineApplication.setStatus(rs.getString("Status")); onlineApplication.setRecordNumber(rs.getString("RecordNumber")); onlineApplication.setType(rs.getString("Type")); onlineApplication.setProcessed(rs.getBoolean("Processed")); try { onlineApplication.setCreatedDate(rs.getTimestamp("Created")); } catch (SQLException e) { dataLogger.debug("Error reading Created date: " + e.getMessage()); } try { onlineApplication.setModifiedDate(rs.getTimestamp("Modified")); } catch (SQLException e) { dataLogger.debug("Error reading Modified date: " + e.getMessage()); } if (!onlineApplication.getProcessed() && onlineApplication.getPersonGUID() == 0 && StringUtils.equals(onlineApplication.getStatus(), "Unprocessed")) { // Check to see if a relevant person already exists try { onlineApplication.setExistingRecord(this.getExistingRecord(onlineApplication)); } catch (WhichDoctorDaoException wde) { dataLogger.error("Error searching for an existing person: " + wde.getMessage()); } } return onlineApplication; } /** * Gets the status id. * * @param typeVal the type val * @param statusVal the status val * @param recordId the record id * @return the status id details * @throws WhichDoctorDaoException the which doctor dao exception */ private Integer[] getStatusIdDetails(final String typeVal, final String statusVal, final String recordId) throws WhichDoctorDaoException { int statusId = 0; int orderId = 0; String type = this.defaultType; String status = this.defaultStatus; String recordNumber = ""; if (StringUtils.isNotBlank(typeVal)) { type = typeVal; } if (StringUtils.isNotBlank(statusVal)) { status = statusVal; } if (StringUtils.isNotBlank(recordId)) { recordNumber = recordId; } if (dataLogger.isDebugEnabled()) { dataLogger.debug("Status class: " + type); dataLogger.debug("Status: " + status); dataLogger.debug("Record number: " + recordNumber); } try { ObjectTypeBean object = this.getObjectTypeDAO().load("Application Status", recordNumber, status, type); statusId = object.getObjectTypeId(); orderId = (int) object.getValue(); } catch (SFSDaoException sfe) { dataLogger.error("Error loading objecttype for application status: " + sfe.getMessage()); throw new WhichDoctorDaoException("Online application requires " + "a valid status"); } Integer[] statusIdDetails = { statusId, orderId }; return statusIdDetails; } }