Sample modified Integration Object template

This sample template illustrates the addition of new code to Integration Object templates, in order to add new function to the Integration Objects that will be generated from it. This sample template is based on the default template provided by ZIETrans. See Sample modified Integration Object template for a description of the additions in this template.

////////////////////////////////////////////////////////////////////////////////
// begin add for HPubExtractFieldAttributes
//
//
//  ZIETrans Customized template that obtains all planes for extracted data 
//  when customreco tag specifying HPubExtractFieldAttributes is coded in the macro
//
//  This software is provided AS IS.
//  Permission to use, copy and modify this software for any purpose and
//  without fee is hereby granted.provided that the name of IBM not be used in
//  advertising or publicity pertaining to distribution of the software without
//  specific written permission.
//
//  IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.IN NO EVENT SHALL IBM
//  BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
//  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
//  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
//  OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// end add for HPubExtractFieldAttributes
////////////////////////////////////////////////////////////////////////////////

%Global
package %9%;
%End

// Host On-Demand support
import com.ibm.eNetwork.beans.HOD.*;            // HOD JavaBeans
import com.ibm.eNetwork.beans.HOD.event.*;      // HOD JavaBeans events
import com.ibm.eNetwork.beans.HOD.trace.*;      // HOD JavaBeans trace
import com.ibm.eNetwork.ECL.*;                  // Host Access Class Library
// begin add for HPubExtractFieldAttributes 
import com.ibm.eNetwork.ECL.screenreco.event.ECLCustomRecoEvent;
// end add for HPubExtractFieldAttributes


//import ZIETrans Session Manager classes
import com.ibm.hats.runtime.connmgr.*;
import com.ibm.hats.runtime.*;
import com.ibm.HostPublisher.IntegrationObject.*;
import com.ibm.hats.util.*;
import com.ibm.hats.common.connmgr.*;
import com.ibm.hats.common.ResourceLoader;
import com.ibm.hats.common.HMacro;
import com.ibm.hats.common.CommonConstants;

import com.ibm.hats.common.customlogic.HatsCustomListener;
import com.ibm.hats.common.wel.SSOMacro; 

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*; 
import java.lang.reflect.*;
import java.beans.*;
import java.util.zip.*;
import org.w3c.dom.Document;
import javax.servlet.*; 


%Global
public class %1% extends HPubHostAccess implements
%End
                                          MacroRuntimeListener,
                                          MacroCustomActionListener ,
                                          MacroParseListener,
                                          MacroTracerListener,
                                          TraceListener,
                                          Serializable,
                                          Runnable
{
  // Do not change the following 2 values
  public static float  getIOTemplateVersion()  { return 8.0F; }          // Template version 
  public static String getIOTemplateType()     { return "-CUSTOMIZED"; } // Template type - Host Customizable
// begin add for HPubExtractFieldAttributes
  public static String getIOTemplateRevision() { return ":1.2"; }       // Template revision - internal value
// end add for HPubExtractFieldAttributes

  // Version information for Integration Object problem determination
  //      -- update this string to whatever value you like if you customize the template
  //      -- the full IO version string is written to traces
  public static String getIOVersionInfo()      { return ""; }  // Customizable version info

  public String hPubIOVersion= getIOBaseVersion()+";"+getHPubBeanType()+
                               getIOTemplateType()+getIOTemplateVersion()+
                               getIOTemplateRevision()+getIOVersionInfo();
  public String getIOVersion() { return hPubIOVersion; }

  // Bean State Constants
  public static final int MACRO_STATE_NOT_INSTANTIATED = 0;
  public static final int MACRO_STATE_INSTANTIATED     = 1;
  public static final int MACRO_STATE_READY_TO_PLAY    = 2;
  public static final int MACRO_STATE_PLAYING          = 3;
  public static final int MACRO_STATE_PARSE_ERROR      = 4;
  public static final int MACRO_STATE_PLAY_FINISHED    = 5;

  int intMacroState = MACRO_STATE_NOT_INSTANTIATED;

  // File Separator - used to locate macro file
  static String staticstringFileSeparator = new String(System.getProperty("file.separator"));

  boolean booleanFirstTimeHere = true;

  // Vector of Generated Objects
  public Vector        vHAOVariables = new Vector();

  // HostPublisher Session Manager objects
  transient HodConn    oConn = null;

  // HOD objects
  Macro         macroBean = null;
  Session       sessionHost = null;
  String        stringMacroName = null;
  transient ECLSession    eclsessionHost = null;
  static MacroScreens oMacroScreens = null;
  boolean welCorrelatorsUsed = false;  

  // Synchronize access of macro file
  static Object oSyncObject = new Object();

  // Variable to determine processing of HOD extract events
  int           intCodePage = 0;
  String        stringCodePage = null;
  boolean       booleanDBCSCodePageInUse = false;

  // Variables used to make known the bean's status
  public String hPubScreenState = null;
  public String hPubMacroMessage = null;

  // HOD Error Message holder
  public String stringHODMacroError = null;

  // Generated Objects
 %HAO_Variable_Definition
  HAOVariable %1% = new HAOVariable("%2%","%3%","%1%",%4%,"%5%",%6%,%7%,%8%,%9%,%12%,%13%,HAO_VARIABLE_SIMPLE);
 %End

 %HAO_Variable_Vector_Definition
  HAOVariable %1% = new HAOVariable("%2%","%3%","%1%",%4%,"%5%",%6%,%7%,%8%,%9%,%12%,%13%,HAO_VARIABLE_ARRAY);
 %End

 %Global
  public static final String stringHODMacroFilename = "%3%";
  public String stringBeanName = new String("%1%");
 %End


  // Constructor
 %Global
  public %1%()
 %End                                                                                                    
  { // Generated vector population
   %HAO_Variable_Definition
    vHAOVariables.addElement(%1%);
   %End


   %HAO_Variable_Vector_Definition
    vHAOVariables.addElement(%1%);
   %End


   hPubBeanType = new String("HOD");
   %Global                                 
   hPubBeanName = new String("%1%");
   %End                                    

   %Global
    %If %5% == pool
    hPubStartPoolName  = new String("%6%");
    hPubStartChainName = null;
    hPubStartType         = BEAN_START_FROM_POOL;
    %Endif

    %If %5% == connection
    hPubStartPoolName  = null;
    hPubStartChainName = new String("%6%");
    hPubStartType         = BEAN_START_FROM_CONNECTION;
    %Endif

    %If %7% == pool
    hPubEndChainName   = null;
    hPubEndType           = BEAN_END_TO_POOL;
    %Endif

    %If %7% == connection
    hPubEndChainName   = new String("%8%");
    hPubEndType           = BEAN_END_TO_CONNECTION;
    %Endif

   %End

  }


  // *************************************************************************
  /* Generated Setters */

 %HAO_Variable_Definition
 %If %4% == true
  public void set%11%( String stringToBe)
  {
    hPubErrorOccurred = 0;
    allowTracing();  // call made in case started from IDE and was not able to
                     // start tracing on the constructor
    if (HPubTracingOn) { Ras.traceEntry( className,"set%11%(String)", stringToBe); }

    %1%.stringValue = stringToBe;
  }
 %Endif
 %End

  /* Generated Getters */
 %HAO_Variable_Definition
  public String get%11%()
  {
     hPubErrorOccurred = 0;
     if (HPubTracingOn) { Ras.trace( className,"get%11% simple: ", %1%.stringValue); }
     return (%1%.stringValue);
  }
 %End

 %HAO_Variable_Vector_Definition
  public synchronized String get%11%(int i)
  {
     hPubErrorOccurred = 0;
     if (  (%1%.oMultiValues.size() != 0)
         &&(i >= 0)
         &&(i < %1%.oMultiValues.size())
        )
     {
       if (HPubTracingOn)
       { Integer integerX = new Integer(i);
         Ras.trace( className,"get%11% array: ",
           integerX.toString(), (String) %1%.oMultiValues.elementAt(i));
       }

       return ( (String) %1%.oMultiValues.elementAt(i));
     }
     else
     { if (HPubTracingOn)
       {
         Integer integerX = new Integer(i);
         Ras.trace( className,"get%11% array element ", "Throwing out of bounds on iteration: ",
           integerX.toString());
       }

       throw new ArrayIndexOutOfBoundsException("Row is Out of Bounds");
     }
  }

  public String[] get%11%()
  {
     hPubErrorOccurred = 0;

     if (HPubTracingOn) { Ras.trace( className,"get%11% ", "array all"); }

     %1%.oStringArray = new String[%1%.oMultiValues.size()];
     %1%.oMultiValues.copyInto(%1%.oStringArray);
     return (String[])%1%.oStringArray.clone();
  }
 %End

  public String getHPubScreenState()
  { // Name of the HOD Macro screen when a macroStateEvent was received
    // and the macro state was STATE_STOPPED, STATE_PLAYING, or STATE_PLAY_ERROR
    hPubErrorOccurred = 0;
    if (HPubTracingOn) { Ras.trace( className,"getHPubScreenState: ", hPubScreenState); }
    return hPubScreenState;
  }

  public void setHPubScreenState(String stringToBe)
  { // Name of the HOD Macro screen when a macroStateEvent was received
    // and the macro state was STATE_STOPPED, STATE_PLAYING, or STATE_PLAY_ERROR
    hPubErrorOccurred = 0;
    hPubScreenState = stringToBe;
    if (HPubTracingOn) { Ras.trace( className,"setHPubScreenState: ", hPubScreenState); }
  }

  public String getHPubMacroMessage()
  {  // The getMessage string receive from the HOD Macro on the
     // latest macroMessageEvent.
     hPubErrorOccurred = 0;
     if (HPubTracingOn) { Ras.trace( className,"getHPubMacroMessage: ", hPubMacroMessage); }
     return hPubMacroMessage;
  }

  public void setHPubMacroMessage(String stringToBe)
  {  // The getMessage string receive from the HOD Macro on the
     // latest macroMessageEvent.
     hPubErrorOccurred = 0;
     hPubMacroMessage = stringToBe;
     if (HPubTracingOn) { Ras.trace( className,"getHPubMacroMessage: ", hPubMacroMessage); }
  }


  // *************************************************************************

  public void DoTheWork()
  { // This is the main method for the bean.  In this method the bean will
    // acquire a session to the host and invoke the HOD macro.  Events
    // fired by the HOD subsystem will be used to communicate with the
    // macro and host.

    HMacro hmacro;
    int index;
    ResourceLoader resLoader; 

    if (HPubTracingOn)
    { Ras.traceEntry( className,"DoTheWork");
    }

    hPubErrorException = null;
    hPubErrorOccurred = 0;

    if (booleanFirstTimeHere == true)
    { booleanFirstTimeHere = false;
    }
    else
    { // reset output variables if bean is being called multiple times.
      resetCurrentVariableValues();
    }

    try
    { // Call extended class to get a HostPublisher session.  It will handle exceptions and
      // return null if there is a problem
      oConn = (HodConn) acquireSessionFromSessionManager(stringBeanName);

      if (oConn == null)
      { // Trace and Log Error
        HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
        oErrorsToLog.handleMessage(stringBeanName, className,
          "DoTheWork", "HodConn_Error_1", HPubTracingOn);

        if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
        return;
      }

      // Get the HOD session
      sessionHost = oConn.getConnection();
      if (sessionHost == null)
      { // Log and Trace the Error
        HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
        oErrorsToLog.handleMessage(oHttpServletRequest, stringBeanName, className,
          "DoTheWork", "BeanConn_Error_3", HPubTracingOn);

        // return session back to source
        releaseSessionToSessionManager(BEAN_END_TO_POOL);

        // invoke error page
        hPubErrorOccurred = 1;
        responseWithErrorKey("BeanConn_Error_3");

        if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
        return;
      }

      // Get the HOD ECL session to determine if the code page being used is DBCS
      eclsessionHost = sessionHost.getECLSession();
      intCodePage = eclsessionHost.GetCodePage();

      if (intCodePage == 37)
      { // Need 37 to convert to "037"
        stringCodePage = "037";
      }
      else
      { Integer integerTemp = new Integer(intCodePage);
        stringCodePage = integerTemp.toString();
      }
      if (isDBCSCodePage(stringCodePage))
      { booleanDBCSCodePageInUse = true;
      }
      else
      { booleanDBCSCodePageInUse = false;
      }

      if (HPubTracingOn) { Ras.trace( className,"DoTheWork","Instantiate a HOD Macro object"); }
      macroBean = new Macro();
      intMacroState = MACRO_STATE_INSTANTIATED;
      stringMacroName = new String(stringHODMacroFilename);
      if (stringMacroName.endsWith(".macro"))
      {
      	index = stringMacroName.lastIndexOf(".macro");
      	stringMacroName = stringMacroName.substring(0,(index));      	
      }
      else if (stringMacroName.endsWith(".hma"))                                             
      {                                                                                      
        index = stringMacroName.lastIndexOf(".hma");                                         
        stringMacroName = stringMacroName.substring(0,(index));                              
      }    

      synchronized(this)
      { try
        { // listen for HOD Macro and Custom events for this macro
          macroBean.addMacroRuntimeListener(this);
          macroBean.addMacroCustomActionListener(this);

          // Query the Host Publisher trace settings for HOD
          HODRasSettings oHODRasSettings = HODRas.getHODRasSettings();
          try
          {
            if (oHODRasSettings != null)
            { macroBean.setTraceLevel(oHODRasSettings.getMacroTracingLevel());
              macroBean.addTraceListener(this);
            }
            // Support additional trace points in HOD macros 
            if ((oHODRasSettings.getMacroTracingLevel() != 0) ||                               
                    (oHODRasSettings.getUserMacroTracingLevel() != 0)) 
            {     
                Macro.setMacroTracer(true);
                if ( oHODRasSettings.getMacroTracingLevel() == HODRas.MACRO_TRACER_LEVEL_2)     
                
                    Macro.setMacroTracerLevel(HODRas.MACRO_TRACER_LEVEL_2);
                else
                    Macro.setMacroTracerLevel(HODRas.MACRO_TRACER_LEVEL_1);
                Macro.addMacroTracerListener(this);
            }
          }
          catch (PropertyVetoException pvEx)
          {
            // ignore
          }

          synchronized(oSyncObject)
          { // Synchronize in order to avoid concurrent access to the global parameters
            // (oMacroScreens).

            if (oMacroScreens != null)
            {                                                                                           
               if (HPubTracingOn){ Ras.trace( className,"doTheWork", "Macro has already been parsed"); }
               macroBean.setParsedMacro( (MacroScreens) oMacroScreens.clone());           
            }                                                                                           
            else 
            {
               if (HPubTracingOn){ Ras.trace( className,"doTheWork","Get macro"); }

               if (HPubTracingOn){ Ras.trace( className,"doTheWork", "Reading Macro from Disk and Parsing"); }
                              
               // Locate the file name of the HOD macro that is being used with this bean.
               // Can not make this part of the bean's jar file due to unicode considerations.
          
               resLoader = new ResourceLoader(new IOResourceProvider(this)); 
               hmacro = resLoader.getMacro(
                   (oHttpServletRequest != null) ? oHttpServletRequest.getContextPath() : null, stringMacroName);         
                                                                                             
               if (hmacro != null)                                                                      
               {
                  macroBean.addMacroParseListener(this); 
                  if (HPubTracingOn){ Ras.trace( className,"doTheWork", "Set Macro and get parsed Macro Screens"); }
                  macroBean.setMacro(hmacro.getMacro());               
                                                      
                  macroBean.setInitialPrompt(true);
                  oMacroScreens = macroBean.getParsedMacro();
               }
               else 
               {
                  ResourceBundle res = ResourceBundle.getBundle("com.ibm.HostPublisher.IntegrationObject.HPub_Resources",
                                                                 Locale.getDefault());

                  // Log and Trace the Error
                  HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
                  String stringTemp1 = new String(res.getString("Macro_File_Name"));
                  oErrorsToLog.concatAndAddStrings(stringTemp1, stringMacroName);
                  oErrorsToLog.handleMessage(oHttpServletRequest, stringBeanName,
                                     className, "DoTheWork", "Internal_Error_1", HPubTracingOn);

                  releaseSessionToSessionManager(BEAN_END_TO_POOL);

                  // invoke error page
                  hPubErrorOccurred = 1;
                  responseWithErrorKey("Internal_Error_1");
                  if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
                  return;
               }
            }
          }

          sessionHost.addCommListener(macroBean);

          if (intMacroState == MACRO_STATE_INSTANTIATED)
          { if (HPubTracingOn)
            { Ras.trace( className,"DoTheWork","Waiting for macro state event STATE_STOPPED to fire");
            }
            // wait for a macroStateEvent with STATE_STOPPED before continuing.
            wait();
          }
          else
          { if (HPubTracingOn) { Ras.trace( className,"DoTheWork","Ready to play macro"); }
          }


        }
        catch(InterruptedException oException)
        { // Log and Trace the Error
          HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
          oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                             className, "DoTheWork", "Interrupted_Error_1", HPubTracingOn);

          releaseSessionToSessionManager(BEAN_END_TO_POOL);

          // invoke error page
          hPubErrorOccurred = 1;
          responseWithErrorKey("Interrupted_Error_1");
          if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
          return;
        }
      }

      if (intMacroState == MACRO_STATE_READY_TO_PLAY)
      { // To avoid a possible deadlock with HOD when a macro error occurs, the play() will
        // be moved outside of the synchronized block and the state variable will be used
        // to avoid errant processing on our part.
        if (HPubTracingOn) { Ras.trace( className,"DoTheWork","Call Macro.play()"); }
        intMacroState = MACRO_STATE_PLAYING;
        registerCustomScreenListeners(macroBean);

        // If the connection supports Web Express Logon, then the macro 
        // may contain Java function calls that need access to the HttpServletRequest which
        // is driving this connection/macro.   Must store this info for WEL.
        HodConnSpec connSpec = (HodConnSpec) oConn.getSpec();
        if ((connSpec != null) && (connSpec.isWelEnabled()))
        {
           com.ibm.hats.common.wel.SSOMacro.storeCorrelators( /*ECLSession*/ eclsessionHost,
                                                              /*HttpServletRequest*/ oHttpServletRequest,
                                                              /*HodConnSpec*/ connSpec );
           welCorrelatorsUsed = true;
        }
        
        // Play the macro - what we're here for!
        macroBean.play();

        synchronized(this)
        { if (intMacroState != MACRO_STATE_PLAY_FINISHED)
          try
          { wait();
          }
          catch(InterruptedException oException)
          { // Trace and Log Error
            HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
            oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                               className, "DoTheWork", "Interrupted_Error_1", HPubTracingOn);

            releaseSessionToSessionManager(BEAN_END_TO_POOL);

            // invoke error page
            hPubErrorOccurred = 1;
            responseWithErrorKey("Interrupted_Error_1");
            if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
            return;
          }
        }
      }
    }

    // catch MacroException here
    catch (MacroException oException)
    { // Trace and Log Error
      HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
      oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                         className, "DoTheWork", "HOD_Macro_Error_1", HPubTracingOn);

      releaseSessionToSessionManager(BEAN_END_TO_POOL);

      // invoke error page
      hPubErrorOccurred = 1;
      responseWithErrorKey("HOD_Macro_Error_1");

      if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
      return;

    }

    catch (Exception oException)
    { // Trace and Log Error
      HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
      oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                         className, "DoTheWork", "Internal_Error_1", HPubTracingOn);

      releaseSessionToSessionManager(BEAN_END_TO_POOL);

      // invoke error page
      hPubErrorOccurred = 1;
      responseWithErrorKey("Internal_Error_1");

      if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
      return;
    }

    // If the connection supports Web Express Logon, we previously
    // stored correlators for use by a WEL-enabled macro.   Cleanup of the macro
    // means we cleanup the correlators.
    finally
    {
      if (welCorrelatorsUsed)  // we know then that wel is enabled and we've got a session object
        com.ibm.hats.common.wel.SSOMacro.removeCorrelators( /*ECLSession*/ eclsessionHost);
    }

    releaseSessionToSessionManager(hPubEndType);

    if (stringHODMacroError != null)
    { hPubErrorOccurred = 1;
      responseWithErrorKey(stringHODMacroError);
    }

    if (HPubTracingOn) { Ras.traceExit( className,"DoTheWork"); }
  }

  // *************************************************************************

  public void resetCurrentVariableValues()
  { // This bean can be called (using the DoTheWork method) multiple times
    // without having to be instantiated each time.  Therefore the output
    // values need to be reset upon each call.

    HAOVariable haovWorkOnThis;

    if (HPubTracingOn)
    { Ras.traceEntry( className,"resetCurrentVariableValues");
    }

    hPubErrorOccurred = 0;
    hPubScreenState = null;

    for (int i=0; i < vHAOVariables.size(); i++)
    { haovWorkOnThis = (HAOVariable) vHAOVariables.elementAt(i);
      if (haovWorkOnThis.intVariableType == HAO_VARIABLE_SIMPLE)
      { // simple variable
        if (haovWorkOnThis.booleanInputVariable == false)
        { // if variable is output, reset null
          // if variable is input,  leave value as is.
          haovWorkOnThis.stringValue = null;
        }
      }
      else
      { // vector variable
        // Garbage collect
        haovWorkOnThis.oMultiValues = null;
        // Set up new vector
        haovWorkOnThis.oMultiValues = new Vector();
      }
    }

    if (HPubTracingOn)
    { Ras.traceExit( className,"resetCurrentVariableValues");
    }
  }


  // *************************************************************************

  public void releaseSessionToSessionManager(int intEndType)
  {
    //  Releaase the session back to the HostPublisher Subsystem and
    //  perform general clean up.
    if (HPubTracingOn) { Ras.traceEntry( className,"releaseSessionToSessionManager"); }

    try
    { if (sessionHost != null)
      { if (HPubTracingOn)
        { Ras.trace( className,"releaseSessionToSessionManager","Release HOD Session object");
        }
        // remove the HOD session listeners
        sessionHost.removeCommListener(macroBean);
        sessionHost = null;
      }
      if (macroBean != null)
      { if (HPubTracingOn)
        { Ras.trace( className,"releaseSessionToSessionManager","Release HOD Macro object");
        }
        // remove the HOD Macro listeners
        macroBean.removeMacroParseListener(this);
        macroBean.removeMacroCustomActionListener(this);
        Macro.removeMacroTracerListener(this);
        macroBean.removeMacroRuntimeListener(this);

        macroBean.dispose();
        macroBean = null;
      }
    }
    catch (MacroException oException)
    { // ignore, because we are attempting to clean up.
    }

    if (oConn != null)
    { if (HPubTracingOn)
      { Ras.trace( className,"releaseSessionToSessionManager","Release HPub connection object");
      }
      try
      { switch (intEndType)
        { case BEAN_END_TO_POOL:
            // Release the session back to HostPublisher
            Ras.trace( className,"releaseSessionToSessionManager","Release To Pool");
            oConn.releaseConnectionToSource(oHttpServletRequest, this);
          break;

          case BEAN_END_TO_CONNECTION:

            if (  (intStartMethod == START_FROM_EVENT)
                ||(intStartMethod == START_FROM_PROCESSREQUEST)
               )
            { Ras.trace( className,"releaseSessionToSessionManager","Release From NON-Web session");

              if (hPubLinkKey == null)
              { Ras.trace( className,"releaseSessionToSessionManager","No link key - seed key with oConn.getTitle()");

                if (hPubStartType == BEAN_START_FROM_POOL)
                { hPubLinkKey = oConn.getTitle();
                  oConn.saveConnectionWithKey(hPubLinkKey, hPubEndChainName, this);
                }
                else
                { Ras.trace( className,"releaseSessionToSessionManager","Error No link key when bean released from a chain");

                  HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
                  oErrorsToLog.handleMessage(oHttpServletRequest, stringBeanName, className,
                    "releaseSessionToSessionManager", "BeanConn_Error_5", HPubTracingOn);

                 // invoke error page
                 hPubErrorOccurred = 1;
                 responseWithErrorKey("BeanConn_Error_5");
                }
              }
              else
              { Ras.trace( className,"releaseSessionToSessionManager","link key provided:", hPubLinkKey);
                oConn.saveConnectionWithKey(hPubLinkKey, hPubEndChainName, this);
              }

            }

            else
            {
               // If we are passing the connection to the ZIETrans entry servlet,
               // we need to insure that the connection is not returned to the
               // connection pool.  Also, if no chaining is occurring, then
               // add a predefined label to be used when the connection is saved.
               if ((getHPubSaveConnOnError() == true) &&                
                   (isTransformConn() == true))                         
               {                                                        
                  String label;                                         
                  if (hPubEndChainName == null)                         
                     label = CommonConstants.PARAM_NO_CHAINING;         
                  else                                                  
                     label = hPubEndChainName;                          
                  oHttpServletRequest.setAttribute(CommonConstants.ZIETrans_EXISTING_CONN, label); 
                  oConn.saveConnectionInWebsession(oHttpServletRequest, label, this);  
               }                                                        
               else                                                     
               {                                                        
                  // Normal chain processing  
                  oConn.saveConnectionInWebsession(oHttpServletRequest, hPubEndChainName, this);
               }                                                        

            }

          break;
        }
        oConn = null;

        cleanupHPubCommon();

      }
      catch (ConnException oException)
      { // Trace and Log Error
        HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
        oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                           className, "releaseSessionToSessionManager", HPubTracingOn);

      }
    }

    if (HPubTracingOn) { Ras.traceExit( className,"releaseSessionToSessionManager"); }
    return;
  }

  // *************************************************************************

  protected void finalize()
  {
    if (HPubTracingOn) { Ras.traceEntry( className,"finalize"); }
    releaseSessionToSessionManager(BEAN_END_TO_POOL);
    if (HPubTracingOn) { Ras.traceExit( className,"finalize"); }
  }

  // *************************************************************************

  public void parseFailed(MacroParseEvent eventParseError)
  { // HOD parse event fired for this macro

    // Not that our macros would fail to parse, but if the user hand-modified
    // a macro, we need to catch the error here

    // Log and trace the error
    MacroParseStat mpStat;
    HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();

    if (HPubTracingOn) { Ras.traceEntry( className,"parseFailed"); }
    ResourceBundle res = ResourceBundle.getBundle("com.ibm.HostPublisher.IntegrationObject.HPub_Resources",
                                                  Locale.getDefault());

    intMacroState = MACRO_STATE_PARSE_ERROR;

    if (macroBean != null)
    { String stringTemp1 = new String(res.getString("Macro_Name"));
      oErrorsToLog.concatAndAddStrings(stringTemp1, stringMacroName);
    }

    oErrorsToLog.handleMessage(oHttpServletRequest, stringBeanName, className,
      "parseFailed", "HOD_Macro_Parse_Error_1", HPubTracingOn);

    for (Enumeration e = eventParseError.parseStats(); e.hasMoreElements();)
    {
      mpStat = (MacroParseStat) e.nextElement();
      StringBuffer stringbufferErrorMessage = new StringBuffer(new Integer(mpStat.getLineNum()).toString());
      stringbufferErrorMessage.append(mpStat.getLineText());
      stringbufferErrorMessage.append(mpStat.getStatMessage());
      if (HPubTracingOn) { Ras.trace( className,"parseFailed",stringbufferErrorMessage.toString()); }

    }

    if (HPubTracingOn) { Ras.traceExit( className,"parseFailed"); }
  }

  // *************************************************************************

  public void parsePassed()
  { // What we expected, so only trace that we go here
    if (HPubTracingOn) { Ras.traceEntry( className,"parsePassed"); }
    if (HPubTracingOn) { Ras.traceExit( className,"parsePassed"); }
  }

  // *************************************************************************

  public synchronized void macroMessageEvent(MacroMessageEvent mmEv)
  { // A HOD Macro message event was fired for this macro.

    // If there was a message associated with a macro screen (the only way
    // to do this in this release is for the user to hand edit the macro file)
    // then store it here, in this way another program can query about what
    // screen the bean ended at.
    if (HPubTracingOn) { Ras.traceEntry( className,"macroMessageEvent"); }
    hPubMacroMessage = mmEv.getMessage();
    if (HPubTracingOn) { Ras.traceExit( className,"macroMessageEvent"); }

  }

  // *************************************************************************

  public void traceEvent(TraceEvent tEv)
  { // A HOD trace event was fired

    // If tracing is on, or the trace event was a HOD exception, then
    // pass this on to the HostPublisher subsystem for tracing.

    int intMessageType;

    intMessageType = tEv.getMsgType();

    if (  (HPubTracingOn)
        ||(intMessageType == TraceEvent.LOGEXCEPTION)
       )
    {
      if (oConn != null)
      {
        oConn.traceEvent(tEv);
      }
    }
  }

  // *************************************************************************

  public synchronized void macroTraceEvent(MacroTraceEvent mtEv)
  { // A HOD trace event was fired for this macro

    // If tracing is on, then pass this on to the HostPublisher subsystem
    // for tracing.
    if (HPubTracingOn)
    {
      Ras.trace(className, "macroTraceEvent", mtEv.getData());
    }
  }

  // *************************************************************************
  /**
  * Public method used by HOD9.0 to inform the code executing a macro
  * that a Macro Tracer action has been executed by the macro engine.
  * This method saves the trace entry to the HP trace file only if User Macro Tracing
  * or Support Tracing was selected.
  *
  * @param MacroTracerEvent
  **/
  public void macroTracerEvent(MacroTracerEvent mtEv)
  { // A HOD trace event was fired
    // If tracing is on, or the trace event was a HOD exception, then
    // pass this on to the HostPublisher subsystem for tracing.
      if (oConn != null)
      {
        oConn.macroTracerEvent(mtEv);
      }
  }

  // ****************************************************************************

  public void macroErrorEvent(MacroErrorEvent oMacroErrorEvent)
  { // A HOD error event was fired for this macro

    HPubErrorsToLog      oErrorsToLog = new HPubErrorsToLog();
    if (HPubTracingOn) { Ras.traceEntry( className,"macroErrorEvent"); }

    // Prepend message string with notice that this was a macroerrorevent from HOD
    ResourceBundle res = ResourceBundle.getBundle("com.ibm.HostPublisher.IntegrationObject.HPub_Resources",
                                                  Locale.getDefault());
    StringBuffer errorEventMessage = new StringBuffer(res.getString("HOD_MACRO_ERROR_EVENT"));

    // HOD is not translating this particular message for this release... do it for them
    if ((oMacroErrorEvent.getMessageID() == Macro.EID_M_CONNECTION_DOWN))
      errorEventMessage.append(res.getString("HOD_MACRO_ERROR_EVENT_CONNECTION_DOWN"));
    else
      errorEventMessage.append(oMacroErrorEvent.getMessage());

    // Most of the error reporting will be done when the subsequent
    //  MacroStateEvent.STATE_PLAY_ERROR is received.  But log the
    //  Error Event Message now.
    if (HPubTracingOn) { Ras.trace( className, "macroErrorEvent: ", errorEventMessage.toString()); }

    oErrorsToLog.stringToLog(errorEventMessage.toString());
    oErrorsToLog.log(Ras.TYPE_ERROR, stringBeanName, className );

    stringHODMacroError = new String("HOD_Macro_Error_1");

    if (HPubTracingOn) { Ras.traceExit( className,"macroErrorEvent"); }
  }
  
  

  // ****************************************************************************
   public void execute(MacroCustomActionEvent oMacroCustomActionEvent)
   {//A HOD custom event was fired

      if (HPubTracingOn) { Ras.traceEntry( className,"macroCustomActionEvent"); } 
      customlistener.setHodConn(oConn);                 
      customlistener.execute(oMacroCustomActionEvent);  
      customlistener.releaseHodConn();                  
      
      if (HPubTracingOn) { Ras.traceExit( className,"macroCustomActionEvent"); }

   }

  // ****************************************************************************

   public void halt(MacroCustomActionEvent oMacroCustomActionEvent)
   {//A HOD custom event gets halted

      customlistener.setHodConn(oConn);                 
      customlistener.halt(oMacroCustomActionEvent);     
      customlistener.releaseHodConn();                  


   }

  
  // ****************************************************************************

  public void macroPromptEvent(MacroPromptEvent oMacroPromptEvent)
  { // A HOD Macro prompt event was fired for this macro

    MacroPrompts oMacroPrompts;
    HAOVariable haovWorkOnThis;

    if (HPubTracingOn) { Ras.traceEntry( className,"macroPromptEvent"); }

    
    // Set the all the prompt values that the IntegrationObject knows of.

    // Get the HOD macro prompt object
    oMacroPrompts = oMacroPromptEvent.getPrompts();
    synchronized (this)
    { for (int i=0; i < vHAOVariables.size(); i++)
      { haovWorkOnThis = (HAOVariable) vHAOVariables.elementAt(i);

        // Populate the object with the prompt values that were given to the bean
        // via the "set" methods.
        if (haovWorkOnThis.booleanInputVariable == true)
        { if (  (  (haovWorkOnThis.stringValue != null)
                 &&(haovWorkOnThis.stringValue.length() > 0)
                )
              ||(  (oMacroPrompts.getPromptDefault(haovWorkOnThis.stringPromptName) != null)
                 &&(oMacroPrompts.getPromptDefault(haovWorkOnThis.stringPromptName).length() > 0)
                )
             )
          { // If the object has a prompt value (usually obtain via the beans "set" methods),
            // Or, if the object has not be given a prompt value but there has been
            // defined a default value,
            // then set it in the HOD Prompt object with
            // the prompt name that was given by the user (using the Host Access GUI).
            if (HPubTracingOn)
            { Ras.trace( className,"macroPromptEvent","Setting the following Prompt Name and Value",
                         haovWorkOnThis.stringPromptName, haovWorkOnThis.stringValue);
            }
            oMacroPrompts.setPromptValue(haovWorkOnThis.stringPromptName,haovWorkOnThis.stringValue);
          }
          else
          { // If the prompt value can not be set, and there is no default,
            // then find the HOD prompt name for this object and set the prompt action to skip.

            MacroActionPrompt oMacroActionPrompt = null;
            String stringThisPromptName = new String(haovWorkOnThis.stringPromptName);
            int intNumberOfPrompts = oMacroPrompts.size();

            for (int j=0; j < intNumberOfPrompts; j++)
            { oMacroActionPrompt = oMacroPrompts.get(j);
              if (stringThisPromptName.equals(oMacroActionPrompt.getName()))
              { oMacroActionPrompt.setSkip(true);
                if (HPubTracingOn)
                { Ras.trace( className,"macroPromptEvent",
                            "MacroActionPrompt.setSkip called on the following Prompt Name",
                            haovWorkOnThis.stringPromptName);
                }
                break;
              }
              oMacroActionPrompt = null;  // quick garbage collect
            }
          }
        }
      }
    }
    try
    { oMacroPromptEvent.setPrompts(oMacroPrompts);
    }
    catch (MacroException oException)
    { // Trace and Log Error
      HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
      oErrorsToLog.handleException(oException, oHttpServletRequest, stringBeanName,
                         className, "macroPromptEvent", "HOD_Macro_Error_1", HPubTracingOn);
    }

    if (HPubTracingOn) { Ras.traceExit( className,"macroPromptEvent"); }
  }

  // ****************************************************************************

  public void macroExtractEvent(MacroExtractEvent oMacroExtractEvent)
  { // a HOD macroExtractEvent was fired for this macro

    HAOVariable haovWorkOnThis;

    if (HPubTracingOn) { Ras.traceEntry( className,"macroExtractEvent"); }

    // extract the data (VT,3270, 5250 datastream/emulator) that was associated with this extract
    String stringExtractNameForThisEvent = oMacroExtractEvent.getExtractName();
    String data [] = oMacroExtractEvent.getData();
    if (HPubTracingOn)
    {       
        Ras.trace( className,"macroExtractEvent","Extract Name: ", stringExtractNameForThisEvent);
        for (int j=0; j < data.length; j++)
        {
            Ras.trace(className, "macroExtractEvent", "data extracted: ", data[j]); 
        }
    }

    // Go through list of objects, for each variable
    // whose extract name matches stringExtractName, extract
    // the correct fields for that object
    synchronized (this)
    { for (int i = 0; i < vHAOVariables.size(); i++)
      { haovWorkOnThis = (HAOVariable) vHAOVariables.elementAt(i);
        if ( haovWorkOnThis.stringExtractName.equals(stringExtractNameForThisEvent) == true)
        { pullVariableValueFromExtractData( haovWorkOnThis, data);
        }
      }
    }

    if (HPubTracingOn) { Ras.traceExit( className,"macroExtractEvent"); }

    return;
  }

  // ****************************************************************************

  public void pullVariableValueFromExtractData( HAOVariable haovTarget, String [] stringarrayExtractData)
  {
    // To make life easy
    // X is horizontal, Y is Vertical
    int intX  = haovTarget.intXLocation;     // location relative to the extracted data
    int intDX = haovTarget.intXDelta;
    int intY  = haovTarget.intYLocation;     // location relative to the extracted data
    int intDY = haovTarget.intYDelta;

    // -----------------------------------------------------------------------
    // Note:  The actual x,y coordinates of the variable relative to the
    //        host screen are located in:
    //          haovTarget.intXScreenLocation
    //                  and
    //          haovTarget.intYScreenLocation
    // -----------------------------------------------------------------------

    if (HPubTracingOn) { Ras.traceEntry( className,"pullVariableValueFromExtractData"); }

    // Check parameters, if invalid log error and return
    if (  (intDX == 0)
        ||(intDY == 0)
        ||(intX < 0 )
        ||(intY < 0 )
        ||(intY >= stringarrayExtractData.length)
        ||(intY + intDY > stringarrayExtractData.length)
       )
    { // log and trace error
      HPubErrorsToLog oErrorsToLog = new HPubErrorsToLog();
      oErrorsToLog.handleMessage(oHttpServletRequest, stringBeanName, className,
        "pullVariableValueFromExtractData", "HOD_Macro_Error_2", HPubTracingOn);

      if (HPubTracingOn) { Ras.traceExit( className,"pullVariableValueFromExtractData"); }
      return;
    }

    if (haovTarget.intVariableType == HAO_VARIABLE_SIMPLE)
    { // simple (non-table) extract/object
      StringBuffer stringbufferHoldingValue;

      // concatenate multiple extracts which have the same name
      if (haovTarget.stringValue == null)
      { stringbufferHoldingValue = new StringBuffer("");
      }
      else
      { stringbufferHoldingValue = new StringBuffer(haovTarget.stringValue);
      }

      if (intDY == 1)
      { // This extract is contained in one row of data
        String stringOutput = pullStringFromIndexes(stringarrayExtractData[intY], intX, intDX,
                                                    haovTarget.intVariableType );
        stringbufferHoldingValue.append(stringOutput);
      }
      else
      { for (int j = 0; j < intDY; j++)
        { // This extract spans multiple rows of data.
          String stringOutput = pullStringFromIndexes(stringarrayExtractData[intY+j], intX, intDX,
                                                      haovTarget.intVariableType );
          stringbufferHoldingValue.append(stringOutput);
        }
      }

      if (stringbufferHoldingValue.toString() != null)
      { // store value in object
        haovTarget.stringValue = new String( stringbufferHoldingValue.toString() );
      }

      if (HPubTracingOn)
      { Ras.trace( className,"pullVariableValueFromExtractData",
        "Simple Variable Value Extracted: ", haovTarget.stringValue);
      }
    }
    else
    { // vector (table) extract/object
      for (int j = 0; j < intDY; j++)
      { // Go through each row and get this columns worth of data
        String stringOutput = pullStringFromIndexes(stringarrayExtractData[intY+j], intX, intDX,
                                                    haovTarget.intVariableType );

        if (HPubTracingOn)
        { Integer integerX = new Integer(j);
          Ras.trace( className,"pullVariableValueFromExtractData ", integerX.toString(),
           stringOutput);
        }
        // One object holds the entire column of data
        haovTarget.oMultiValues.addElement(new String(stringOutput));
      }
    }

    if (HPubTracingOn) { Ras.traceExit( className,"pullVariableValueFromExtractData"); }
  }

  // ****************************************************************************

  public String pullStringFromIndexes( String stringInput, int intX, int intDX, int intVariableType)
  { // stringInput - string from which to acquire the substring.
    // intX - starting index of the substring
    // intDX - length of the substring
    // intVariableType - if substring is a Simple object (non-table) or Vector (table)
    // output - resulting substring
    // This routine would not be needed, except for the case of the simple object
    // that has DBCS characters, as described below

    int intCount;
    int intExtractStart;
    int intExtractLength;
    int intInputLength;

    if (HPubTracingOn) { Ras.traceEntry( className,"pullStringFromIndexes"); }

    if (booleanDBCSCodePageInUse)
    {
      // Screen Coordinates, and not Extract Coordinates are given for DBCS and Simple Variables
      if (HPubTracingOn)
      { Ras.trace(className,"pullStringFromIndexes", "DBCS Code Page In Use detected");
      }
      intInputLength = stringInput.length();
      // find where X starts inside of stringInput
      intCount = 0;
      for (intExtractStart=0; intExtractStart < intInputLength; intExtractStart++)
      { if (intCount >= intX) break;

        if ( IsDBCSChar(stringInput.charAt(intExtractStart)) )
        { // DBCS characters take up two columns, but only one extracted character element
          Ras.trace(className,"pullStringFromIndexes", "Extract Start - DBCS Character found");
          intCount+=2;
        }
        else
        { intCount ++;
        }
      }

      // Find the length of the desired extract
      intCount = 0;
      for (intExtractLength = 0; intExtractLength < intInputLength - intExtractStart; intExtractLength++)
      { if (intCount >= intDX) break;

        if ( IsDBCSChar(stringInput.charAt(intExtractStart+intExtractLength)) )
        { // DBCS characters take up two columns, but only one extracted character element
          Ras.trace(className,"pullStringFromIndexes", "Extract Length - DBCS Character found");
          intCount+=2;
        }
        else
        { intCount ++;
        }
      }
    }
    else
    { // For single byte and table variables, the coordinates given in the extract match
      // the coordinates that were determined by the Host Access GUI.
      intExtractStart = intX;
      intExtractLength = intDX;
    }

    if (HPubTracingOn)
    { Integer integerTemp = new Integer(intExtractStart);
      Ras.trace(className,"pullStringFromIndexes", "extract start index: ", integerTemp);
      integerTemp = new Integer(intExtractLength);
      Ras.trace(className,"pullStringFromIndexes","extract length: ", integerTemp);
      Ras.trace(className,"pullStringFromIndexes","returning following string: ",
        stringInput.substring(intExtractStart, intExtractStart+intExtractLength));
    }

    if (HPubTracingOn) { Ras.traceExit( className,"pullStringFromIndexes"); }

    // return the extracted string
    return ( stringInput.substring(intExtractStart, intExtractStart+intExtractLength));
  }

  // ****************************************************************************

  public boolean isDBCSCodePage(String codePage)
  { boolean booleanReturnCode = false;

    if (HPubTracingOn) { Ras.traceEntry( className,"isDBCSCodePage"); }

    booleanReturnCode = checkCodePages(DBCSCodePages,  codePage);

    if (HPubTracingOn) { Ras.traceExit( className,"isDBCSCodePage"); }

    return booleanReturnCode;

  }

  // ****************************************************************************

  private boolean checkCodePages(int[] codePageList, String codePage)
  { // check a list of code page numbers with a String that represents a number
    boolean booleanReturnCode = false;;

    if (HPubTracingOn) { Ras.traceEntry( className,"checkCodePages"); }

    if ((codePageList == null) || (codePage == null))
    {
      if (HPubTracingOn) { Ras.traceExit( className,"checkCodePages"); }
      return booleanReturnCode;
    }
    try
    {
      booleanReturnCode = checkCodePages(codePageList, Integer.valueOf(codePage).intValue());
      if (HPubTracingOn) { Ras.traceExit( className,"checkCodePages"); }
      return booleanReturnCode;
    }
    catch (NumberFormatException e)
    {
      // If a number format exception is caught then our value can not match any of the predefined values
      // so return false.
      if (HPubTracingOn) { Ras.traceExit( className,"checkCodePages"); }
      return booleanReturnCode;
    }
  }

  // ****************************************************************************

  private boolean checkCodePages(int[] codePageList, int codePage)
  { // check a list of code page numbers with a code page number
    boolean booleanReturnCode = false;

    if (HPubTracingOn) { Ras.traceEntry( className,"checkCodePages"); }

    for (int i=0; i < codePageList.length; i++)
    { if (codePageList[i] == codePage)
      { booleanReturnCode = true;
        if (HPubTracingOn) { Ras.traceExit( className,"checkCodePages"); }
        return booleanReturnCode;
      }
    }
    if (HPubTracingOn) { Ras.traceExit( className,"checkCodePages"); }
    return booleanReturnCode;
  }

  // ****************************************************************************

  static public final int[] DBCSCodePages =
  { 930,   // Japan Kana Ext
    939,   // Japan Eng Ext
    933,   // Korean
    937,   // Traditional Chinese
    935,   // Simpilified Chinese
    942,   // Japan ASCII
    949,   // Korea ASCII
    950,   // T-Chinese ASCII
    948,   // T-Chinese ASCII
    964,   // T-Chinese ASCII
    1364,  // Korean Euro  
    1371,  // Taiwan Euro  
    1381,  // Simplified Chinese
    1388,  // Simplified Chinese
    1390,  // Japan Katakana ( Extended Euro )   
    1399   // Japan Latin Euro (Host MBCS - Latin-Kanji)  
  };

  // DBCS range table for UNICODE
  private static final char[][] dbrange =
  {
    {'\u00B0', '\u00FF'},              // DB Latin 1 supplement
    {'\u0100', '\u01FF'},              // DB Latin 1 Extended-A
    {'\u02B0', '\u02E9'},              // DB Spacing Modifier
    {'\u0370', '\u04FF'},              // DB Greek/Cyrillic
    {'\u2000', '\u27BE'},              // DB Symbols
    {'\u3000', '\u33FE'},              // CJK Misc
    {'\u4E00', '\u9FFF'},              // CJK Ideographics
    {'\uAC00', '\uD7A3'},              // Hanguel
    {'\uE000', '\uF8FF'},              // User defined
    {'\uF900', '\uFAFF'},              // CJK Compatibility
    {'\uFE30', '\uFE4F'},              // CJK Compatibility
    {'\uFE50', '\uFE6F'},              // Small form Variants
    {'\uFF01', '\uFF5E'},              // full width ASCII
    {'\uFFE0', '\uFFE6'},              // full width punctuation and currency signs

    {'\u0000', '\u0000'}               // end of table
  };

  // ****************************************************************************

  public boolean IsDBCSChar(char charInput)
  { // check if input char (UNICODE character value) is within DBCS range
    int i;
    // if not DBCS session, always return false
    boolean booleanDBCS = false;

    // If single byte Korean Won, it should be treated as SBCS character
    if (charInput == '\u20a9')
    { return booleanDBCS;
    }

    // If single byte Euro sign, it should be treated as SBCS chracter
    if (charInput == '\u20ac')
    { return booleanDBCS;
    }

    // go thru the DBCS range table, and find if char is DBCS
    for (i=0; dbrange[i][0] != '\u0000'; i++)
    { // if character is within DBCS range, return true
      if ( (dbrange[i][0] <= charInput) && (dbrange[i][1] >= charInput) )
      { booleanDBCS = true;
        break;
      }
    }

    // these characters also take two columns for DBCS code pages
    if (  (!booleanDBCS)
        &&(  (charInput == 0xa1)  // inverted !
           ||(charInput == 0xa4)  // currency Sign
           ||(charInput == 0xa7)  // section sign
           ||(charInput == 0xa8)  // diaeresis
           ||(charInput == 0xaa)  // a with underscore
         )
       )
    { booleanDBCS = true;
    }

    return booleanDBCS;
  }

  // ****************************************************************************

  public void macroStateEvent(MacroStateEvent oMacroStateEvent)
  { // a HOD macroStateEvent was fired for this macro
    MacroScreen oMacroScreen;

    if (HPubTracingOn) { Ras.traceEntry( className,"macroStateEvent"); }

    switch (oMacroStateEvent.getState())
    { case MacroStateEvent.STATE_STOPPED:
        // Macro is Stopped, which means it is ready to be played (which can also mean
        // that the macro has finished playing)
        if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","STATE_STOPPED fired"); }

        oMacroScreen = oMacroStateEvent.getMacroScreen();
        if (oMacroScreen != null)
        { hPubScreenState = oMacroScreen.getName();
        }

        synchronized(this)
        { switch (intMacroState)
          { case MACRO_STATE_INSTANTIATED:
              intMacroState = MACRO_STATE_READY_TO_PLAY;
              if (HPubTracingOn) { Ras.trace( className,"macroStateEvent",
                                              "perform notify at STATE_STOPPED(INSTANTIATED)"); }
              // We are waiting in method "DoTheWork" to start playing
              notify();
            break;

            case MACRO_STATE_PLAYING:
            case MACRO_STATE_PARSE_ERROR:
              intMacroState = MACRO_STATE_PLAY_FINISHED;
              if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","perform notify at STATE_STOPPED"); }
              // We are waiting in method "DoTheWork" to be finished playing
              notify();
            break;

            default:
            break;
          }
        }
      break;

      case MacroStateEvent.STATE_PLAYING:
        if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","STATE_PLAYING fired"); }

        oMacroScreen = oMacroStateEvent.getMacroScreen();
        if (oMacroScreen != null)
        { hPubScreenState = oMacroScreen.getName();
        }

      break;

      case MacroStateEvent.STATE_RECORDING:
      case MacroStateEvent.STATE_PLAY_PAUSED:
      case MacroStateEvent.STATE_RECORD_PAUSED:
        // Since the macro is being run to completion, we don't expect to be in this state.
        if (HPubTracingOn)
        { Ras.trace( className,"macroStateEvent", "STATE_RECORDING/PLAY_PAUSED/RECORD_PAUSE fired");
        }
      break;

      case MacroStateEvent.STATE_EMPTY:
         if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","STATE_EMPTY fired"); }
         // Trace and Log Error
         HPubErrorsToLog oErrorsToLog2 = new HPubErrorsToLog();
         oErrorsToLog2.handleMessage(oHttpServletRequest, stringBeanName, className,
             "macroStateEvent", "HOD_Macro_Error_3", HPubTracingOn);

         stringHODMacroError = new String("HOD_Macro_Error_3");

         synchronized(this)
         { switch (intMacroState)
           { case MACRO_STATE_INSTANTIATED:
               intMacroState = MACRO_STATE_READY_TO_PLAY;

               if (HPubTracingOn) { Ras.trace( className,"macroStateEvent",
                                               "perform notify at STATE_EMPTY(INSTANTIATED)"); }
              // We are waiting in method "DoTheWork" to start playing
               notify();
             break;

             case MACRO_STATE_PLAYING:
             case MACRO_STATE_PARSE_ERROR:
               // we should never get here (can't be playing an empty macro)
               intMacroState = MACRO_STATE_PLAY_FINISHED;
               if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","perform notify at STATE_EMPTY"); }
               // We are waiting in method "DoTheWork" to be finished playing
               notify();
             break;
           }
         }
      break;

      case MacroStateEvent.STATE_DISCONNECTED:
        if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","STATE_DISCONNECTED fired"); }

        stringHODMacroError = new String("HOD_Macro_Error_1");

        switch (intMacroState)
        { case MACRO_STATE_INSTANTIATED:
          case MACRO_STATE_PLAYING:
          case MACRO_STATE_PARSE_ERROR:
            synchronized(this)
            { intMacroState = MACRO_STATE_PLAY_FINISHED;
              if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","perform notify at STATE_DISCONNECTED"); }
              notify();
            }
          break;

          default:
          break;
        }
      break;

      case MacroStateEvent.STATE_PLAY_ERROR:
        ECLErr               oECLErr;
        ECLSession           oECLSession;
        ECLPS                oECLPS;
        char[]               caBufferForOneRow;
        int                  intNumberOfRows;
        int                  intNumberOfColumns;
        int                  intReadCount;
        StringBuffer         stringbufferScreenToLog = new StringBuffer();
        String               stringScreenToLog;
        String               stringMacroLineInError;
        int                  intECLErrMsgNumber;
        String               stringECLErrText;
        HPubErrorsToLog      oErrorsToLog = new HPubErrorsToLog();

        // Log and Trace the information we know about the status of the bean and macro
        // Add messages to the ErrorsToLog object and then log and trace them with
        // the ErrorsToLog.log() method

        ResourceBundle res = ResourceBundle.getBundle("com.ibm.HostPublisher.IntegrationObject.HPub_Resources",
                                                      Locale.getDefault());
        if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","STATE_PLAY_ERROR fired"); }


        // get the name of the last screen this macro was on
        oMacroScreen = oMacroStateEvent.getMacroScreen();
        if (oMacroScreen != null)
        { hPubScreenState = oMacroScreen.getName();
        }

        // log/trace the bean name
        if (res != null)
        { String stringTemp = res.getString("Bean_Name");
          oErrorsToLog.concatAndAddStrings(stringTemp, stringBeanName);
        }

        // log/trace the http session information (if we can)
        try {                                                                  
           oErrorsToLog.addHttpServletRequestInformation(oHttpServletRequest);
        }                                                                      
        catch (Exception e)                                                    
        {                                                                      
        }       

        // log/trace the name of the host machine
        if (sessionHost.getHost() != null)
        { String stringTemp = new String(sessionHost.getHost());
          oErrorsToLog.stringToLog(stringTemp);
        }

        if (sessionHost.getSessionType().equals(ECLSession.SESSION_TYPE_3270_STR))
        { // log/trace LU Name (only valid for 3270 sessions)
          String stringTemp = null;
          stringTemp = sessionHost.getLUName();
          if (stringTemp != null)
          {  if (stringTemp.length() > 0)
             {
               oErrorsToLog.stringToLog(stringTemp);
             }
          }
        }

        // log/trace the macro name
        if (macroBean != null)
        { String stringTemp1 = new String(res.getString("Macro_Name"));
          oErrorsToLog.concatAndAddStrings(stringTemp1, stringMacroName);
        }

        // log/trace the error message stored in HOD.
        oECLErr = oMacroStateEvent.getECLErr();
        if (oECLErr != null)
        {
          oErrorsToLog.stringToLog(oECLErr.GetMsgText());
        }

        // log/trace the name of the last screen this macro was on
        if (hPubScreenState != null)
        { if (res != null)
          { String stringTemp = new String(res.getString("Last_Screen_Name"));
            oErrorsToLog.concatAndAddStrings(stringTemp, hPubScreenState);
          }
        }
        else
        { if (res != null)
          { String stringTemp1 = new String(res.getString("Last_Screen_Name"));
            String stringTemp2 = new String(res.getString("Null_Returned"));
            oErrorsToLog.concatAndAddStrings(stringTemp1, stringTemp2);
          }
        }

        // log/trace the contents of the current(last) screen that we are on.
        oECLSession = sessionHost.getECLSession();
        if (oECLSession != null)
        { oECLPS = oECLSession.GetPS();
          if (oECLPS != null)
          { intNumberOfRows    = oECLPS.GetSizeRows();
            intNumberOfColumns = oECLPS.GetSizeCols();
            caBufferForOneRow  = new char[intNumberOfColumns + 1];

            stringbufferScreenToLog.append(res.getString("Screen_Dump"));
            stringbufferScreenToLog.append("\n");
            // Append horizontal rule
            for (int intI = 1; intI <= intNumberOfColumns + 2; intI++)
            { stringbufferScreenToLog.append("-");
            }
            stringbufferScreenToLog.append("\n");

            // Append one row at a time, adding demarcating '|' characters at the
            // beginning and the end of each row.
            for (int intCurrentRow = 1; intCurrentRow <= intNumberOfRows; intCurrentRow++)
            { try
              { intReadCount = oECLPS.GetString(caBufferForOneRow, intNumberOfColumns + 1,
                                                intCurrentRow, 1, intNumberOfColumns);

                // Replace null character with demarcation character.
                caBufferForOneRow[intReadCount] = '|';
                stringbufferScreenToLog.append("|" + new String(caBufferForOneRow) + "\n");
              }
              catch (ECLErr oException)
              { // If we get an exception while trying to print the error
                // information, then log the fact we got an exception, but don't
                // worry about the details of the exception
                String stringTemp = res.getString("ECLPS_Error_1");
                oErrorsToLog.stringToLog(stringTemp);
              }
            }

            // Append horizontal rule
            for (int intI = 1; intI <= intNumberOfColumns + 2; intI++)
            { stringbufferScreenToLog.append("-");
            }
            stringbufferScreenToLog.append("\n");

            ECLOIA oECLOIA = oECLSession.GetOIA();
            stringbufferScreenToLog.append(res.getString("OIA_Input_Inhibited_Status") + " 0x"
              + Integer.toHexString(oECLOIA.InputInhibited()) + " "
              + convertOIAInputInhibitedStatus(oECLOIA.InputInhibited()) + "\n");

            stringbufferScreenToLog.append(res.getString("OIA_Status_Flags") + " 0x"
              + Integer.toHexString(oECLOIA.GetStatusFlags()) + "\n");

            stringbufferScreenToLog.append( res.getString("Comm_Status") + " 0x"
              + Integer.toHexString(sessionHost.getCommStatus()) + " "
              + convertCommStatus(sessionHost.getCommStatus()) + "\n");

            stringScreenToLog = new String(stringbufferScreenToLog);
            oErrorsToLog.stringToLog(stringScreenToLog);
          }
        }

        oErrorsToLog.log(Ras.TYPE_ERROR, stringBeanName, className );

        stringHODMacroError = new String("HOD_Macro_Error_1");

        // If we will be passing the connection to the ZIETrans entry servlet
        // for processing, then insure that we do not return the connection
        // to the pool and we save it in the HTTP session object.
        if ((getHPubSaveConnOnError() == true) &&                
            (isTransformConn() == true))                         
        {                                                        
           hPubEndType           = BEAN_END_TO_CONNECTION;       
           if (oHttpServletRequest != null)                      
              oHttpServletRequest.setAttribute(CommonConstants.HATS_EVENT, CommonConstants._ERROREVENT); 
        }                                                        
        else                                                      
           hPubEndType           = BEAN_END_TO_POOL;


        switch (intMacroState)
        { case MACRO_STATE_INSTANTIATED:
          case MACRO_STATE_PLAYING:
          case MACRO_STATE_PARSE_ERROR:
            synchronized(this)
            { intMacroState = MACRO_STATE_PLAY_FINISHED;
              if (HPubTracingOn)
              { Ras.trace( className,"macroStateEvent","perform notify at STATE_PLAY_ERROR");
              }
              notify();
            }
          break;

          default:
          break;
        }

      break;

      default:
        if (HPubTracingOn) { Ras.trace( className,"macroStateEvent","Unknown macro state fired"); }
      break;
    }

    if (HPubTracingOn) { Ras.traceExit( className,"macroStateEvent"); }
  }

  // ****************************************************************************
  public String convertCommStatus(int intCommStatus)
  {
    // convert communication status value to a string.
    if (intCommStatus == Session.CONNECTION_ACTIVE)
      return "CONNECTION_ACTIVE";
    else if (intCommStatus == Session.CONNECTION_INACTIVE)
      return "CONNECTION_INACTIVE";
    else if (intCommStatus == Session.CONNECTION_INIT)
      return "CONNECTION_INIT";
    else if (intCommStatus == Session.CONNECTION_PND_INACTIVE)
      return "CONNECTION_PND_INACTIVE";
    else if (intCommStatus == Session.CONNECTION_PND_ACTIVE)
      return "CONNECTION_PND_ACTIVE";
    else if (intCommStatus == Session.CONNECTION_READY)
      return "CONNECTION_READY";
    else if (intCommStatus == Session.CONNECTION_DEVICE_NAME_READY)
      return "CONNECTION_DEVICE_NAME_READY";
    else
      return Integer.toString(intCommStatus);
  }

  // ****************************************************************************
  public String convertOIAInputInhibitedStatus(int intOIAInputInhibitedStatus)
  { // convert OIA Input Inhibited Status to a string
    if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_NOTINHIBITED)
      return "INHIBIT_NOTINHIBITED";
    else if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_SYSTEMWAIT)
      return "INHIBIT_SYSTEMWAIT";
    else if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_COMMCHECK)
      return "INHIBIT_COMMCHECK";
    else if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_PROGCHECK)
      return "INHIBIT_PROGCHECK";
    else if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_MACHCHECK)
      return "INHIBIT_MACHCHECK";
    else if (intOIAInputInhibitedStatus == com.ibm.eNetwork.ECL.ECLOIA.INHIBIT_OTHERINHIBIT)
      return "INHIBIT_OTHERINHIBIT";
    else
      return Integer.toString(intOIAInputInhibitedStatus);
  } 

// begin add for HPubExtractFieldAttributes

public String extendedxml = "";   
public String getExtendedxml() {return extendedxml;}
// ADDED FOR XML TABLE
/**
 * Callback for HOD Custom screen recognition.  
 * This tag must be added to the screen in the macro for which the attributes are to be retrieved:
 *   <customreco id="HPubExtractFieldAttributes|" optional="false" invertmatch="false" />
 * It must be the last tag in the screen description so that the screen matches the other
 * descriptors.
 * When the macro is played, this code will be called when the screen matches the other
 * descriptors.  The attributes are gathered and saved as XML data in extendedxml.  The data is retrieved by
 * calling getExtendedxml() 
 *
 * Always return true for customreco ids you have added ( including this sample ).
 * Returning false would mean that the screen is not recognized.
 */
public boolean DoReco(ECLCustomRecoEvent e) //Custom Version
 {  
    String descString = e.getID();
    ECLPS ps = e.GetPS();
    ECLScreenDesc screenDesc = e.GetScreenDesc();
    
    int pos = -1;
    String compareRegionOrValue;
    String separator = "|";
    pos = descString.indexOf(separator);
    compareRegionOrValue = descString.substring(0,pos);

    // Parse descString.  Only handle "HPubExtractFieldAttributes" here.
    // Super class with handle other CustomRecoEvents used in advanced
    // screen recognition and fixed iteration looping.
    if (compareRegionOrValue.equalsIgnoreCase("HPubExtractFieldAttributes"))
    {
       // call method to build XML file
       extractFieldData( ps, screenDesc.GetName() );
       
	  
       // Always return true.  Returning false would mean the screen is not
       // recognized.
       return true;
    }  
        
    // not the extended attribute tag - return true
    else
    {
       return super.DoReco(e);
    }  
 }  // end DoReco()
 
 // ADDED FOR XML TABLE
   /** 
   *
   *  Method to extract field data and build XML table which can be retrieved by JSP.
   *  This method may be modified to extract only specific data for specific fields.
   *    @param ECLPS - Presentation Space - includes characters and attributes sent from host
   *    @param screenName - not known to ECL Session  ( may use "" )
   **/
  void extractFieldData( ECLPS ps, String screenName )
  {
    Object colortablebackground[] = {"Black","Blue","Green","Cyan","Red","Magenta","Yellow","White"};

    Object colortableforeground[] = {"Black","Blue","Green","Cyan","Red","Magenta","WhiteHI","White",
					  "Gray","LightBlue","LightGreen","LightCyan","LightRed","LightMagenta","Yellow"};
    int index;
    String astr = ""; //Attribute String

       ECLFieldList fields = null;      // collection of information about fields
       try 
       {
         // get information for all planes
 	     int planes = com.ibm.eNetwork.ECL.ECLPS.TEXT_PLANE |
	                     com.ibm.eNetwork.ECL.ECLPS.FIELD_PLANE |
	                     com.ibm.eNetwork.ECL.ECLPS.COLOR_PLANE |
	                     com.ibm.eNetwork.ECL.ECLPS.EXFIELD_PLANE;
         fields = ps.GetFieldList(planes);	                     
	   } 
	   catch (Exception e1)
	   {
 	     System.out.println("Exception in DoReco calling ps.GetFieldList()");
 	     fields = null;
       }
       
	   // if fields is null, nothing to examine - bail out. xml file will be empty  
	   if (fields == null)
	   {
           System.out.println("DoReco - fields is null - cannot build xml");	       
	       return;
	   }    
	   astr += "<Screen>\n";
	   astr += "<ScreenID>" + screenName + "</ScreenID>\n";
	   for(int i=0; i < fields.size(); i++)
	   {
	      ECLField field = null; 
		  field = (ECLField) fields.elementAt(i);
		  if (field != null) 
		  {
		     astr += "<Field>\n";
		     astr += "<FieldNumber>" + i + "</FieldNumber>\n";
		     astr += "<StartRow>" + field.GetStartRow() + "</StartRow>\n";
		     astr += "<StartColumn>" + field.GetStartCol() + "</StartColumn>\n";
		     astr += "<EndRow>" + field.GetEndRow() + "</EndRow>\n";
		     astr += "<EndColumn>" + field.GetEndCol() + "</EndColumn>\n";
		     astr += "<StartLinear>" + field.GetStart() + "</StartLinear>\n";
		     astr += "<EndLinear>" + field.GetEnd() + "</EndLinear>\n";
		     astr += "<Length>" + field.GetLength() + "</Length>\n";
		     if (field.IsProtected()) {
    			astr += "<Protected>true</Protected>\n";
		     } else {
		 	 astr += "<Protected>false</Protected>\n";
		     }
		     char buf1[] = new char[1000];
		     int length;
		     try {
		     length = field.GetString(buf1,1000);   
		     } catch (Exception e3)
		     {
		        System.out.println("DoReco: Error calling ps.field.GetString()");
		        length = 0;
		     }
		     String textstr = new String(buf1);
		     astr += "<Text>" + textstr + "</Text>\n";
		     try {
		     length = field.GetScreen(buf1,1000,com.ibm.eNetwork.ECL.ECLPS.COLOR_PLANE);
		     } catch (Exception e4)
		     {
		        System.out.println("DoReco: Error calling ps.field.GetScreen()");
		        length = 0;		        
		     }
		     String foregroundString = "";
		     String backgroundString = "";
		     if (length > 0) length = 1; //Just get first color		   
		     for (int j=0; j<length; j++)
		     {
			        
			    int compareintmask = 15;
			    int compareint;
			    compareint = buf1[j];

			    index = compareint & compareintmask;
			    foregroundString += colortableforeground[index]; // + ",";               

 			    index = (compareint >> 4);
			    index = index & 7;
		        backgroundString += colortablebackground[index]; // + ",";
		     }
		     astr += "<ForegroundColor>" + foregroundString + "</ForegroundColor>\n";
		     astr += "<BackgroundColor>" + backgroundString + "</BackgroundColor>\n";
		     if (field.IsHighIntensity()) {
			 astr += "<HighIntensity>true</HighIntensity>\n";
		     } else {
			 astr += "<HighIntensity>false</HighIntensity>\n";
		     }
		     if (field.IsDisplay()) {
			 astr += "<Displayable>true</Displayable>\n";
		     } else {
			 astr += "<Displayable>false</Displayable>\n";
		     }
		     if (field.IsModified()) {
			 astr += "<FieldModified>true</FieldModified>";
		     } else {
			 astr += "<FieldModified>false</FieldModified>";
		     }
		     astr += "</Field>\n";
		  }
	   }
	   astr += "</Screen>\n";
	   extendedxml = astr;
	   
  }  

// end add for HPubExtractFieldAttributes

} // end class