/* * 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: * <br>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: * <br>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", "<<<Start transaction key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACEStartTransactionActionImpl.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 ACEStartTransactionActionImpl.sendDataEntrySequence()"); log.trace(tempAEFMessage); } int retVal = -1; args.clear(); args.put("%0", theTransactionID.getData()); args.put("SEQUENCE_ID", "transDataEntry"); theKeySequenceAction = (AEFAction) (actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args))); Condition[] goodConditions = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("EXPECTING_ITEM")), // 0 = success new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("TRAINING_MODE")), }; theLock = new ConditionLock(); 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", "<<<Data entry key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACEStartTransactionActionImpl.sendDataEntrySequence()"); log.trace(tempAEFMessage); } return retVal; } /* Instance Variables */ protected TransactionIdentifier theTransactionID = null; protected AEFAction theKeySequenceAction; protected ConditionLock theLock; protected ObjectDetector theDetector; protected int theInstanceNumber; protected String theMainState; protected String theItemEntryState; private static Log log = LogFactory.getLog(ACEStartTransactionActionImpl.class); }