/* * 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: * <br>AEFConst.INVALID_ARGUMENT, AEFConst.WEIGHT_AND_QUANTITY_MUTUALLY_EXCLUSIVE * <br><a href="../commonerrorcodes.html">Common Errors</a> */ 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", "<<<Item void key sequence processed by application."); } if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACEItemVoidActionImpl.sendItemVoidSequence()"); log.trace(tempAEFMessage); } return retVal; } /** * Sends the key sequence which will cause the item to be sold. * * * @return ArrayList An array of LineItems created by the action. * @exception AEFException */ public ArrayList waitForItem() throws AEFException { if (log.isTraceEnabled()) { tempAEFMessage.setMessage("+Enter ACEItemVoidActionImpl.waitForItem()"); log.trace(tempAEFMessage); } ArrayList retVal = null; // Successfully got to item void. Wait for the array of LineItems to be created. ObjectDetectorLock objLock = new ObjectDetectorLock(); retVal = (ArrayList)(objLock.waitForNewObject("wait-for-item-array", theDetector, theInstanceNumber, getTimeout())); if (log.isTraceEnabled()) { tempAEFMessage.setMessage("-Exit ACEItemVoidActionImpl.waitForItem()"); log.trace(tempAEFMessage); } return retVal; } /* Instance Variables */ protected AEFAction theKeySequenceAction; protected ItemIdentifier theItemID; protected String theQty = null; protected String thePrice = null; protected String theWeight = null; protected String theDealPrice = null; protected String theDealQuantity = null; protected ConditionLock theLock; protected ObjectDetector theDetector; protected int theInstanceNumber; protected String theExpectingItemSubstate; protected static Vector theValidSubstates; private static Log log = LogFactory.getLog(ACEItemVoidActionImpl.class); }