/*
* ACEItemVoidActionImpl
*
* 07/23/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;
/**
* ACEItemVoidActionImpl is a class which the POSAutomationProvider uses to void
* an item from a transaction on the ACE application.
*
*/
public class ACEItemVoidActionImpl 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.
* @exception AEFException
*/
public ACEItemVoidActionImpl(ActionRequest request) throws AEFException
{
super(request);
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter constructor of ACEItemVoidActionImpl.");
log.trace(tempAEFMessage);
}
// validSubstates contains a list of all the substates for which
// an item may be voided. This is a class static, so it is only
// initialized once.
if (theValidSubstates == null)
{
theValidSubstates = new Vector();
theValidSubstates.addElement(Substate.getSubstate("SELECT_PROCEDURE"));
theValidSubstates.addElement(Substate.getSubstate("EXPECTING_ITEM"));
theValidSubstates.addElement(Substate.getSubstate("EXPECTING_TENDER"));
theValidSubstates.addElement(Substate.getSubstate("TRAINING_MODE"));
}
//theItemID = (ItemIdentifier)(request.getArguments().get("id"));
theItemID = (ItemIdentifier)(request.getArguments());
theQty = theItemID.getQuantity();
thePrice = theItemID.getPrice();
theWeight = theItemID.getWeight();
theDealPrice = theItemID.getDealPrice();
theDealQuantity = theItemID.getDealQuantity();
if (thePrice != null)
{
// Remove any non-digits from the price.
thePrice = thePrice.replaceAll("\\D","");
}
if (theWeight != null)
{
// Remove any non-digits from the weight.
theWeight = theWeight.replaceAll("\\D","");
}
if (theDealPrice != null)
{
// Remove any non-digits from the deal price.
theDealPrice = theDealPrice.replaceAll("\\D","");
}
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Exit constructor of ACEItemVoidActionImpl.");
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 Item instance.
* @exception AEFException
* Among the possible AEFException error codes are:
*
AEFConst.INVALID_ARGUMENT, AEFConst.WEIGHT_AND_QUANTITY_MUTUALLY_EXCLUSIVE
*
Common Errors
*/
public Object performAction() throws AEFException
{
super.performAction();
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEItemVoidActionImpl.performAction()");
log.trace(tempAEFMessage);
}
// Call super to perform any common processing and clear any errors before we start.
Object retVal = null;
if (log.isDebugEnabled())
{
log.debug( new AEFMessage( sessionID, "ACEItemVoidActionImpl.performAction() qty = " + theQty +
" price =" + thePrice +
" weight =" + theWeight +
" dealPrice = " + theDealPrice +
" dealQuantity = " + theDealQuantity)) ;
}
// If ACE is in secured state, and options are set to automatically do a special
// signon, then do a special signon.
checkForSpecialSignon();
int seqResult = -1;
theDetector = ((DetectorAccess)(SessionContext.getSession())).getLineItemDetector();
//Check that ACE is in one of the substates which is valid for item void.
//If not, throw exception.
String currentSubstate = getCurrentSubstate();
if (theValidSubstates.contains(currentSubstate))
{
// Application is in correct substate to void the item.
// Validate input, cannot have qty and weight in same sequence
if (theWeight != null && theWeight.length() != 0)
{
if (theQty != null && theQty.length() != 0)
{
// input bad, can't have both keyed weight and keyed quantity
String tempString = "ACEItemVoidActionImpl.performAction(): Cannot have both a keyed weight and a keyed quantity.\n";
AEFException tempException = new AEFException(AEFConst.INVALID_ARGUMENT,
AEFConst.WEIGHT_AND_QUANTITY_MUTUALLY_EXCLUSIVE,
tempString);
tempAEFMessage.setMessage(tempString);
log.error(tempAEFMessage, tempException);
throw tempException;
}
}
seqResult = sendItemVoidSequence();
if (seqResult>=0)
{
retVal = waitForItem();
}
}
else
{
// Not in valid state for item void.
String tempString = "ACEItemVoidActionImpl.performAction(): POS application not in proper substate to perform item void.\n Application substate is " + currentSubstate + ".";
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 ACEItemVoidActionImpl.performAction()");
log.trace(tempAEFMessage);
}
return retVal;
}
/**
* Sends the key sequence which will cause the item to be voided.
*
*
* @return int An integer value representing the result of the key sequence.
* @exception AEFException
*/
public int sendItemVoidSequence() throws AEFException
{
if (log.isTraceEnabled())
{
tempAEFMessage.setMessage("+Enter ACEItemVoidActionImpl.sendItemVoidSequence()");
log.trace(tempAEFMessage);
}
int retVal = -1;
args.clear();
// Select key sequence:
// Example: (overridePrice) PRICE (quantity) QUANTITY (item) ENTER
// (overridePrice) PRICE (weight) WEIGHT (item) ENTER
StringBuffer sequenceIdBuf = new StringBuffer();
sequenceIdBuf.append("void+");
if (thePrice != null)
{
sequenceIdBuf.append("itemPrice+");
args.put("%itemPrice.0", thePrice);
}
else if (theDealPrice != null)
{
sequenceIdBuf.append("itemDealPrice+");
args.put("%itemDealPrice.0", theDealQuantity);
args.put("%itemDealPrice.1", theDealPrice);
}
if (theQty != null)
{
sequenceIdBuf.append("itemQty+");
args.put("%itemQty.0", theQty);
}
else if (theWeight != null)
{
sequenceIdBuf.append("itemWeight+");
args.put("%itemWeight.0", theWeight);
}
if (log.isDebugEnabled())
{
log.debug( new AEFMessage( sessionID, "ACEItemVoidActionImpl.sendItemVoidSequence itemCode = ." +
theItemID.getItemCode() + ".")) ;
}
sequenceIdBuf.append("item");
args.put("%item.0", theItemID.getItemCode());
args.put("SEQUENCE_ID", new String(sequenceIdBuf));
theKeySequenceAction = (AEFAction)
(actionFactory.makeAction(new ActionRequest("SimpleKeySequenceAction", args)));
Condition[] goodConditions =
{
new PropertyEqualsCondition(POSDeviceProperties.CATEGORY,
POSDeviceProperties.POS_SUB_STATE,
Substate.getSubstate("EXPECTING_ITEM")), // 0 = Success
};
theLock = new ConditionLock();
// Save any current item instance number so we are sure to only get an item
// created after this key sequence is sent.
theInstanceNumber = theDetector.getInstanceNumber();
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"voidItem",
">>>Sending item void key sequence to application.");
}
retVal = theLock.performActionAndWait("wait-for-expecting-item-substate",
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout());
if (retVal < 0)
{
AEFErrorHandler errorHandler = new AEFErrorHandler("Send Item Void Sequence Error");
retVal = errorHandler.handleError(theLock,
theKeySequenceAction,
goodConditions,
BadConditionsImpl.getInstance().getBadConditions(),
getTimeout(),
retVal);
}
if (perfTrace.isEnabled(AEFPerfTrace. COARSE))
{
perfTrace.reportTimer(AEFPerfTrace. COARSE,
sessionID,
"voidItem",
"<<