/*
* GSAStartTransactionActionImpl
*
* 06/27/2003
*
* Copyright:
* Licensed Materials - Property of IBM
* "Restricted Materials of IBM"
* 5724-AEF
* (C) Copyright IBM Corp. 2003.
*
* %W% %E%
*/
package com.ibm.retail.AEF.action;
import com.ibm.retail.AEF.automation.*;
import com.ibm.retail.AEF.util.*;
import com.ibm.retail.si.util.*;
import com.ibm.retail.si.Copyright;
import com.ibm.retail.AEF.thread.*;
import com.ibm.retail.AEF.data.*;
import com.ibm.retail.AEF.session.*;
import com.ibm.retail.AEF.factory.*;
import java.util.*;
import java.rmi.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* GSAStartTransactionActionImpl is a class which the POSAutomationProvider uses to start a
* sales transaction on the POS application.
*
*/
public class GSAStartTransactionActionImpl extends GSAActionImpl
{
static String copyright()
{ return com.ibm.retail.si.Copyright.IBM_COPYRIGHT_SHORT;}
/**
* Constructor
*
* @param request The ActionRequest.
* @exception AEFException
* AEFException error codes:
*
AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACATION_TYPE
*/
public GSAStartTransactionActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.GSAStartTransactionActionImpl().");
log.trace(tempAEFMessage);
}
try
{
transactionID = (TransactionIdentifier)(request.getArguments());
validateTransactionType(transactionID);
}
catch (AEFException e)
{
tempAEFMessage.setMessage("There was an AEF exception thrown in the constructor of GSAStartTransactionActionImpl.");
log.error(tempAEFMessage, e);
throw e;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.GSAStartTransactionActionImpl().");
log.trace(tempAEFMessage);
}
}
/**
* Perform the action represented by the ActionRequest and return an ActionResult.
*
*
* @param request The ActionRequest which contains the classname and arguments.
* @return Object The SalesTransaction instance.
* @exception AEFException
* AEFException error codes:
*
AEFConst.APPLICATION_NOT_IN_PROPER_STATE, AEFConst.NONE
*/
public Object performAction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.performAction().");
log.trace(tempAEFMessage);
}
super.performAction(); // Call super to perform any common processing and clear any errors before we start.
Object retVal = null;
try
{
//Check to make sure that we are in the TRANSACTION_SELECT state. If not, throw exception.
if (getCurrentState().equals(State.getState("TRANSACTION_SELECT")))
{
retVal = sendStartTransactionSequence();
// If user data was specified, send the data entry sequence.
if (transactionID.getData() != null && transactionID.getData().length() > 0)
{
sendDataEntrySequence();
}
}
else if (getCurrentState().equals(State.getState("ITEMENTRY")))
{
retVal = createTransaction();
}
else
{
// Not in valid state for start transaction.
throw new AEFException(AEFConst.APPLICATION_NOT_IN_PROPER_STATE,
0,
"GSAStartTransactionActionImpl.performAction(): POS application not in proper state to perform start transaction.\n Expected state " + State.getState("TRANSACTION_SELECT") + ", but application is in state " + getCurrentState() + ".");
}
}
catch (AEFException e)
{
tempAEFMessage.setMessage("There was an AEF exception thrown in performAction of GSAStartTransactionActionImpl.");
log.error(tempAEFMessage, e);
throw e;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.performAction().");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Sends the user data in a data entry sequence.
*
*
* @exception AEFException
*/
public void sendDataEntrySequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.sendDataEntrySequence().");
log.trace(tempAEFMessage);
}
int retVal = -1;
try
{
args.clear();
args.put("%0", transactionID.getData());
args.put("SEQUENCE_ID", "transDataEntry");
keySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] goodConditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_STATE, State.getState("ITEMENTRY")),
};
lock = new ConditionLock();
retVal = lock.performActionAndWait("wait-for-expecting-item-entry-state",
keySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send User Data Sequence Error");
retVal = errorHandler.handleError(lock,
keySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
}
catch (AEFException e)
{
tempAEFMessage.setMessage("There was an AEF exception thrown in sendDataEntrySequence of GSAStartTransactionActionImpl. The transaction will be voided. Transaction = " + transactionID);
log.error(tempAEFMessage, e);
// Void the transaction as this operation is all or nothing an we did not send the data.
try
{
automationProvider.voidCurrentTransaction();
}
catch (RemoteException re)
{
// Not expected to get here since we are calling locally.
tempAEFMessage.setMessage("There was a remote exception thrown in sendDataEntrySequence of GSAStartTransactionActionImpl.");
log.error(tempAEFMessage, re);
}
// Throw the exception.
throw e;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.sendDataEntrySequence().");
log.trace(tempAEFMessage);
}
}
/**
* Sends the key sequence to start a transaction.
*
* @return Transaction A transaction object or null.
* @exception AEFException
*/
public Transaction sendStartTransactionSequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.sendStartTransactionSequence().");
log.trace(tempAEFMessage);
}
int tmpRetVal = -1;
Transaction retVal = null;
args.clear();
args.put("SEQUENCE_ID", "startTransaction");
args.put("%0", Integer.toString(gsaTranType));
keySequenceAction = (AEFAction)(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
lock = new ConditionLock();
detector = ((DetectorAccess)(SessionContext.getSession())).getTransactionDetector();
// Save any current transaction instance number so we are sure to only get a transaction
// created after this key sequence is sent.
instanceNumber = detector.getInstanceNumber();
tmpRetVal = lock.performActionAndWait("wait-for-expecting-item-entry-state",
keySequenceAction,
GSANormalConditionsImpl.getInstance().getShortConditions(),
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (tmpRetVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Start Transaction Sequence");
tmpRetVal = errorHandler.handleError(lock,
keySequenceAction,
GSANormalConditionsImpl.getInstance().getShortConditions(),
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
tmpRetVal);
}
if (tmpRetVal >= 0)
{
// Successfully sent the sales transaction started sequence.
// We will create a sales transaction object because technically a
// transaction has not yet been started.
retVal = createTransaction();
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.sendStartTransactionSequence().");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Validates the transaction type.
*
* @param TransactionIdentifier The transaction identifier for the transaction to start.
* Valid values are:
*
* - AEFConst.NO_SALE
* - AEFConst.REGULAR_CASH
* - AEFConst.CASH_SPECIAL
* - AEFConst.CASH_DOC
* - AEFConst.COD
* - AEFConst.LAYAWAY
* - AEFConst.CHARGE_PLAN_A
* - AEFConst.CHARGE_PLAN_B
* - AEFConst.CHARGE_PLAN_C
* - AEFConst.CHARGE_PLAN_D
*
* @exception AEFException
* AEFException error codes:
*
AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACTION_TYPE
*/
private void validateTransactionType (TransactionIdentifier transactionID) throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.validateTransactionType().");
log.trace(tempAEFMessage);
}
boolean validTransactionType = false;
// Convert the AEF transaction type to the GSA transaction type.
String tranType = transactionID.getTransactionType();
if (tranType == null)
{
// Default to AEFConst.REGULAR_CASH
tranType = AEFConst.REGULAR_CASH;
}
if (tranType.equals(AEFConst.NO_SALE))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.NO_SALE;
}
else if (tranType.equals(AEFConst.REGULAR_CASH))
{
validTransactionType = true;
gsaTranType = GSAStartTransactionActionImpl.REGULAR_CASH;
}
else if (tranType.equals(AEFConst.CASH_SPECIAL))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CASH_SPECIAL;
}
else if (tranType.equals(AEFConst.CASH_DOC))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CASH_DOC;
}
else if (tranType.equals(AEFConst.COD))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.COD;
}
else if (tranType.equals(AEFConst.LAYAWAY))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.LAYAWAY;
}
else if (tranType.equals(AEFConst.CHARGE_PLAN_A))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CHARGE_PLAN_A;
}
else if (tranType.equals(AEFConst.CHARGE_PLAN_B))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CHARGE_PLAN_B;
}
else if (tranType.equals(AEFConst.CHARGE_PLAN_C))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CHARGE_PLAN_C;
}
else if (tranType.equals(AEFConst.CHARGE_PLAN_D))
{
validTransactionType = false;
gsaTranType = GSAStartTransactionActionImpl.CHARGE_PLAN_D;
}
else
{
validTransactionType = false;
}
// Throw and exception if the type is not valid.
if (validTransactionType == false)
{
AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACTION_TYPE, "GSAStartTransactionActionImpl(): Unsupported transaction type = " + transactionID.getTransactionType() + ". Unable to start transaction.");
tempAEFMessage.setMessage("An AEF exception was thrown in GSAStartTransactionActionImpl.validateTransactionType().");
log.error(tempAEFMessage, tempException);
throw tempException;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.validateTransactionType().");
log.trace(tempAEFMessage);
}
}
/**
* This method will create a sales transaction object because technically a
* transaction has not yet been started by GSA.
*
* @return Transaction A transaction object or null.
* @exception AEFException
*/
public Transaction createTransaction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter GSAStartTransactionActionImpl.createTransaction().");
log.trace(tempAEFMessage);
}
Transaction retVal = null;
SalesTransaction trans = null;
ObjectDetector detector = ((DetectorAccess)(SessionContext.getSession())).getTransactionDetector();
Object obj = detector.getObject();
if (obj != null && obj instanceof Transaction)
{
retVal = (Transaction)(obj);
}
else
{
try
{
retVal = (Transaction)(FactoryImpl.createObject("SalesTransaction"));
AEFSession session = SessionContext.getSession();
retVal.setSession(session);
retVal.setIsActive(true);
session.getPOSAutomationProvider().setTransaction(retVal);
detector.setObject(retVal);
}
catch (RemoteException re)
{
// We should never get here because the call is local.
tempAEFMessage.setMessage("There was a remote exception thrown in createTransaction of GSAStartTransactionActionImpl.");
log.error(tempAEFMessage, re);
}
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit GSAStartTransactionActionImpl.createTransaction().");
log.trace(tempAEFMessage);
}
return(retVal);
}
/* Instance and Class Variables */
protected TransactionIdentifier transactionID = null;
protected AEFAction keySequenceAction = null;
protected ConditionLock lock = null;
protected ObjectDetector detector = null;
protected int instanceNumber = 0;
protected int gsaTranType;
public static final int NO_SALE = 0;
public static final int REGULAR_CASH = 1;
public static final int CASH_SPECIAL = 2;
public static final int CASH_DOC = 3;
public static final int COD = 4;
public static final int LAYAWAY = 5;
public static final int CHARGE_PLAN_A = 6;
public static final int CHARGE_PLAN_B = 7;
public static final int CHARGE_PLAN_C = 8;
public static final int CHARGE_PLAN_D = 9;
private static Log log = LogFactory.getLog(GSAStartTransactionActionImpl.class);
}