/*
* ACEApplyDelayedCouponsActionImpl
*
* 07/22/2003
*
* Copyright:
* Licensed Materials - Property of IBM
* "Restricted Materials of IBM"
* 5724-AEF
* (C) Copyright IBM Corp. 2003.
*
* ace/com/ibm/retail/AEF/action/ACEApplyDelayedCouponsActionImpl.java, aef.ace, aef.bravo 04/07/12
*/
package com.ibm.retail.AEF.action;
import java.util.ArrayList;
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.AndCondition;
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.State;
import com.ibm.retail.AEF.automation.Substate;
import com.ibm.retail.AEF.data.POSDeviceProperties;
import com.ibm.retail.AEF.data.WorkstationStatusProperties;
import com.ibm.retail.AEF.session.SessionContext;
import com.ibm.retail.AEF.thread.ConditionLock;
import com.ibm.retail.AEF.thread.ObjectDetectorLock;
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;
/**
* ACEApplyDelayedCouponsActionImpl is a class which the POSAutomationProvider uses to send
* the sequence which causes delayed coupons to be applied.
* This method should be called only once per transaction when all the items have been entered.
*
*/
public class ACEApplyDelayedCouponsActionImpl 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 which contains a HashMap of arguments.
*
*/
public ACEApplyDelayedCouponsActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter/-Exit constructor of ACEApplyDelayedCouponsActionImpl.");
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:
*
AEFConst.APPLICATION_NOT_IN_PROPER_STATE, AEFConst.APPLICATION_NOT_IN_PROPER_SUBSTATE
*/
public Object performAction() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEApplyDelayedCouponsActionImpl.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();
theDetector = ((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();
}
theCurrentSubstate = getCurrentSubstate();
// Check precondition that POS_SUB_STATE is "EXPECTING_ITEM" substate (1001).
// If not, throw exception.
if (!theCurrentSubstate.equals(Substate.getSubstate("EXPECTING_ITEM")))
{
// Not in valid state for applyDelayedCoupons.
String tempString = "ACEApplyDelayedCouponsActionImpl.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 tempException = new AEFException(AEFConst.APPLICATION_NOT_IN_PROPER_STATE,
AEFConst.APPLICATION_NOT_IN_PROPER_SUBSTATE,
tempString);
tempAEFMessage.setMessage(tempString);
log.error(tempAEFMessage, tempException);
throw tempException;
}
else
{
// Application is in correct state to send the total key.
seqResult = sendApplyDelayedCouponsSequence();
if (seqResult==0)
{
retVal = waitForCoupons();
}
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEApplyDelayedCouponsActionImpl.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 ACEApplyDelayedCouponsActionImpl.sendApplyDelayedCouponsSequence()");
log.trace(tempAEFMessage);
}
int retVal = -1;
args.clear();
args.put("SEQUENCE_ID", "applyDelayedCoupons");
theKeySequenceAction = (AEFAction)
(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] andConditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY,
POSDeviceProperties.POS_STATE,
State.getState("MAIN")),
// substate is coming in AFTER the unit of work, uow gets a True, then a False so
// by the time we get the substate and check, it is no longer True.
/*new PropertyEqualsCondition(POSDeviceProperties.CATEGORY,
POSDeviceProperties.POS_SUB_STATE,
Substate.getSubstate("EXPECTING_TENDER")), */
new PropertyEqualsCondition(WorkstationStatusProperties.CATEGORY,
WorkstationStatusProperties.UNIT_OF_WORK,
"true")
};
Condition[] goodConditions =
{
new AndCondition( andConditions ),
};
Condition andConds2[] =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY,
POSDeviceProperties.POS_STATE,
State.getState("MAIN")),
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY,
POSDeviceProperties.POS_SUB_STATE,
Substate.getSubstate("EXPECTING_TENDER")),
};
Condition goodConditions2[] =
{
new AndCondition(andConds2)
};
theLock = 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.
theInstanceNumber = theDetector.getInstanceNumber();
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"applyDelayedCoupons",
">>>Sending apply delayed coupon key sequence to application.");
}
retVal = theLock.performActionAndWait("wait-for-trans-totalled-substate",
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Apply Delayed Coupons Sequence Error");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
goodConditions2,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("-Exit ACEApplyDelayedCouponsActionImpl.sendApplyDelayedCouponsSequence()");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Wait for any delayed 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 ACEApplyDelayedCouponsActionImpl.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",theDetector, theInstanceNumber, 1, true));
}
catch (AEFException e)
{
// This should never happen since we are ignoring timeout in waitForNewObject call - d 6098
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 ACEApplyDelayedCouponsActionImpl.waitForCoupons()");
log.trace(tempAEFMessage);
}
return retVal;
}
/* Instance Variables */
protected AEFAction theKeySequenceAction;
protected ConditionLock theLock;
protected ObjectDetector theDetector;
protected int theInstanceNumber;
protected String theCurrentSubstate;
private static Log log = LogFactory.getLog(ACEItemEntryActionImpl.class);
}