/* * SAStartTransactionActionImpl * * 11/13/2002 * * 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.factory.*; import com.ibm.retail.AEF.thread.*; import com.ibm.retail.AEF.data.*; import com.ibm.retail.AEF.session.*; import java.util.*; import java.rmi.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * SAStartTransactionActionImpl is a class which the POSAutomationProvider uses to start a * sales transaction on the POS application. * */ public class SAStartTransactionActionImpl extends SAActionImpl { 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: * <br>AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACTION_TYPE * */ public SAStartTransactionActionImpl(ActionRequest request) throws AEFException { super(request); if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAStartTransactionActionImpl.SAStartTransactionActionImpl()."); log.trace(tempAEFMessage); } transactionID = (TransactionIdentifier)(request.getArguments()); String transType = transactionID.getTransactionType(); if (transType == null) { // Default to AEFConst.REGULAR_SALE transType = AEFConst.REGULAR_SALE; } if (!transType.equals(AEFConst.REGULAR_SALE)) { String tempString = "SALogonActionImpl(): Unsupported transaction type = " + transactionID.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 SAStartTransactionActionImpl.SAStartTransactionActionImpl()."); 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: * <br>AEFConst.APPLICATION_NOT_IN_PROPER_STATE */ public Object performAction() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAStartTransactionActionImpl.performAction()."); log.trace(tempAEFMessage); } super.performAction(); // Call super to perform any common processing and clear any errors before we start. Object retVal = null; int seqResult = -1; mainState = State.getState("MAIN"); itemEntryState = State.getState("ITEMENTRY"); // If app 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 exception. if (getCurrentState().equals(mainState)) { // Application is in correct state to start the sales transaction. seqResult = sendStartTransactionSequence(); if (seqResult==0 || seqResult==1) { // Successfully got to item entry state - sales transaction started. // We will create a sales transaction object because technically a // transaction has not yet been started. SalesTransaction trans = null; Object obj = detector.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); detector.setObject(trans); } catch (RemoteException re) { // We should never get here because the call is local. tempAEFMessage.setMessage("There was a remote exception thrown in SAStartTransactionActionImpl.performAction()."); log.error(tempAEFMessage, re); } } // If user data was specified, send the data entry sequence. if (transactionID.getData() != null && transactionID.getData().length() > 0) { seqResult = sendDataEntrySequence(); } retVal = trans; } } else { // Not in valid state for start transaction. String tempString = "SAStartTransactionActionImpl.performAction(): POS application not in proper state to perform start transaction.\n Expected state " + mainState + ", 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 SAStartTransactionActionImpl.performAction()."); log.trace(tempAEFMessage); } return retVal; } /** * Sends the key sequence which will cause the transaction to be started. * Note that in SA, 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 SAStartTransactionActionImpl.sendStartTransactionSequence()."); log.trace(tempAEFMessage); } int retVal = -1; args.clear(); args.put("SEQUENCE_ID", "startTransaction"); keySequenceAction = (AEFAction) (actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args))); Condition[] goodConditions = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("SELECT_PROCEDURE")), new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("TRAINING_MODE")), }; 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(); if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "startTransaction", ">>>Sending start transaction key sequence to application."); } retVal = lock.performActionAndWait("wait-for-expecting-item-entry-substate", keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout()); if (retVal < 0) { AEFErrorHandler errorHandler = new AEFErrorHandler("Send Start Transaction Sequence Error"); retVal = errorHandler.handleError(lock, keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal); } if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "startTransaction", "<<<Start transaction key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit SAStartTransactionActionImpl.sendStartTransactionSequence()."); log.trace(tempAEFMessage); } return retVal; } /** * Sends the user data in a data entry sequence. * * * @return int An integer value representing the result of the key sequence. * @exception AEFException */ public int sendDataEntrySequence() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAStartTransactionActionImpl.sendDataEntrySequence()."); log.trace(tempAEFMessage); } int retVal = -1; 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_SUB_STATE, Substate.getSubstate("SELECT_PROCEDURE")), // 0 = success new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("TRAINING_MODE")), }; lock = new ConditionLock(); if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "startTransaction", ">>>Sending data entry key sequence to application."); } retVal = lock.performActionAndWait("wait-for-expecting-item-entry-substate", keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout()); if (retVal < 0) { AEFErrorHandler errorHandler = new AEFErrorHandler("Send Logoff Sequence Error Part 2 (User Data)"); retVal = errorHandler.handleError(lock, keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal); } if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "startTransaction", "<<<Data entry key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit SAStartTransactionActionImpl.sendDataEntrySequence()."); log.trace(tempAEFMessage); } return retVal; } /* Instance Variables */ protected TransactionIdentifier transactionID = null; protected AEFAction keySequenceAction; protected ConditionLock lock; protected ObjectDetector detector; protected int instanceNumber; protected String mainState; protected String itemEntryState; private static Log log = LogFactory.getLog(SAStartTransactionActionImpl.class); }