/* * SAApplyDelayedCouponsActionImpl * * 03/21/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.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; /** * SAApplyDelayedCouponsActionImpl is a class which the POSAutomationProvider uses to send * the <Total> sequence which causes delayed coupons to be applied. This action can only be applied * once per transaction. * */ public class SAApplyDelayedCouponsActionImpl 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 which contains a HashMap of arguments. * */ public SAApplyDelayedCouponsActionImpl(ActionRequest request) throws AEFException { super(request); if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter and -Exit SAApplyDelayedCouponsActionImpl.SAApplyDelayedCouponsActionImpl()."); 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 Operator instance. * @exception AEFException * Among the possible error codes are: * <br>AEFConst.APPLICATION_NOT_IN_PROPER_STATE */ public Object performAction() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAApplyDelayedCouponsActionImpl.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; String currentState = getCurrentState(); detector = ((DetectorAccess)(SessionContext.getSession())).getLineItemDetector(); // Check if we are in a clear state. // If so, clear the error. if (currentState.equals(State.getState("CLEAR"))) { sendClearSequence(true); currentState = getCurrentState(); } currentSubstate = getCurrentSubstate(); // Check precondition that POS_SUB_STATE is "EXPECTING_ITEM" substate (1001). // If not, throw exception. if (!currentSubstate.equals(Substate.getSubstate("EXPECTING_ITEM"))) { // Not in valid state for signon. String tempString = "SAApplyDelayedCouponsActionImpl.performAction(): POS application not in proper substate to apply delayed coupons.\n Expected substate " + Substate.getSubstate("EXPECTING_ITEM") + ", but application is in state " + currentState + "."; AEFException tempAEFException = new AEFException(AEFConst.APPLICATION_NOT_IN_PROPER_STATE, 0, tempString); tempAEFMessage.setMessage(tempString); log.error(tempAEFMessage, tempAEFException); throw tempAEFException; } else { // Application is in correct state to send the total key. seqResult = sendApplyDelayedCouponsSequence(); if (seqResult==0) { retVal = waitForCoupons(); } } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit SAApplyDelayedCouponsActionImpl.performAction()."); log.trace(tempAEFMessage); } return retVal; } /** * Sends the key sequence for applying delayed coupons. * * * @return int 0 = success, * @exception AEFException */ public int sendApplyDelayedCouponsSequence() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAApplyDelayedCouponsActionImpl.sendApplyDelayedCouponsSequence()."); log.trace(tempAEFMessage); } int retVal = -1; args.clear(); args.put("SEQUENCE_ID", "applyDelayedCoupons"); keySequenceAction = (AEFAction) (actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args))); Condition[] andConditions = { new PropertyEqualsCondition(POSDeviceProperties.CATEGORY, POSDeviceProperties.POS_SUB_STATE, Substate.getSubstate("TRANS_TOTALLED")), new PropertyEqualsCondition(WorkstationStatusProperties.CATEGORY, WorkstationStatusProperties.UNIT_OF_WORK, "true") }; Condition[] goodConditions = { new AndCondition( andConditions ), }; lock = new ConditionLock(); // Save any current line item instance number so we are sure to only get line items // created after this key sequence is sent. instanceNumber = detector.getInstanceNumber(); if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "applyDelayedCoupons", ">>>Sending apply delayed coupon key sequence to application."); } retVal = lock.performActionAndWait("wait-for-trans-totalled-substate", keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout()); if (retVal < 0) { AEFErrorHandler errorHandler = new AEFErrorHandler("Send Apply Delayed Coupons Sequence Error"); retVal = errorHandler.handleError(lock, keySequenceAction, goodConditions, BadConditionsImpl.getInstance().getBadConditions(), getTimeout(), retVal); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit SAApplyDelayedCouponsActionImpl.sendApplyDelayedCouponsSequence()."); log.trace(tempAEFMessage); } return retVal; } /** * Wait for the coupons to be detected. * * * @return ArrayList An array of LineItems created by the action. * @exception AEFException */ public ArrayList waitForCoupons() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter SAApplyDelayedCouponsActionImpl.waitForCoupons()."); log.trace(tempAEFMessage); } ArrayList retVal = null; ObjectDetectorLock objLock = new ObjectDetectorLock(); // Note: We don't do the typical wait because we may not get any line items. // Since we have already waited for the unit of work, we will only wait 1 ms for the line // items, since they should already have been detected. try { retVal = (ArrayList)(objLock.waitForNewObject("wait-for-coupon-array",detector, instanceNumber, 1)); } catch (AEFException e) { if (e.getErrorCode() == AEFConst.OPERATION_TIMEOUT) { // This is normal. retVal = null; } else { throw e; } } if (perfTrace.isEnabled(AEFPerfTrace. COARSE)) { perfTrace.reportTimer(AEFPerfTrace. COARSE, sessionID, "applyDelayedCoupons", ">>>Apply delayed coupon key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit SAApplyDelayedCouponsActionImpl.waitForCoupons()."); log.trace(tempAEFMessage); } return retVal; } /* Instance and class Variables */ protected AEFAction keySequenceAction; protected ConditionLock lock; protected ObjectDetector detector; protected int instanceNumber; protected String currentSubstate; private static Log log = LogFactory.getLog(SAApplyDelayedCouponsActionImpl.class); }