/* * 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: * <br>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: * <br>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: * <ul> * <li>AEFConst.NO_SALE</li> * <li>AEFConst.REGULAR_CASH</li> * <li>AEFConst.CASH_SPECIAL</li> * <li>AEFConst.CASH_DOC</li> * <li>AEFConst.COD</li> * <li>AEFConst.LAYAWAY</li> * <li>AEFConst.CHARGE_PLAN_A</li> * <li>AEFConst.CHARGE_PLAN_B</li> * <li>AEFConst.CHARGE_PLAN_C</li> * <li>AEFConst.CHARGE_PLAN_D</li> * </ul> * @exception AEFException * AEFException error codes: * <br>AEFConst.INVALID_ARGUMENT, AEFConst.INVALID_TRANSACTION_TYPE</li> */ 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); }