/*
* ACEStartTransactionActionImpl
*
* 07/08/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 java.rmi.RemoteException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.ibm.retail.AEF.automation.ActionRequest;
import com.ibm.retail.AEF.automation.Condition;
import com.ibm.retail.AEF.automation.DetectorAccess;
import com.ibm.retail.AEF.automation.ObjectDetector;
import com.ibm.retail.AEF.automation.PropertyEqualsCondition;
import com.ibm.retail.AEF.automation.SalesTransaction;
import com.ibm.retail.AEF.automation.State;
import com.ibm.retail.AEF.automation.Substate;
import com.ibm.retail.AEF.automation.TransactionIdentifier;
import com.ibm.retail.AEF.data.POSDeviceProperties;
import com.ibm.retail.AEF.factory.FactoryImpl;
import com.ibm.retail.AEF.session.AEFSession;
import com.ibm.retail.AEF.session.SessionContext;
import com.ibm.retail.AEF.thread.ConditionLock;
import com.ibm.retail.AEF.util.AEFErrorHandler;
import com.ibm.retail.AEF.util.AEFPerfTrace;
import com.ibm.retail.AEF.util.BadConditionsImpl;
import com.ibm.retail.si.util.AEFConst;
import com.ibm.retail.si.util.AEFException;
/**
* ACEStartTransactionActionImpl is a class which the POSAutomationProvider uses to start a
* sales transaction on the ACE application.
*
*/
public class ACEStartTransactionActionImpl extends ACEActionImpl
{
static String copyright()
{ return com.ibm.retail.si.Copyright.IBM_COPYRIGHT_SHORT; }
private static AEFPerfTrace perfTrace = AEFPerfTrace.getInstance();
/**
* Constructor
*
* @param request The ActionRequest.
* @exception AEFException
* AEFException error codes:
*
AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACTION_TYPE
*
*/
public ACEStartTransactionActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter constructor of ACEStartTransactionActionImpl.");
log.trace(tempAEFMessage);
}
theTransactionID = (TransactionIdentifier)(request.getArguments());
String transType = theTransactionID.getTransactionType();
if (transType == null)
{
// Default to AEFConst.REGULAR_SALE
transType = AEFConst.REGULAR_SALE;
}
if (!transType.equals(AEFConst.REGULAR_SALE))
{
String tempString = "ACELogonActionImpl(): Unsupported transaction type = " + theTransactionID.getTransactionType() + ". Unable to start transaction.";
AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT,
AEFConst.INVALID_TRANSACTION_TYPE,
tempString);
tempAEFMessage.setMessage(tempString);
log.error(tempAEFMessage, tempException);
throw tempException;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit constructor of ACEStartTransactionActionImpl.");
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
*/
public Object performAction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEStartTransactionActionImpl.performAction()");
log.trace(tempAEFMessage);
}
// Call super to perform any common processing and clear any errors before we start.
super.performAction();
Object retVal = null;
int seqResult = -1;
theMainState = State.getState("MAIN");
theItemEntryState = State.getState("ITEMENTRY");
// If ACE is in secured state, and options are set to automatically do a special
// signon, then create the logon action to do the special signon first.
checkForSpecialSignon();
//Check precondition that POS_STATE is "MAIN" state (10). If not, throw an exception.
if (getCurrentState().equals(theMainState))
{
// Application is in the correct state to start the sales transaction.
// if training, don't need to start a transaction, don't send the
// sequence, but same as regular transaction we'll create the object
if(getCurrentSubstate().equals(Substate.getSubstate("ITEM_TRAINING")))
{
// theDetector is created in sendStartTransactionSequence()
theDetector = ((DetectorAccess)(SessionContext.getSession())).getTransactionDetector();
seqResult = 0;
}
else
{
seqResult = sendStartTransactionSequence();
}
if (seqResult==0 || seqResult==1)
{
// Successfully got to item entry state - sales transaction started.
// We will create a sales transaction object even though technically a
// transaction has not yet been started.
SalesTransaction trans = null;
Object obj = theDetector.getObject();
if (obj != null && (obj instanceof SalesTransaction))
{
trans = (SalesTransaction)(obj);
}
else
{
try
{
trans = (SalesTransaction)(FactoryImpl.createObject("SalesTransaction"));
AEFSession session = SessionContext.getSession();
trans.setSession(session);
trans.setIsActive(true);
session.getPOSAutomationProvider().setTransaction(trans);
theDetector.setObject(trans);
}
catch (RemoteException re)
{
// We should never get here because the call is local.
}
}
// If user data was specified, send the data entry sequence.
if (theTransactionID.getData() != null && theTransactionID.getData().length() > 0)
{
seqResult = sendDataEntrySequence();
}
// Check return value of data entry send
retVal = trans;
}
}
else
{
// Not in a valid state for start transaction.
String tempString = "ACEStartTransactionActionImpl.performAction(): POS application not in proper state to perform start transaction.\n Expected state " + theMainState + ", but application is in state " + getCurrentState() + ".";
AEFException tempException = new AEFException(AEFConst.APPLICATION_NOT_IN_PROPER_STATE,
0,
tempString);
tempAEFMessage.setMessage(tempString);
log.error(tempAEFMessage, tempException);
throw tempException;
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEStartTransactionActionImpl.performAction()");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Sends the key sequence which will cause the transaction to be started.
* Note that in ACE, the transaction is not actually started until an item is
* sold, so instead of letting the TransactionDetector create the transaction object,
* we will create it in the action.
*
* @return int An integer value representing the result of the key sequence.
* @exception AEFException
*/
public int sendStartTransactionSequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEStartTransactionActionImpl.sendStartTransactionSequence()");
log.trace(tempAEFMessage);
}
int retVal = -1;
args.clear();
args.put("SEQUENCE_ID", "startTransaction");
theKeySequenceAction = (AEFAction)
(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] goodConditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("TRAINING_MODE")),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("ENTER_ITEM")),
};
theLock = new ConditionLock();
theDetector = ((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.
theInstanceNumber = theDetector.getInstanceNumber();
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"startTransaction",
">>>Sending start transaction key sequence to application.");
}
retVal = theLock.performActionAndWait("wait-for-enter-item-entry-substate",
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Start Transaction Sequence Error");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"startTransaction",
"<<>>Sending data entry key sequence to application.");
}
retVal = theLock.performActionAndWait("wait-for-expecting-item-entry-substate",
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Data Entry Sequence Error");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"startTransaction",
"<<