package com.sap.mw.jco.jra.examples;

import java.rmi.*;
import javax.ejb.*;
import javax.resource.cci.*;
import javax.naming.*;
import java.util.*;

/**
 * Before you start using this bean, check, if you system contains RFMs used here.
 * This is an example of a container managed (demarcation) stateless session bean
 * with container managed authentication.
 * (check, if you set the tag <res-auth>Container</res-auth> correct).
 *
 * The JCA recommends to use both container managed demarcation and
 * container managed authentication. Becides that it is a better way
 * to relay on highly optimized container managing your trancations rather then
 * to start transactions manualy (by localTransaction.begin()/commit()) and
 * to relay on user management on App. Server (container managed authentication)
 * rather then maintaining you own user management.
 * So use any other ways only if your business logic really requires it.
 */
public class ExampleBean implements SessionBean
{
    private SessionContext sessionContext;

    public void ejbCreate()
    {
    }
    public void ejbRemove() throws RemoteException
    {
    }
    public void ejbActivate() throws RemoteException
    {
    }
    public void ejbPassivate() throws RemoteException
    {
    }
    public void setSessionContext(SessionContext sessionContext) throws RemoteException
    {
      this.sessionContext = sessionContext;
    }

    /**
     * This method creates a connection to R/3
     */
    public String testSimpleConnection() throws RemoteException
    {
        String result="";
        Connection connection = null;
        try
        {
            System.out.println("\n*************************************************\n");
            System.out.println("***********  Date: "+new Date()+"   *************");
            System.out.println("\n*************************************************\n");
            System.out.println("call method testSimpleConnection");

            // create new InitialContext
            InitialContext initialcontext = new InitialContext();

            // lookup for ConnectionFactory in JNDI
            ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("eis/SAPJRAFactory");
            //ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("java:comp/env/eis/SAPJRAFactory");
            // get connection
            connection = connectionfactory.getConnection();
            result="connection created successful";
            System.out.println("connection created");
            System.out.println("Product Version ist: "+connection.getMetaData().getEISProductVersion());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null)
            {
                try
                {
                    connection.close();
                }
                catch(Exception exception1) { }
            }
        }
        return result;
    }

     /**
      * This method returns a list of available banks.
      * It gets a table from R/3 using ResultSet interface.
      * Since you do not use writing access on the data base
      * you do not need starting any trancation here.
      */
     public Object[][] callBapiBankGetList(String bankCountry, int maxRows) throws RemoteException
    {
      Connection connection = null;
      try
      {
            System.out.println("\n*************************************************\n");
            System.out.println("call method callBapiBankGetList");

            InitialContext initialcontext = new InitialContext();
            ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("eis/SAPJRAFactory");
            //ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("java:comp/env/eis/SAPJRAFactory");

            // create connection
            connection = connectionfactory.getConnection();

            // get InteractionObject
            Interaction interaction = connection.createInteraction();

            // create new structure for given RFC-Function
            MappedRecord input = connectionfactory.getRecordFactory().createMappedRecord("BAPI_BANK_GETLIST");
            System.out.println("MappedRecord(\"BAPI_BANK_GETLIST\") was created");

            // set input-parameters
            input.put("MAX_ROWS", String.valueOf(maxRows));
            input.put("BANK_CTRY", String.valueOf(bankCountry));

            // get output-parameter
            MappedRecord output = (MappedRecord) interaction.execute(null, input);

            // extract results
            javax.resource.cci.ResultSet bankList = (ResultSet) output.get("BANK_LIST");
            Object result[][] = Util.transformResultSetToString(bankList);

            // release interaction
            interaction.close();

            return result;
        }
        catch (Exception e)
        {
          e.printStackTrace();  // helpful for debugging
          throw new RemoteException(e.getMessage(), e);
        }
        finally
        {
            if (connection != null)
            {
                try
                {
                    connection.close();
                }
                catch(Exception exception1) { }
            }
        }
    }

    /**
     * This method creates new record in the test bank.
     * This method passes a structure to/from R/3 using interface MappedRecord.
     * It runs under the same transaction like the method which called this method.
     */
    private String[] callBapiBankCreate(RecordFactory recordfactory, Connection connection, String bankCountry, String bankKey, String bankName, String bankCity) throws Exception
    {
        try
        {
            // get InteractionObject and create input-record
            Interaction interaction = connection.createInteraction();
            MappedRecord input = recordfactory.createMappedRecord("BAPI_BANK_CREATE");
            System.out.println("MappedRecord(\"BAPI_BANK_CREATE\") was created");

            // set input-parameters
            MappedRecord bankAddressStructure = (MappedRecord)input.get("BANK_ADDRESS");
            bankAddressStructure.put("BANK_NAME", bankName);
            bankAddressStructure.put("CITY", bankCity);

            input.put("BANK_CTRY", bankCountry);
            input.put("BANK_KEY", bankKey);

            // call function and get output
            MappedRecord output = (MappedRecord) interaction.execute(null, input);

            // extract results
            String resultBankCountry = (String) output.get("BANKCOUNTRY");
            String resultBankKey = (String) output.get("BANKKEY");
            MappedRecord returnStructure = (MappedRecord) output.get("RETURN");
            String resultMessage = (String) returnStructure.get("MESSAGE");
            if (resultMessage != null && resultMessage.trim().length() != 0)
              throw new Exception("Error-Message from SAP-system: " + resultMessage);

            // release interaction
            interaction.close();

            System.out.println("everything in callBapiBankCreate was executed");
            return new String[] { resultBankCountry, resultBankKey };
        }
        catch (Exception e)
        {
            throw new RemoteException("Error in method callBapiBankCreate()", e);
        }
    }

    /**
     * This method creats a new record in the table.
     * It uses Container-Managed demarcation.
     * Transaction attribute of this method should be set on Required, so that
     * Transaction Manager will start a transaction and call commit/begin.
     * The Transaction Manager also passes the transaction to
     * the private method, called from this method.
     */
    public String callBapiBankCreateUsingContainerTransaction(String bankCountry, String bankKey, String bankName, String bankCity) throws RemoteException
    {
        String result = "";
        Connection connection = null;
        try
        {
            System.out.println("\n*************************************************\n");
            System.out.println("call method callBapiBankCreateUsingContainerTransaction");

            InitialContext initialcontext = new InitialContext();

            // get ConnectionFactory
            ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("eis/SAPJRAFactory");
            //ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("java:comp/env/eis/SAPJRAFactory");

            // get Connection
            connection = connectionfactory.getConnection();

            RecordFactory recordfactory = connectionfactory.getRecordFactory();

            // create bank
            String createResult[] = callBapiBankCreate(recordfactory, connection, bankCountry, bankKey, bankName, bankCity);
            result += "Created Bank (" + createResult[0] + ", " + createResult[1] + ").";

            return result;
        }

        catch (Exception e)
        {
            e.printStackTrace();  // helpful for debugging
            throw new RemoteException(e.getMessage(), e);
        }

        finally
        {
            if (connection != null)
            {
                try
                {
                    connection.close();
                }
                catch(Exception exception1) { }
            }
        }
    }

    /**
     *  Method calls simple RFC. This RFC (STFC_CONNECTION) is usually used for testing RFC-calls.
     */
    public String callFunctionStfcConnection(String echoMessage) throws RemoteException
    {
        String result = "";
        Connection connection = null;

        try
        {
            System.out.println("\n*************************************************\n");
            System.out.println("call method callFunctionStfcConnection");

            InitialContext initialcontext = new InitialContext();

            ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("eis/SAPJRAFactory");
            //ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("java:comp/env/eis/SAPJRAFactory");

            // connect with default-info and display information
            //ConnectionSpec connectionSpec = new JRA.ConnectionSpecImpl("001", "EN");
            connection = connectionfactory.getConnection();

            // get InteractionObject
            Interaction interaction = connection.createInteraction();
            MappedRecord input = connectionfactory.getRecordFactory().createMappedRecord("STFC_CONNECTION");
            System.out.println("MappedRecord(\"STFC_CONNECTION\") was created");

            // set input-parameters
            input.put("REQUTEXT", echoMessage);

            // call function and create output
            MappedRecord output = (MappedRecord) interaction.execute(null, input);
            String resultBankCountry = (String) output.get("ECHOTEXT");

            // extract results
            result += resultBankCountry;

            // release interaction
            interaction.close();

            return result;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            throw new RemoteException(e.getMessage(), e);
        }
        finally
        {
            if (connection != null)
            {
                try
                {
                    connection.close();
                }
                catch(Exception exception1) { }
            }
        }
    }

    /**
     * This method returns details to the bank by County and Key. It returns Structure.
     * Since you do not use writing access on the data base
     * you do not need starting any trancation here.
     */
    public String callBapiBankGetDetail(String bankCountry, String bankKey) throws RemoteException
    {
        String result = "";
        Connection connection = null;

        try
        {
            System.out.println("\n*************************************************\n");
            System.out.println("call method callBapiBankGetDetail");

            InitialContext initialcontext = new InitialContext();

            ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("eis/SAPJRAFactory");
            //ConnectionFactory connectionfactory = (ConnectionFactory) initialcontext.lookup("java:comp/env/eis/SAPJRAFactory");

            connection = connectionfactory.getConnection();

            RecordFactory recordfactory = connectionfactory.getRecordFactory();

            // get InteractionObject
            Interaction interaction = connection.createInteraction();

            // create input-record: the whole structure beloning to BAPI_BANK_CHANGE will be loaded into repository
            MappedRecord input = recordfactory.createMappedRecord("BAPI_BANK_GETDETAIL");
            System.out.println("MappedRecord(\"BAPI_BANK_GETDETAIL\") was created");

            // set input-parameters
            input.put("BANKCOUNTRY", bankCountry);
            input.put("BANKKEY", bankKey);

            System.out.println("before callin execute in the method callBapiBankGetDetail");
            // call function
            MappedRecord output = (MappedRecord) interaction.execute(null, input);

            // extract results
            String resultBankCountry = (String) output.get("BANKCOUNTRY");
            String resultBankKey = (String) output.get("BANKKEY");
            MappedRecord returnStructure = (MappedRecord) output.get("RETURN");
            String resultMessage = (String) returnStructure.get("MESSAGE");
            String resultNumber = (String) returnStructure.get("NUMBER");
            MappedRecord bankAddressStructure = (MappedRecord) output.get("BANK_ADDRESS");
            String bankName = (String) bankAddressStructure.get("BANK_NAME");
            String bankCity = (String) bankAddressStructure.get("CITY");

            if (resultNumber != null && resultNumber.trim().equals("211"))
              result += "Bank (" + bankCountry + ", " + bankKey + ") does NOT exist.";
            else if (resultMessage != null && resultMessage.trim().length() != 0)  // other errors
              throw new Exception("Error-Message from SAP-system: " + resultMessage);
            else
              result += "Bank (" + bankCountry + ", " + bankKey + ", " + bankName + ", " + bankCity + ") exists.";

            // release interaction
            interaction.close();

            return result;
        }
        catch (Exception e)
        {
            e.printStackTrace();  // helpful for debugging
            throw new RemoteException(e.getMessage(), e);
        }
        finally
        {
            if (connection != null)
            {
                try
                {
                    connection.close();
                }
                catch(Exception exception1) { }
            }
        }
    }
}