Package org.any_openeai_enterprise.gateways.warehouse

Source Code of org.any_openeai_enterprise.gateways.warehouse.EnterpriseWarehouseCommand

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/examples/org/any_openeai_enterprise/gateways/warehouse/EnterpriseWarehouseCommand.java,v $
$Revision: 1.4 $
*******************************************************************************/

/**********************************************************************
This file is part of the OpenEAI sample, reference implementation,
and deployment management suite created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.

Copyright (C) 2002 The OpenEAI Software Foundation

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For specific licensing details and examples of how this software
can be used to implement integrations for your enterprise, visit
http://www.OpenEai.org/licensing.
*/


package org.any_openeai_enterprise.gateways.warehouse;

import javax.jms.*;
import java.util.*;
import java.io.*;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.output.XMLOutputter;

import org.openeai.dbpool.*;
import org.openeai.xml.*;
import org.openeai.jms.producer.*;
import org.openeai.jms.consumer.*;
import org.openeai.jms.consumer.commands.*;
import org.openeai.layouts.*;
import org.openeai.config.*;
import org.openeai.moa.*;
import org.openeai.moa.objects.resources.*;
import org.openeai.moa.objects.testsuite.*;

import com.any_erp_vendor.moa.jmsobjects.person.v1_0.BasicPerson;
import com.any_erp_vendor.moa.objects.resources.v1_0.Date;
import com.any_erp_vendor.moa.objects.resources.v1_0.Name;
import com.any_erp_vendor.moa.objects.resources.v1_0.Address;
import com.any_erp_vendor.moa.objects.resources.v1_0.Phone;

import java.sql.*;
import java.net.URL;
import java.io.*;

/**
* This command is part of the OpenEAI Getting Started guide.  It is an example of
* a gateway that consumes Synchronizaton messages from our ficticious ERP system
* from the ficticious "any-erp-vendor.com" company.  That ERP (com.any-erp-vendor.Gateway) is authoritative for the
* following messages:
* <ul>
* <li>com.any-erp-vendor.Person/BasicPerson/1.0
* <li>com.any-erp-vendor.Person/EmergencyContact/1.0
* <li>com.any-erp-vendor.Employee/BasicEmployee/1.0
* </ul>
* This command will consume Synchronization messages for the
* com.any-erp-vendor.Person.BasicPerson/1.0 message object. 
* This includes:  Create, Update, Delete.  When it consumes a Sync message, it
* will pull relevant information from the message it consumes and store it in it's
* own repository.  This information will be stored in a more 'traditional' repository
* meaning it will actually store data in individual columns in its database.
* <P>
* You can use the SelfServiceApplication or the TestSuite Application (also included in the Getting Started
* distribution) to create, update, delete and query for people, employees and emergency
* contacts in the com.any-erp-vendor.Gateway.  When you create, delete or update
* BasicPerson objects synchronization messages will be published and routed to this
* gateway.
* <P>
* Note, this command is purposely simple.  It does not attempt to factor out much of the
* logic that could or should be.  This is so most of the work being done is contained in this single
* file.  Wile it is completely and fully functional, it should not be considered
* the best way to actually code some of this stuff.  It is thouroughly commented so you
* should be able to get a pretty good idea about what's going on at all the critical points
* within the command execution.
* <P>
* To start this gateway you must execute the org.openeai.jms.consumer.MessageConsumerClient 
* class passing the path to the properties file you wish to use.
* <P>
* e.g. - java -cp [classpath] org.openeai.jms.consumer.MessageConsumerClient c:\GettingStarted.properties
* <P>
* In the GettingStarted.properties file, you must un-comment the line that contains:
* <P>
* <i>messageComponentName=org.any-openeai-enterprise.EnterpriseWarehouse</i>
* <P>
* This tells AppConfig which Messaging Component (gateway) it's configuring.  
* Refer to the GettingStarted guide and installation instructions for more information.
* <P>
* <B>Gateway Configuration</B>
* <P>
* These are the configuration parameters required by the sample org.any-openeai-enterprise.EnterpriseWarehouse. 
* They are specified in the AnyOpenEaiEnterprise.xml Deployment Descriptor which is provided
* in the sample enterprise distribution. 
* This gateway is identified in the AnyOpenEaiEnterprise.xml Deployment
* Descriptor as <b>org.any-openeai-enterprise.EnterpriseWarehouse</b>.
* <P>
* Configuration for a gateway can be broken into two pieces:
* <ul>
* <li>Configuring the consumer to connect to a topic or queue and telling it what commands it executes.
* <li>Configuring the command(s) executed by that consumer.
* </ul>
* <P>
* <b>Configuring the Consumer</b>
* <P>
* The items listed below can be found in the 'Configuration' Element associated to
* the org.any-openeai-enterprise.EnterpriseWarehouse gateway in the deployment descriptor. 
* This Configuration element becomes the AppConfig
* object associated to this gateway <b>(remember, all OpenEAI gateways are started through
* the org.openeai.jms.consumer.MessageConsumerClient class)</b>.
* <P>
* The consumer's Configuration is fairly simple.  It contains a LoggerConfig object that specifies
* how the log4j logger will behave and it contains a ConsumerConfigs element.  Below is a description
* of the Consumer configuration.  Note, not all configurable items are mentioned but that
* information can be reviewed by looking at the core OpenEAI API Javadoc.
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>WarehouseConsumer1</TD>
* <TD>yes</TD>
* <TD>An OpenEAI PubSubConsumer object configured to consume JMS messages off
* the 'cn=EnterpriseWarehouseTopic' topic.  When the com.any-erp-vendor.Gateway publishes
* Sync messages, the EnterpriseTransRouter will route messages that contain messageObjects of
* type BasicPerson to this topic.  This consumer will consume those messages and execute
* the org.any_openeai_enterprise.gateways.warehouse.EnterpriseWarehouseCommand (this command)
* which is specified as a Command executed by this consumer.  As a matter of fact, it is the ONLY command
* that will ever be executed by this consumer since its 'isAbsolute' attribute is 'true'. 
* That Command will perform the necessary business logic.  If any errors occur, the command
* will publish an org.openeai.CoreMessaging/Sync/1.0/Error-Sync message that will be logged
* by the 'Enterprise Logging Service'.
* <P>
* The Consumer's configuration specifies that it will connect to the broker
* and be ready to consume messages when it is initialized ('startOnInitialization=true') use the
* InitialContextFactory 'org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory' to retrieve the JMS
* administered objects from the 'rmi://localhost:1099/JndiServer' ProviderURL (the directory server normally). 
* Then it will connect to the JMS Provider using the 'cn=EnterpriseWarehouseConsumerTCF' JMS TopicConnectionFactory
* administered object.
* <P>
* NOTE:  These are the parameters you change when you wish to switch JMS providers or use different JNDI stores 
* to store your administered objects.
* <P>
* It will execute the Commands specified in a ThreadPool that has 30 pre-allocated Threads available to it and it will
* detect when the ThreadPool is busy and only add another Command execution to the ThreadPool when the ThreadPool has
* available threads to process the transaction.</TD>
* </TR>
* </TABLE>
* <P>
* <b>Configuring the Command(s) executed by the Consumer</b>
* <P>
* The EnterpriseWarehouseCommand command will NOT validate
* the JDOM Document created from the JMS Message that's passed to it (inboundXmlValidation=false). 
* If you'd like it to validate incomming XML, you can change this attribute to true. 
* Additionally, it will not write the XML Document to a file (writeToFile=false) when it receives it.  As stated
* before, this command is the 'absolute' command associated to this consumer.  So, no matter what "COMMAND_NAME" is
* associated to the JMS Message as it is consumed by the consumer, this command will be executed.  The
* EnterpriseWarehouse (CommandName) is implemented by the
* org.any_openeai_enterprise.gateways.warehouse.EnterpriseWarehouseCommand class (CommandClass) and
* it is a 'syncMessage' Command (type=syncMessage).
* <P>
* The items listed below can be found in the 'Configuration' Element associated to the
* EnterpriseWarehouse in the deployment descriptor.  This Configuration element becomes the AppConfig
* object associated to this Command that is used by the command when it is executed.
* <P>
* They are broken apart by Configuration object type.  This command 
* will Publish Sync-Error messages if it ever has any problems performing the business logic,
* it will use Message Objects to operate on the data contained in the message consumed, it will
* use a DbConnectionPool to persist data and it will use several general Properties object. 
* Therefore, there are four categories of configuration objects used:  ProducerConfigs,
* MessageObjectConfigs, DbConnectionPoolConfigs and PropertyConfigs.
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Type</TH>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>ProducerConfigs</TD>
* <TD>SyncErrorPublisher</TD>
* <TD>yes</TD>
* <TD>An OpenEAI PubSubProducer object configured to publish Synchronization message to the
* 'cn=EnterpriseSyncErrorLoggerTopic'.  This will be used any time the command encounters
* errors performing its business logic.  That Sync-Error message will then be logged
* by the 'Enterprise Logging Service' for follow-up by EAI support staff.
* <P>
* NOTE:  This is a required object for all SyncCommand implementations.  The gateway
* will not start if you have not specified a PubSubProducer named 'SyncErrorPublisher'.</TD>
* </TR>
* </TABLE>
* <P>
* <b>MessageObjectConfigs</b>
* <P>
* These configuration objects are used to configure all Message objects required by this command. 
* The message objects themselves are part of the com.any-erp-vendor Message Object API (MOA) which
* was provided by the vendor because they've defined enterprise messages according to the OpenEAI
* Message Protocol.  These objects were generated off of their enterprise message definitions (their Segments.dtd file).
* <P>
* The objects are configured to use the Enterprise Object (EO) documents supplied by the com.any-erp-vendor organization that
* were also generated from their Segments.dtd file. 
* In our sample enterprise, we've added some of our own formatting rules (datatypes, lengths, scrubbers and translations)
* to these EO documents that our sample organization require.
* <P>
* The objects are used to operate on the data supplied in the sync messages as well
* as to persist the relevant information to the database.
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>BasicPerson.v1_0</TD>
* <TD>yes</TD>
* <TD>A com.any_erp_vendor.moa.jmsobjects.person.v1_0.BasicPerson Java object that was generated
* from the com/any-erp-vendor/Resources/1.0/Segments.dtd file.  This object will be built
* from the contents of the messages consumed
* and used to store relevant information in the repository associated to this command.</TD>
* </TR>
* </TABLE>
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Type</TH>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>DbConnectionPoolConfigs</TD>
* <TD>WarehouseDbPool</TD>
* <TD>yes</TD>
* <TD>This is an OpenEAI org.openeai.dbpool.EnterpriseConnectionPool object.  The command will 
* retrieve a pre-established database connection from the pool and execute SQL statements.  By default,
* the connections in the pool are configured to work with a MySql database.  However, scripts
* are provided in the Sample Enterprise distribution that will create Oracle structures as well.  To
* use these Oracle structures, you would simply change the pool configuration information here.</TD>
* </TR>
* </TABLE>
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Type</TH>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>PropertyConfig</TD>
* <TD>WarehouseProperties</TD>
* <TD>yes</TD>
* <TD>These are 'general' properties that will be associated to this Command.</TD>
* </TR>
* </TABLE>
* <P>
* <TABLE BORDER=2 CELLPADDING=5 CELLSPACING=2>
* <TR>
* <TH>Configuration Object Type</TH>
* <TH>Configuration Object Name</TH>
* <TH>Required</TH>
* <TH>Description</TH>
* </TR>
* <TR HALIGN="left" VALIGN="top">
* <TD>PropertyConfig</TD>
* <TD>SyncErrorSyncProperties</TD>
* <TD>yes</TD>
* <TD>These are REQUIRED properties that are used by SyncCommandImpl (this command's anscestor)
* to configure itself to publish Sync-Error messages.  All SyncCommand implementations must
* have a PropertyConfig object named 'SyncErrorSyncProperties' or they will not start.  These
* Properties specify the 'primed' Sync-Error document location so that resource can be made
* available when the Command is first initialized and so it doesn't have to do it itself
* later when/if there's an error.</TD>
* </TR>
* </TABLE>
* <P>
* @author Tod Jackson (tod@openeai.org)
**/
public class EnterpriseWarehouseCommand 
  extends SyncCommandImpl
  implements SyncCommand {
 
  private EnterpriseConnectionPool m_connPool = null;

  public EnterpriseWarehouseCommand(CommandConfig cConfig) throws InstantiationException {
    super(cConfig);

    try {
      // default properties associated to this command (there could be others named differently).
      PropertyConfig pConfig = (PropertyConfig)getAppConfig().getObject("WarehouseProperties");
      setProperties(pConfig.getProperties());

      // initialize db connection pool that will be used to store information from the
      // message into our own repository
      m_connPool = (EnterpriseConnectionPool)getAppConfig().getObject("WarehouseDbPool");
    }
    catch (Exception e) {
      logger.fatal("Error initializing 'EnterpriseWarehouse' command.");
      logger.fatal(e.getMessage(), e);
      throw new InstantiationException(e.getMessage());
    }

    logger.info("EnterpriseWarehouseCommand instantiated successfully.");
  }

  /**
  * Takes the BasicPerson sync messages that have been published by the ERP system
  * and routed to this gateway and stores relevant information from the consumed
  * messages in its own repository for "wharehousing" purposes like report writing etc.
  **/
  public void execute(int messageNumber, Message aMessage) throws CommandException {
    String errMessage = "";
    Document inDoc = null;
    try {
      inDoc = initializeInput(messageNumber, aMessage);
    }
    catch (Exception e) {
      errMessage = "Exception occurred processing input message in ConsumerCommand.  Exception: " + e.getMessage();
      ArrayList errors = new ArrayList();
      errors.add(buildError("application", "SYNC-1001", errMessage));
      publishSyncError(new Element("EmptyControlArea"), errors, e);
      throw new CommandException(e.getMessage());
    }

    Element eControlArea = getControlArea(inDoc.getRootElement());
    Element eDataArea = inDoc.getRootElement().getChild(DATA_AREA);

    String msgAction = eControlArea.getAttribute(MESSAGE_ACTION).getValue();
    String msgObject = eControlArea.getAttribute(MESSAGE_OBJECT).getValue();
    String msgRelease = eControlArea.getAttribute(MESSAGE_RELEASE).getValue();
    String msgCategory = eControlArea.getAttribute(MESSAGE_CATEGORY).getValue();
    String msgType     = eControlArea.getAttribute(MESSAGE_TYPE).getValue();

    // if the message object isn't one we're interested in (BasicPerson) publish
    // a sync error and return...
   
    String dataAreaChild = NEW_DATA;    // Default, this will work for Create and Update
    if (msgAction.equalsIgnoreCase(DELETE_ACTION)) {
      dataAreaChild = DELETE_DATA;
    }

    // Get the DataArea element out of the document
    // This should correspond to one of our message objects.
    Element eMessageObject = eDataArea.getChild(dataAreaChild).getChild(msgObject);

    if (eMessageObject == null) {
      // Error!
      errMessage = "Could not find an element at DataArea/" + dataAreaChild + "/" + msgObject +
                   "in the " + msgObject + "-" + msgAction + "-Sync Document passed in";
      logger.fatal(errMessage);
      logger.fatal("Message sent in is: \n" + getMessageBody(inDoc));

      ArrayList errors = new ArrayList();
      errors.add(buildError("application", "MSG-1001", errMessage));
      publishSyncError(eControlArea, errors);
      return;
    }
   
    // if the msgAction is Update, we'll need to get the baseline object out of the document as well.
    Element eBaselineMessageObject = null;
    if (msgAction.equalsIgnoreCase(UPDATE_ACTION)) {
      // we need to create a baseline BasicPerson also so we have to get the baseline element...
      eBaselineMessageObject = inDoc.getRootElement().
                      getChild(DATA_AREA).
                      getChild(BASELINE_DATA).
                      getChild(msgObject);

      if (eBaselineMessageObject == null) {
        // Error!
        errMessage = "Could not find a " + msgObject + " + element at DataArea/BaselineData/" + msgObject +
                     " in the "+msgObject+"-"+msgAction+"-" + msgAction + " Document passed in";

        ArrayList errors = logErrors("MSG-1012", errMessage, inDoc);
        publishSyncError(eControlArea, errors);
        return;
      }
    }
   
    // get the object(s) we need to build from AppConfig
    BasicPerson bPerson = null;
    BasicPerson baselinePerson = null;

    // build the message object from the element retrieved from the XML document.
    // this is done via the default XmlLayout manager.
    try {
      bPerson = (BasicPerson)getAppConfig().getObject(msgObject + "." + generateRelease(msgRelease));
      bPerson.buildObjectFromInput(eMessageObject);
      if (msgAction.equalsIgnoreCase(UPDATE_ACTION)) {
        baselinePerson = (BasicPerson)getAppConfig().getObject(msgObject + "." + generateRelease(msgRelease));
        baselinePerson.buildObjectFromInput(eBaselineMessageObject);
      }
    }
    catch (Exception e) {
      errMessage = "Exception occurred building the " + eMessageObject.getName() + " Java object from the Element passed in.  Exception: " + e.getMessage();

      ArrayList errors = logErrors("MSG-1003", errMessage, inDoc);
      publishSyncError(eControlArea, errors, e);
      return;
    }
   
    // now, perform the actual database activity based on the action associated to
    // the message consumed.
    if (msgAction.equalsIgnoreCase(CREATE_ACTION)) {
      try {
        createPerson(msgCategory, msgObject, msgRelease, bPerson);
        return;
      }
      catch (Exception e) {
        errMessage = "Exception occurred Creating the " + msgObject + " Java object in the database.  Exception: " + e.getMessage();
        logger.fatal(errMessage, e);

        ArrayList errors = logErrors("MSG-1003", errMessage, inDoc);
        publishSyncError(eControlArea, errors, e);
        return;
      }
    }
    else if (msgAction.equalsIgnoreCase(DELETE_ACTION)) {
      try {
        String deleteAction = "delete";
        deletePerson(msgCategory, msgObject, msgRelease, deleteAction, bPerson);
        return;
      }
      catch (Exception e) {
        errMessage = "Exception occurred Deleting the " + msgObject + " Java object from the database.  Exception: " + e.getMessage();
        logger.fatal(errMessage, e);

        ArrayList errors = logErrors("MSG-1003", errMessage, inDoc);
        publishSyncError(eControlArea, errors, e);
        return;
      }
    }
    else if (msgAction.equalsIgnoreCase(UPDATE_ACTION)) {
      try {
        // since we're not authoritative, we just want to do the update if the person
        // exists, if it doesn't exist, we could create the person?
        updatePerson(msgCategory, msgObject, msgRelease, bPerson, baselinePerson);
      }
      catch (Exception e) {
        errMessage = "Exception occurred Updating the " + msgObject + " Java object in the database.  Exception: " + e.getMessage();
        logger.fatal(errMessage, e);

        ArrayList errors = logErrors("MSG-1003", errMessage, inDoc);
        publishSyncError(eControlArea, errors, e);
        return;
      }
    }
    else {
      // error, invalid message action.
    }
  }

  protected BasicPerson retrievePerson(String instId) throws SQLException {   
    PreparedStatement stmt = null;
    String sqlString =  "SELECT INST_ID, FIRST_NAME, MIDDLE_NAME, LAST_NAME, " +
                        "GENDER, ETHNICITY, BIRTH_DATE, SSN FROM T_PERSON " +
                        "WHERE INST_ID=?";

    java.sql.Connection conn = null;
    EnterprisePooledConnection p = null;
    try {
      p = m_connPool.getExclusiveConnection();
      conn = p.getConnection();
      conn.setAutoCommit(true);
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }

    try {
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, instId);
      logger.info("Retrieving Person record for InstitutionalId: " + instId);
      ResultSet rs = stmt.executeQuery();
      logger.info("Retreived Person record for InstitutionalId: " + instId);

      BasicPerson bPerson = (BasicPerson)getAppConfig().getObject("BasicPerson.v1_0");
      Name aName = bPerson.newName();
      boolean foundPerson = false;
      while (rs.next()) {
        foundPerson = true;
        bPerson.setInstitutionalId(rs.getString(1));
        aName.setFirstName(rs.getString(2));
        aName.setMiddleName(rs.getString(3));
        aName.setLastName(rs.getString(4));
        bPerson.setName(aName);
        bPerson.setGender(rs.getString(5));
        bPerson.setEthnicity(rs.getString(6));
        com.any_erp_vendor.moa.objects.resources.v1_0.Date bDate = bPerson.newBirthDate();
        java.sql.Date dbDate = rs.getDate(7);

        if (dbDate != null) {
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(dbDate);

          bDate.setYear(Integer.toString(calendar.get(Calendar.YEAR)));
          bDate.setMonth(Integer.toString(calendar.get(Calendar.MONTH)+1));
          bDate.setDay(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)));

          logger.info("BirthDate from db is: " + bDate.toString());
          bPerson.setBirthDate(bDate);
        }
        bPerson.setSocialSecurityNumber(rs.getString(8));
      }
     
      stmt.close();

      // finally, release the connection.
      m_connPool.releaseExclusiveConnection(p);
      if (foundPerson) {
        return bPerson;
      }
      else {
        return null;
      }
    }
    catch (Exception e) {
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
    finally {
      m_connPool.releaseExclusiveConnection(p);
    }
  }
  /**
  * This method updates the information in T_PERSON for the BasicPerson object passed in. 
  * Since this is a SyncCommand (it's not authoritative), it simply takes the data provided
  * and updates its repository.  If anything had been changed in the local repository, it would
  * be overridden.  Since's this is a warehouse gateway, data is only viewed, it's not changed
  * in the local repository.
  * <P>
  * In addition to updating the T_PERSON table, this method also looks at each Address and Phone
  * object contained within the newData BasicPerson object and compares them against the
  * Address and Phone objects contained withing the baselinePerson BasicPerson object.  Depending
  * on that comparison, it may call any of the create, delete or update methods associated to
  * Addresses and Phones.  It uses the 'key' fields associated to the Address and Phone objects
  * to determine if the Address or Phone transaction needs to be an insert, update or delete.
  * <P>
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param deleteAction the delete action associated to the request that was pulled
  * from the 'DataArea/DeleteData/DeleteAction' element in the enterprise message.
  * @param newData the BasicPerson Java object that was built from the contents of the
  * enterprise message passed in (DataArea/NewData).  This is the new state of the BasicPerson.  When
  * this method is complete, the state of the object in our local repository (T_PERSON, T_ADDRESS and T_PHONE)
  * should match this object.
  * @param baselinePerson the BasicPerson Java object that was built from the contents of the
  * enterprise message passed in (DataArea/BaselineData).  This is the baseline state of the BasicPerson.  This
  * object is used to determine what transaction should be perfored on the Address and Phone
  * objects (insert, update or deletes)
  * @throws SQLException if errors occur deleting the message object from the database or if
  * errors occur publishing the resulting Delete-Sync message.
  **/
  protected void updatePerson(String msgCategory, String msgObject, String msgRelease, BasicPerson newData, BasicPerson baselinePerson) throws SQLException {   
    BasicPerson dbPerson = retrievePerson(newData.getInstitutionalId());
    if (dbPerson == null) {
      logger.info("Person did not exist in our repository, we'll just create them.");
      createPerson(msgCategory, msgObject, msgRelease, newData);
      return;
    }
    PreparedStatement stmt = null;
    String sqlString =  "UPDATE T_PERSON " +
                        "SET FIRST_NAME=?, MIDDLE_NAME=?, LAST_NAME=?, GENDER=?, " +
                        "ETHNICITY=?, BIRTH_DATE=?, SSN=?, MOD_DATE=?, MOD_USER=? " +
                        "WHERE INST_ID=? AND MESSAGE_CATEGORY=? AND MESSAGE_OBJECT=? AND MESSAGE_RELEASE=?";

    String instId = newData.getInstitutionalId();
    java.sql.Connection conn = null;
    EnterprisePooledConnection p = null;
    try {
      p = m_connPool.getExclusiveConnection();
      conn = p.getConnection();
      conn.setAutoCommit(false);
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
   
    try {
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, newData.getName().getFirstName());
      stmt.setString(2, newData.getName().getMiddleName());
      stmt.setString(3, newData.getName().getLastName());
      stmt.setString(4, newData.getGender(getAppName()));
      stmt.setString(5, newData.getEthnicity(getAppName()));
      String sBirthDate = "";
      if (newData.getBirthDate() != null && newData.getBirthDate().isEmpty() == false) {
        sBirthDate = newData.getBirthDate().getMonth() + "/" +
                    newData.getBirthDate().getDay() + "/" +
                    newData.getBirthDate().getYear();
        java.util.Date d = new java.util.Date();
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat( "MM/dd/yyyy" );
        d = formatter.parse(sBirthDate);
        stmt.setDate(6, new java.sql.Date(d.getTime()));
      }
      else {
        stmt.setDate(6, null);
      }
      stmt.setString(7, newData.getSocialSecurityNumber());
      stmt.setTimestamp(8, new java.sql.Timestamp(System.currentTimeMillis()));
      stmt.setString(9, conn.getMetaData().getUserName());
      stmt.setString(10, instId);
      stmt.setString(11, msgCategory);
      stmt.setString(12, msgObject);
      stmt.setString(13, msgRelease);
      logger.info("Attempting to Update " + msgObject + " record for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Updated " + msgObject + " record for InstitutionalId: " + instId + " rc=" + rc);
      stmt.close();

      // now the address(s), using the same connection
      // have to determine if we need to insert, delete or update any
      logger.info("Starting Address update process...");
      java.util.List newAddresses = newData.getAddress();
      java.util.List oldAddresses = baselinePerson.getAddress();
      for (int i=0; i<newAddresses.size(); i++) {
        Address newAddress = (Address)newAddresses.get(i);
        String newAddressKey = newAddress.getCombinedKeyValue();
        boolean foundMatch = false;
        for (int j=0; j<oldAddresses.size(); j++) {
          Address oldAddress = (Address)oldAddresses.get(j);
          String oldAddressKey = oldAddress.getCombinedKeyValue();
          if (oldAddressKey.equalsIgnoreCase(newAddressKey)) {
            // found a match, might have to update...
            foundMatch = true;
            if (newAddress.equals(oldAddress) == false) {
              // need to update individual address
              logger.info("updating existing address object.");
              updateAddress(conn, msgCategory, msgObject, msgRelease, instId, newAddress);
            }
          }
        }
        if (foundMatch == false) {
          // need to create address
          logger.info("creating new address object.");
          createAddress(conn, msgCategory, msgObject, msgRelease, instId, newAddress);
        }
      }
      // now we need to check the oldAddresses and delete any that don't
      // exist in the newAddress list
      for (int i=0; i<oldAddresses.size(); i++) {
        Address oldAddress = (Address)oldAddresses.get(i);
        String oldAddressKey = oldAddress.getCombinedKeyValue();
        boolean foundMatch = false;
        for (int j=0; j<newAddresses.size(); j++) {
          Address newAddress = (Address)newAddresses.get(j);
          String newAddressKey = newAddress.getCombinedKeyValue();
          if (oldAddressKey.equalsIgnoreCase(newAddressKey)) {
            // found a match, don't delete
            foundMatch = true;
          }
        }
        if (foundMatch == false) {
          // must delete the oldAddress
          logger.info("deleting old address object.");
          deleteAddress(conn, msgCategory, msgObject, msgRelease, instId, oldAddress);
        }
      }
      logger.info("Finished Address update process...");

      // now the phone(s), using the same connection
      // have to determine if we need to insert, delete or update any
      logger.info("Starting Phone update process...");
      java.util.List newPhones = newData.getPhone();
      java.util.List oldPhones = baselinePerson.getPhone();
      for (int i=0; i<newPhones.size(); i++) {
        Phone newPhone = (Phone)newPhones.get(i);
        String newPhoneKey = newPhone.getCombinedKeyValue();
        boolean foundMatch = false;
        for (int j=0; j<oldPhones.size(); j++) {
          Phone oldPhone = (Phone)oldPhones.get(j);
          String oldPhoneKey = oldPhone.getCombinedKeyValue();
          if (oldPhoneKey.equalsIgnoreCase(newPhoneKey)) {
            // found a match, might have to update...
            foundMatch = true;
            if (newPhone.equals(oldPhone) == false) {
              // need to update individual phone
              logger.info("updating existing phone object.");
              updatePhone(conn, msgCategory, msgObject, msgRelease, instId, newPhone);
            }
          }
        }
        if (foundMatch == false) {
          // need to create phone
          logger.info("creating new address object.");
          createPhone(conn, msgCategory, msgObject, msgRelease, instId, newPhone);
        }
      }
      // now we need to check the oldPhones and delete any that don't
      // exist in the newAddress list
      for (int i=0; i<oldPhones.size(); i++) {
        Phone oldPhone = (Phone)oldPhones.get(i);
        String oldPhoneKey = oldPhone.getCombinedKeyValue();
        boolean foundMatch = false;
        for (int j=0; j<newPhones.size(); j++) {
          Phone newPhone = (Phone)newPhones.get(j);
          String newPhoneKey = newPhone.getCombinedKeyValue();
          if (oldPhoneKey.equalsIgnoreCase(newPhoneKey)) {
            // found a match, don't delete
            foundMatch = true;
          }
        }
        if (foundMatch == false) {
          // must delete the oldPhone
          logger.info("deleting old address object.");
          deletePhone(conn, msgCategory, msgObject, msgRelease, instId, oldPhone);
        }
      }
      logger.info("Finished Phone update process...");

      // now the email(s), using the same connection

      // finally, commit it all if everything went okay.
      conn.commit();
      m_connPool.releaseExclusiveConnection(p);
    }
    catch (Exception e) {
      conn.rollback();
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
    finally {
      m_connPool.releaseExclusiveConnection(p);
    }                         
  }
  /**
  * This method first deletes all Address and Phone objects contained within the BasicPerson
  * object passed in by calling the deleteAddress and deletePhone methods.  Then it
  * deletes the T_PERSON row associated to the BasicPerson message object passed in.
  * <P>
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param deleteAction the delete action associated to the request that was pulled
  * from the 'DataArea/DeleteData/DeleteAction' element in the enterprise message.
  * @param bPerson the BasicPerson Java object that was built from the contents of the
  * enterprise message passed.  The InstitutionalId from this object will be used
  * to delete data from the T_PERSON table.  Additionally, Address and Phone objects will
  * be extracted from the object and deleted from their respective tables.
  * @throws SQLException if errors occur deleting the message object from the database or if
  * errors occur publishing the resulting Delete-Sync message.
  **/
  protected void deletePerson(String msgCategory, String msgObject, String msgRelease, String deleteAction, BasicPerson bPerson) throws SQLException {   
    PreparedStatement stmt = null;
    String sqlString = "delete from T_PERSON " +
                          "where inst_id=? AND MESSAGE_CATEGORY=? AND MESSAGE_OBJECT=? AND MESSAGE_RELEASE=?";

    String instId = bPerson.getInstitutionalId();
    java.sql.Connection conn = null;
    EnterprisePooledConnection p = null;
    try {
      p = m_connPool.getExclusiveConnection();
      conn = p.getConnection();
      conn.setAutoCommit(false);
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }

    try {
      // first the address(s), using the same connection
      for (int i=0; i<bPerson.getAddress().size(); i++) {
        Address a = bPerson.getAddress(i);
        deleteAddress(conn, msgCategory, msgObject, msgRelease, instId, a);
      }

      // now the phone(s), using the same connection
      for (int i=0; i<bPerson.getPhone().size(); i++) {
        Phone phone = bPerson.getPhone(i);
        deletePhone(conn, msgCategory, msgObject, msgRelease, instId, phone);
      }

      // now the email(s), using the same connection

      // now the actual person record
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, instId);
      stmt.setString(2, msgCategory);
      stmt.setString(3, msgObject);
      stmt.setString(4, msgRelease);
      logger.info("Attempting to delete " + msgObject + " record for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Deleted " + msgObject + " record for InstitutionalId: " + instId);
      stmt.close();

      // finally, commit it all if everything went okay.
      conn.commit();
      m_connPool.releaseExclusiveConnection(p);
    }
    catch (Exception e) {
      conn.rollback();
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
    finally {
      m_connPool.releaseExclusiveConnection(p);
    }                         
  }
  /**
  * Inserts the InstitutionalId, FirstName, MiddleName, LastName, Gender, Ethnicity
  * BirthDate and SocialSecurityNumber fields into the T_PERSON table.  Note, that the
  * values stored for fields like Gender and Ethnicity are reverse translated from
  * "enterprise values" to "application values" that are specified in the BasicPersonEO.xml
  * file (EO doc) for the BasicPerson object being used by this command.
  * <P>
  * Then it goes through each Address object contained within the BasicPerson object passed in
  * and inserts it into the T_ADDRESS table by calling the 'createAddress' method.
  * <P>
  * Then it goes through each Phone object containe within the BasicPerson object passed in and
  * inserts it into the T_PHONE table calling the 'createPhone' method.
  * <P>
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param bPerson the BasicPerson Java object that was built from the contents of the
  * enterprise message passed.  Individual fields from this object will be extracted
  * and inserted into the T_PERSON table.  Additionally, Address and Phone objects will
  * be extracted from the object and inserted into their respective tables.
  * @throws SQLException if errors occur deleting the message object from the database or if
  * errors occur publishing the resulting Delete-Sync message.
  **/
  protected void createPerson(String msgCategory, String msgObject, String msgRelease, BasicPerson bPerson) throws SQLException {   
    PreparedStatement insertStmt = null;
    String insertString = "INSERT INTO T_PERSON (INST_ID, MESSAGE_CATEGORY, MESSAGE_OBJECT, MESSAGE_RELEASE, FIRST_NAME, " +
                          "MIDDLE_NAME, LAST_NAME, GENDER, ETHNICITY, " +
                          "BIRTH_DATE, SSN, " +
                          "CREATE_DATE, CREATE_USER, MOD_DATE, MOD_USER) " +
                          "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    // get the institutional id from the BasicPerson
    String instId = bPerson.getInstitutionalId();

    // get an exclusive connection from our OpenEAI database connection pool.
    // this is required if we're going to perform database activities within
    // a transaction (autocommit=false)
    java.sql.Connection conn = null;
    EnterprisePooledConnection p = null;
    try {
      p = m_connPool.getExclusiveConnection();
      conn = p.getConnection();
      conn.setAutoCommit(false);
    }
    catch (Exception e) {
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }

    // Now, prepare our SQL statement setting values that should be inserted into
    // the T_PERSON table.  Note, when fields like Gender and Ethnicity are retrieved
    // from the BasicPerson object, we're passing our application name.  This will
    // result in the enterprise values contained in the BasicPerson object being reverse
    // translated into application specific values for our system.
    try {
      insertStmt = conn.prepareStatement(insertString);
      insertStmt.clearParameters();
      insertStmt.setString(1, instId);
      insertStmt.setString(2, msgCategory);
      insertStmt.setString(3, msgObject);
      insertStmt.setString(4, msgRelease);
      insertStmt.setString(5, bPerson.getName().getFirstName());
      insertStmt.setString(6, bPerson.getName().getMiddleName());
      insertStmt.setString(7, bPerson.getName().getLastName());
      insertStmt.setString(8, bPerson.getGender(getAppName()));
      insertStmt.setString(9, bPerson.getEthnicity(getAppName()));
      String sBirthDate = "";
      if (bPerson.getBirthDate() != null && bPerson.getBirthDate().isEmpty() == false) {
        sBirthDate = bPerson.getBirthDate().getMonth() + "/" +
                    bPerson.getBirthDate().getDay() + "/" +
                    bPerson.getBirthDate().getYear();
        java.util.Date d = new java.util.Date();
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat( "MM/dd/yyyy" );
        d = formatter.parse(sBirthDate);
        insertStmt.setDate(10, new java.sql.Date(d.getTime()));
      }
      else {
        insertStmt.setDate(10, null);
      }
      insertStmt.setString(11, bPerson.getSocialSecurityNumber());
      insertStmt.setTimestamp(12, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(13, conn.getMetaData().getUserName());
      insertStmt.setTimestamp(14, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(15, conn.getMetaData().getUserName());
      logger.info("Attempting to insert " + msgObject + " record for InstitutionalId: " + instId);
      logger.debug("Gender appValue: '" + bPerson.getGender(getAppName()) + "'");
      logger.debug("Ethnicity appValue: '" + bPerson.getEthnicity(getAppName()) + "'");
      int insertRc = insertStmt.executeUpdate();
      logger.info("Inserted " + msgObject + " record for InstitutionalId: " + instId);
      insertStmt.close();

      // now the address(s), using the same connection
      for (int i=0; i<bPerson.getAddress().size(); i++) {
        Address a = bPerson.getAddress(i);
        createAddress(conn, msgCategory, msgObject, msgRelease, instId, a);
      }

      // now the phone(s), using the same connection
      for (int i=0; i<bPerson.getPhone().size(); i++) {
        Phone phone = bPerson.getPhone(i);
        createPhone(conn, msgCategory, msgObject, msgRelease, instId, phone);
      }

      // now the email(s), using the same connection

      // finally, commit it all if everything went okay.
      conn.commit();
      m_connPool.releaseExclusiveConnection(p);
    }
    catch (Exception e) {
      conn.rollback();
      if (insertStmt != null) {
        insertStmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
    finally {
      m_connPool.releaseExclusiveConnection(p);
    }                         
  }

  /**
  * Deletes a single Address row from the T_ADDRESS table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Address type associated
  * to the Address object passed in as the delete criteria.
  * <P>
  * @param conn a pre-established database connection.  Since an Address is only ever
  * deleted as part of a larger transaction (BasicPerson-Delete or Update) this
  * delete must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're deleting an address for.
  * @param a the Address Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed.
  * @throws SQLException if errors occur deleting the Address from the database.
  **/
  protected void deleteAddress(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Address a) throws SQLException {
    PreparedStatement stmt = null;
    String sqlString = "delete from T_ADDRESS " +
                          "where inst_id=? and MESSAGE_CATEGORY=? AND " +
                          "MESSAGE_OBJECT=? AND MESSAGE_RELEASE=? AND " +
                          "ADDR_TYPE=?";

    try {
      // delete the individual address record passed in
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, instId);
      stmt.setString(2, msgCategory);
      stmt.setString(3, msgObject);
      stmt.setString(4, msgRelease);
      stmt.setString(5, a.getType(getAppName()));
      logger.info("Attempting to delete Address record " + a.toString() + " for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Deleted Address record " + a.toString() + " for InstitutionalId: " + instId + " rc=" + rc);
      stmt.close();
    }
    catch (Exception e) {
      conn.rollback();
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }
  /**
  * Updates a single Address row from the T_ADDRESS table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Address type associated
  * to the Address object passed in as the update criteria.
  * <P>
  * @param conn a pre-established database connection.  Since an Address is only ever
  * updated as part of a larger transaction (BasicPerson-Update) this
  * update must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're updating an address for.
  * @param a the Address Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed in.
  * @throws SQLException if errors occur updating the Address from the database.
  **/
  protected void updateAddress(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Address a) throws SQLException {
    PreparedStatement stmt = null;
    String sqlString = "UPDATE T_ADDRESS SET STREET1=?, STREET2=?, " +
                          "STREET3=?, CITY=?, STATE_CODE=?, ZIP_CODE=?, EFFECTIVE_DATE=?, " +
                          "MOD_DATE=?, MOD_USER=? " +
                          "WHERE INST_ID=? AND MESSAGE_CATEGORY=? AND MESSAGE_OBJECT=? AND " +
                          "MESSAGE_RELEASE=? AND ADDR_TYPE=?";

    try {
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, a.getStreet1(getAppName()));
      stmt.setString(2, a.getStreet2(getAppName()));
      stmt.setString(3, a.getStreet3(getAppName()));
      stmt.setString(4, a.getCityOrLocality(getAppName()));
      stmt.setString(5, a.getStateOrProvince(getAppName()));
      stmt.setString(6, a.getZipOrPostalCode(getAppName()));
      String sEffDate = "";
      if (a.getEffectiveDate().isEmpty() == false) {
        sEffDate = a.getEffectiveDate().getMonth() + "/" +
                    a.getEffectiveDate().getDay() + "/" +
                    a.getEffectiveDate().getYear();
        java.util.Date d = new java.util.Date();
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat( "MM/dd/yyyy" );
        d = formatter.parse(sEffDate);
        stmt.setDate(7, new java.sql.Date(d.getTime()));
      }
      else {
        stmt.setDate(7, null);
      }
      stmt.setTimestamp(8, new java.sql.Timestamp(System.currentTimeMillis()));
      stmt.setString(9, conn.getMetaData().getUserName());
      stmt.setString(10, instId);
      stmt.setString(11, msgCategory);
      stmt.setString(12, msgObject);
      stmt.setString(13, msgRelease);
      stmt.setString(14, a.getType(getAppName()));
      logger.info("Attempting to update Address record " + a.toString() + " for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Updated Address record " + a.toString() + " for InstitutionalId: " + instId + " rc=" + rc);
      stmt.close();
    }
    catch (Exception e) {
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }
  /**
  * Creates a single Address row in the T_ADDRESS table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Address type associated
  * to the Address object passed in as the data to create.
  * <P>
  * @param conn a pre-established database connection.  Since an Address is only ever
  * created as part of a larger transaction (BasicPerson-Create or Update) this
  * insert must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're creating an address for.
  * @param a the Address Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed.
  * @throws SQLException if errors occur creating the Address in the database.
  **/
  protected void createAddress(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Address a) throws SQLException {
    PreparedStatement insertStmt = null;
    String insertString = "INSERT INTO T_ADDRESS (INST_ID, MESSAGE_CATEGORY, " +
                          "MESSAGE_OBJECT, MESSAGE_RELEASE, ADDR_TYPE, STREET1, " +
                          "STREET2, STREET3, CITY, STATE_CODE, ZIP_CODE, EFFECTIVE_DATE, " +
                          "CREATE_DATE, CREATE_USER, MOD_DATE, MOD_USER) " +
                          "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    try {
      insertStmt = conn.prepareStatement(insertString);
      insertStmt.clearParameters();
      insertStmt.setString(1, instId);
      insertStmt.setString(2, msgCategory);
      insertStmt.setString(3, msgObject);
      insertStmt.setString(4, msgRelease);
      insertStmt.setString(5, a.getType(getAppName()));
      insertStmt.setString(6, a.getStreet1(getAppName()));
      insertStmt.setString(7, a.getStreet2(getAppName()));
      insertStmt.setString(8, a.getStreet3(getAppName()));
      insertStmt.setString(9, a.getCityOrLocality(getAppName()));
      insertStmt.setString(10, a.getStateOrProvince(getAppName()));
      insertStmt.setString(11, a.getZipOrPostalCode(getAppName()));
      String sEffDate = "";
      if (a.getEffectiveDate().isEmpty() == false) {
        sEffDate = a.getEffectiveDate().getMonth() + "/" +
                    a.getEffectiveDate().getDay() + "/" +
                    a.getEffectiveDate().getYear();
        java.util.Date d = new java.util.Date();
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat( "MM/dd/yyyy" );
        d = formatter.parse(sEffDate);
        insertStmt.setDate(12, new java.sql.Date(d.getTime()));
      }
      else {
        insertStmt.setDate(12, null);
      }
      insertStmt.setTimestamp(13, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(14, conn.getMetaData().getUserName());
      insertStmt.setTimestamp(15, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(16, conn.getMetaData().getUserName());
      logger.info("Attempting to insert Address record " + a.toString() + " for InstitutionalId: " + instId);
      int insertRc = insertStmt.executeUpdate();
      logger.info("Inserted Address record " + a.toString() + " for InstitutionalId: " + instId);
      insertStmt.close();
    }
    catch (Exception e) {
      if (insertStmt != null) {
        insertStmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }

  /**
  * Deletes a single Phone row from the T_PHONE table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Phone type associated
  * to the Phone object passed in as the delete criteria.
  * <P>
  * @param conn a pre-established database connection.  Since an Address is only ever
  * deleted as part of a larger transaction (BasicPerson-Delete or Update) this
  * delete must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're deleting an address for.
  * @param p the Phone Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed.
  * @throws SQLException if errors occur deleting the Address from the database.
  **/
  protected void deletePhone(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Phone p) throws SQLException {
    PreparedStatement stmt = null;
    String sqlString = "delete from T_PHONE " +
                          "where inst_id=? and MESSAGE_CATEGORY=? AND " +
                          "MESSAGE_OBJECT=? AND MESSAGE_RELEASE=? AND " +
                          "PHONE_TYPE=?";

    try {
      // delete the individual address record passed in
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, instId);
      stmt.setString(2, msgCategory);
      stmt.setString(3, msgObject);
      stmt.setString(4, msgRelease);
      stmt.setString(5, p.getType(getAppName()));
      logger.info("Attempting to delete Phone record " + p.toString() + " for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Deleted Phone record " + p.toString() + " for InstitutionalId: " + instId + " rc=" + rc);
      stmt.close();
    }
    catch (Exception e) {
      conn.rollback();
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }
  /**
  * Updates a single Phone row from the T_ADDRESS table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Phone type associated
  * to the Phone object passed in as the update criteria.
  * <P>
  * @param conn a pre-established database connection.  Since an Phone is only ever
  * updated as part of a larger transaction (BasicPerson-Update) this
  * update must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're updating an address for.
  * @param p the Phone Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed in.
  * @throws SQLException if errors occur updating the Phone from the database.
  **/
  protected void updatePhone(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Phone p) throws SQLException {
    PreparedStatement stmt = null;
    String sqlString = "UPDATE T_PHONE SET PHONE_AREA=?, " +
                          "PHONE_NUMBER=?, MOD_DATE=?, MOD_USER=? " +
                          "WHERE INST_ID=? AND MESSAGE_CATEGORY=? AND " +
                          "MESSAGE_OBJECT=? AND MESSAGE_RELEASE=? AND PHONE_TYPE=?";

    try {
      stmt = conn.prepareStatement(sqlString);
      stmt.clearParameters();
      stmt.setString(1, p.getPhoneArea());
      stmt.setString(2, p.getPhoneNumber());
      stmt.setTimestamp(3, new java.sql.Timestamp(System.currentTimeMillis()));
      stmt.setString(4, conn.getMetaData().getUserName());
      stmt.setString(5, instId);
      stmt.setString(6, msgCategory);
      stmt.setString(7, msgObject);
      stmt.setString(8, msgRelease);
      stmt.setString(9, p.getType(getAppName()));
      logger.info("Attempting to update Phone record " + p.toString() + " for InstitutionalId: " + instId);
      int rc = stmt.executeUpdate();
      logger.info("Updated Phone record " + p.toString() + " for InstitutionalId: " + instId + " rc=" + rc);
      stmt.close();
    }
    catch (Exception e) {
      if (stmt != null) {
        stmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }
  /**
  * Creates a single Phone row in the T_PHONE table.  Uses the msgCategory,
  * msgObject, msgRelease and instId parameters passed in as well as the Phone type associated
  * to the Phone object passed in as the data to create.
  * <P>
  * @param conn a pre-established database connection.  Since a Phone is only ever
  * created as part of a larger transaction (BasicPerson-Create or Update) this
  * insert must occur within that same transaction, therefore, this method does not
  * commit the transaction.
  * @param msgCategory the 'messageCategory' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'com.any-erp-vendor.Person'.
  * @param msgObject the 'messageObject' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: 'BasicPerson'.
  * @param msgRelease the 'messageRelease' attribute extracted from the
  * ControlAreaRequest of the enterprise message.  Example: '1.1'.
  * @param instId associated to the person we're creating an address for.
  * @param p the Phone Java object that was pulled from the BasicPerson object that was
  * built from the enterprise message passed.
  * @throws SQLException if errors occur creating the Phone in the database.
  **/
  protected void createPhone(java.sql.Connection conn, String msgCategory, String msgObject, String msgRelease, String instId, Phone p) throws SQLException {
    PreparedStatement insertStmt = null;
    String insertString = "INSERT INTO T_PHONE (INST_ID, MESSAGE_CATEGORY, " +
                          "MESSAGE_OBJECT, MESSAGE_RELEASE, PHONE_TYPE, PHONE_AREA, " +
                          "PHONE_NUMBER, " +
                          "CREATE_DATE, CREATE_USER, MOD_DATE, MOD_USER) " +
                          "VALUES (?,?,?,?,?,?,?,?,?,?,?)";

    try {
      insertStmt = conn.prepareStatement(insertString);
      insertStmt.clearParameters();
      insertStmt.setString(1, instId);
      insertStmt.setString(2, msgCategory);
      insertStmt.setString(3, msgObject);
      insertStmt.setString(4, msgRelease);
      insertStmt.setString(5, p.getType(getAppName()));
      insertStmt.setString(6, p.getPhoneArea());
      insertStmt.setString(7, p.getPhoneNumber());
      insertStmt.setTimestamp(8, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(9, conn.getMetaData().getUserName());
      insertStmt.setTimestamp(10, new java.sql.Timestamp(System.currentTimeMillis()));
      insertStmt.setString(11, conn.getMetaData().getUserName());
      logger.info("Attempting to insert Phone record " + p.toString() + " for InstitutionalId: " + instId);
      int insertRc = insertStmt.executeUpdate();
      logger.info("Inserted Phone record " + p.toString() + " for InstitutionalId: " + instId);
      insertStmt.close();
    }
    catch (Exception e) {
      if (insertStmt != null) {
        insertStmt.close();
      }
      logger.fatal(e.getMessage(), e);
      throw new SQLException(e.getMessage());
    }
  }

  final private ArrayList logErrors(String errNumber, String errMessage, Throwable e, Document inDoc) {
    logger.fatal(errMessage, e);
    logger.fatal("Message sent in is: \n" + getMessageBody(inDoc));
    ArrayList errors = new ArrayList();
    errors.add(buildError("application", errNumber, errMessage));
    return errors;
  }
 
  final private ArrayList logErrors(String errNumber, String errMessage, Document inDoc) {
    logger.fatal(errMessage);
    logger.fatal("Message sent in is: \n" + getMessageBody(inDoc));
    ArrayList errors = new ArrayList();
    errors.add(buildError("application", errNumber, errMessage));
    return errors;
 
}
TOP

Related Classes of org.any_openeai_enterprise.gateways.warehouse.EnterpriseWarehouseCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.