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

Java tutorial

Introduction

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

Source

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