0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 1997-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026:
0027: package org.cougaar.logistics.plugin.inventory;
0028:
0029: import org.cougaar.core.adaptivity.OMCRange;
0030: import org.cougaar.core.adaptivity.OMCRangeList;
0031: import org.cougaar.core.adaptivity.OperatingMode;
0032: import org.cougaar.core.adaptivity.OperatingModeImpl;
0033: import org.cougaar.core.agent.service.alarm.Alarm;
0034: import org.cougaar.core.blackboard.IncrementalSubscription;
0035: import org.cougaar.core.component.ServiceRevokedEvent;
0036: import org.cougaar.core.component.ServiceRevokedListener;
0037: import org.cougaar.core.logging.LoggingServiceWithPrefix;
0038: import org.cougaar.core.mts.MessageAddress;
0039: import org.cougaar.core.node.NodeIdentificationService;
0040: import org.cougaar.core.plugin.ComponentPlugin;
0041: import org.cougaar.core.service.*;
0042: import org.cougaar.glm.ldm.asset.*;
0043: import org.cougaar.glm.ldm.oplan.Oplan;
0044: import org.cougaar.glm.ldm.oplan.OrgActivity;
0045: import org.cougaar.logistics.ldm.Constants;
0046: import org.cougaar.logistics.plugin.utils.QuiescenceAccumulator;
0047: import org.cougaar.logistics.plugin.utils.ScheduleUtils;
0048: import org.cougaar.logistics.plugin.utils.TaskScheduler;
0049: import org.cougaar.logistics.plugin.utils.TaskSchedulingPolicy;
0050: import org.cougaar.logistics.servlet.CommStatus;
0051: import org.cougaar.logistics.servlet.LogisticsInventoryServlet;
0052: import org.cougaar.planning.ldm.PlanningFactory;
0053: import org.cougaar.planning.ldm.asset.Asset;
0054: import org.cougaar.planning.ldm.asset.NewItemIdentificationPG;
0055: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
0056: import org.cougaar.planning.ldm.plan.*;
0057: import org.cougaar.planning.plugin.util.AllocationResultHelper;
0058: import org.cougaar.planning.plugin.util.PluginHelper;
0059: import org.cougaar.util.*;
0060:
0061: import java.lang.reflect.Constructor;
0062: import java.util.*;
0063:
0064: /** The InventoryPlugin is the Glue of inventory management.
0065: * It handles all blackboard services for its modules,
0066: * facilitates inter-module communication and manages the
0067: * subscriptions. The InventoryPlugin also creates inventories.
0068: * All modules are called from the InventoryPlugin.
0069: **/
0070:
0071: public class InventoryPlugin extends ComponentPlugin implements
0072: InventoryManager, ClassicRefillGeneratorInventoryManager,
0073: ReconcileSupplyExpanderInventoryManager,
0074: LevelOfDetailInventoryManager {
0075:
0076: protected boolean initialized = false;
0077: // protected boolean firstTimeThrough = true;
0078: protected DomainService domainService;
0079: protected NodeIdentificationService nodeIdService;
0080: protected LoggingService logger;
0081: protected UIDService uidService = null;
0082: protected TaskUtils taskUtils;
0083: protected TimeUtils timeUtils;
0084: protected AssetUtils AssetUtils;
0085: protected ScheduleUtils scheduleUtils;
0086: protected HashMap pluginParams;
0087: protected HashMap inventoryHash;
0088: // protected HashMap inventoryInitHash;
0089: protected HashSet touchedInventories;
0090: // inventoriesWithDeletions used to refresh snapshots.
0091: // Ensures correct graphs during deletion periods.
0092: protected HashSet inventoriesWithDeletions;
0093: // protected HashSet backwardFlowInventories; // ### Captures Inventories with unchanged demand
0094: protected boolean touchedProjections;
0095: protected boolean touchedChangedProjections = false;
0096: protected String supplyType;
0097: // protected String inventoryFile;
0098: // protected boolean fillToCapacity; Will be added bug #1482
0099: // protected boolean maintainAtCapacity; Will be added bug #1482
0100: protected DetReqAggHandler detReqHandler;
0101: protected Organization myOrganization;
0102: protected String myOrgName;
0103: protected ExpanderModule supplyExpander;
0104: protected AllocatorModule externalAllocator;
0105: protected RefillGeneratorModule refillGenerator;
0106: protected RefillProjectionGeneratorModule refillProjGenerator;
0107: protected ComparatorModule refillComparator;
0108: protected AllocationAssessor allocationAssessor;
0109: protected LogisticsPlanModule logisticsPlan;
0110: protected long startTime;
0111: protected long cycleStamp;
0112: protected boolean logToCSV = false;
0113: protected transient ArrayList newRefills = new ArrayList();
0114: protected boolean rehydrateInvs = false;
0115: protected boolean OMChange = false;
0116: protected long prevLevel6;
0117: protected boolean turnOnTaskSched = false;
0118: protected int prepoArrivalOffset = 3;
0119:
0120: public final String SUPPLY_TYPE = "SUPPLY_TYPE";
0121: public final String INVENTORY_FILE = "INVENTORY_FILE";
0122: public final String ENABLE_CSV_LOGGING = "ENABLE_CSV_LOGGING";
0123: public final String PREPO_ARRIVAL_OFFSET = "PREPO_ARRIVAL_OFFSET";
0124: public final String TASK_SCHEDULER_ON = "TASK_SCHEDULER_ON";
0125:
0126: // as a default make the max the end of the oplan (225)
0127: public final Integer LEVEL_2_MIN = new Integer(40); // later, these should be parameters to plugin...
0128: public final Integer LEVEL_2_MAX = new Integer(225);
0129: public final Integer LEVEL_6_MIN = new Integer(20);
0130: public final Integer LEVEL_6_MAX = new Integer(225);
0131: // then default to the end of the oplan (max)
0132: public final String LEVEL_2_TIME_HORIZON = "Level2TimeHorizon";
0133: public final Integer LEVEL_2_TIME_HORIZON_DEFAULT = LEVEL_2_MAX;
0134: public final String LEVEL_6_TIME_HORIZON = "Level6TimeHorizon";
0135: public final Integer LEVEL_6_TIME_HORIZON_DEFAULT = LEVEL_6_MAX;
0136:
0137: // OPlan variable
0138: protected LogisticsOPlan logOPlan = null;
0139:
0140: // Policy variables
0141: protected InventoryPolicy inventoryPolicy = null;
0142: protected int criticalLevel = 3;
0143: protected int reorderPeriod = 3;
0144: protected long bucketSize = TimeUtils.MSEC_PER_DAY;
0145: protected boolean fillToCapacity = false;
0146:
0147: public void load() {
0148: super .load();
0149: logger = getLoggingService(this );
0150: timeUtils = new TimeUtils(this );
0151: AssetUtils = new AssetUtils(this );
0152: taskUtils = new TaskUtils(this );
0153: scheduleUtils = new ScheduleUtils(this );
0154: detReqHandler = new DetReqAggHandler(this );
0155: // readParameters() initializes supplyType and inventoryFile
0156: pluginParams = readParameters();
0157: supplyExpander = getExpanderModule();
0158: externalAllocator = getAllocatorModule();
0159: refillGenerator = getRefillGeneratorModule();
0160: refillProjGenerator = getRefillProjectionGeneratorModule();
0161: refillComparator = getComparatorModule();
0162: allocationAssessor = new AllocationAssessor(this ,
0163: getRole(supplyType));
0164: logisticsPlan = new LogisticsPlan(getAgentIdentifier());
0165: inventoryHash = new HashMap();
0166: // inventoryInitHash = new HashMap();
0167: touchedInventories = new HashSet();
0168: inventoriesWithDeletions = new HashSet();
0169: //backwardFlowInventories = new HashSet();
0170: touchedProjections = false;
0171: startTime = currentTimeMillis();
0172:
0173: domainService = (DomainService) getServiceBroker().getService(
0174: this , DomainService.class,
0175: new ServiceRevokedListener() {
0176: public void serviceRevoked(ServiceRevokedEvent re) {
0177: if (DomainService.class.equals(re.getService()))
0178: domainService = null;
0179: }
0180: });
0181:
0182: nodeIdService = (NodeIdentificationService) getServiceBroker()
0183: .getService(this , NodeIdentificationService.class, null);
0184: if (nodeIdService == null) {
0185: throw new RuntimeException(
0186: "Unable to obtain node-id service.");
0187: }
0188:
0189: if (uidService == null) {
0190: uidService = (UIDService) getServiceBroker().getService(
0191: this , UIDService.class,
0192: new ServiceRevokedListener() {
0193: public void serviceRevoked(
0194: ServiceRevokedEvent re) {
0195: if (UIDService.class
0196: .equals(re.getService()))
0197: uidService = null;
0198: }
0199: });
0200: }
0201:
0202: // System.out.println("\n LOADING InventoryPlugin of type: " + supplyType +
0203: // "in org: " + getAgentIdentifier().toString() +
0204: // " this plugin is: " + this);
0205: }
0206:
0207: public void unload() {
0208: super .unload();
0209: if (domainService != null) {
0210: getServiceBroker().releaseService(this ,
0211: DomainService.class, domainService);
0212: }
0213: if (nodeIdService != null) {
0214: getServiceBroker().releaseService(this ,
0215: NodeIdentificationService.class, nodeIdService);
0216: }
0217: }
0218:
0219: public TaskUtils getTaskUtils() {
0220: return taskUtils;
0221: }
0222:
0223: public TimeUtils getTimeUtils() {
0224: return timeUtils;
0225: }
0226:
0227: public AssetUtils getAssetUtils() {
0228: return AssetUtils;
0229: }
0230:
0231: public ScheduleUtils getScheduleUtils() {
0232: return scheduleUtils;
0233: }
0234:
0235: public String getSupplyType() {
0236: return supplyType;
0237: }
0238:
0239: // protected String getInventoryFileName() {
0240: // return inventoryFile;
0241: // }
0242:
0243: public Organization getMyOrganization() {
0244: return myOrganization;
0245: }
0246:
0247: public String getOrgName() {
0248: return myOrgName;
0249: }
0250:
0251: public long getCurrentTimeMillis() {
0252: return currentTimeMillis();
0253: }
0254:
0255: public void publishAdd(Object o) {
0256: getBlackboardService().publishAdd(o);
0257: }
0258:
0259: public BlackboardService getBBService() {
0260: return getBlackboardService();
0261: }
0262:
0263: public NodeIdentificationService getNodeIdService() {
0264: return nodeIdService;
0265: }
0266:
0267: public UIDService getUIDService() {
0268: return uidService;
0269: }
0270:
0271: public void publishAddExpansion(Expansion expansion) {
0272: PluginHelper.publishAddExpansion(getBlackboardService(),
0273: expansion);
0274: }
0275:
0276: public void publishChange(Object o) {
0277: getBlackboardService().publishChange(o);
0278: }
0279:
0280: public void publishRemove(Object o) {
0281: getBlackboardService().publishRemove(o);
0282: }
0283:
0284: public void removeSubTask(Task taskToRemove) {
0285: PluginHelper
0286: .removeSubTask(getBlackboardService(), taskToRemove);
0287: publishRemove(taskToRemove);
0288: }
0289:
0290: public PlanningFactory getPlanningFactory() {
0291: PlanningFactory rootFactory = null;
0292: if (domainService != null) {
0293: rootFactory = (PlanningFactory) domainService
0294: .getFactory("planning");
0295: }
0296: return rootFactory;
0297: }
0298:
0299: public LoggingService getLoggingService(Object requestor) {
0300: LoggingService ls = (LoggingService) getServiceBroker()
0301: .getService(requestor, LoggingService.class, null);
0302: return LoggingServiceWithPrefix.add(ls, getAgentIdentifier()
0303: + ": ");
0304: }
0305:
0306: protected void execute() {
0307: //clear our new refill list
0308: newRefills.clear();
0309:
0310: // need to call these at beginning of execute cycle
0311: supplyTaskScheduler.initForExecuteCycle();
0312: projectionTaskScheduler.initForExecuteCycle();
0313:
0314: // if the OM changed and the window is further out then before
0315: // then mark the flag true so we process previously ignored tasks
0316: // and allocation results. If it went down - don't undo work
0317: if (!Level6OMSubscription.getChangedCollection().isEmpty()) {
0318: long currentLevel6 = getEndOfLevelSix();
0319: if (logger.isInfoEnabled()) {
0320: logger
0321: .info("Inv Mgr got changed OM ... new end of level 6 window is: "
0322: + currentLevel6
0323: + " in agent: "
0324: + getAgentIdentifier()
0325: + " supply type: " + getSupplyType());
0326: }
0327: if (currentLevel6 > prevLevel6) {
0328: OMChange = true;
0329: }
0330: //reset the previous level 6 to the current
0331: prevLevel6 = currentLevel6;
0332: }
0333:
0334: if (inventoryPolicy == null) {
0335: updateInventoryPolicy(inventoryPolicySubscription);
0336: }
0337: updateInventoryPolicy(inventoryPolicySubscription
0338: .getChangedCollection());
0339: processDetReq(detReqSubscription.getAddedCollection());
0340: cycleStamp = (new Date()).getTime();
0341:
0342: if (inventoryPolicy == null) {
0343: if (logger.isInfoEnabled()) {
0344: logger.info("\n InventoryPlugin " + supplyType
0345: + " not ready to process tasks yet."
0346: + " my inv policy is: " + inventoryPolicy
0347: + " in " + getMyOrganization());
0348: }
0349: return;
0350: }
0351:
0352: if (myOrganization == null) {
0353: myOrganization = getMyOrganization(selfOrganizations
0354: .elements());
0355: }
0356:
0357: if (myOrganization == null) {
0358: if (logger.isInfoEnabled()) {
0359: logger.info("\n InventoryPlugin " + supplyType
0360: + " not ready to process tasks yet."
0361: + " my org is: " + myOrganization);
0362: }
0363: return;
0364: }
0365:
0366: if (!initialized) {
0367: myOrgName = myOrganization.getItemIdentificationPG()
0368: .getItemIdentification();
0369: // inventoryFile = getInventoryFile(supplyType);
0370: // getInventoryData();
0371: initialized = true;
0372: }
0373:
0374: logOPlan = logisticsPlan.updateOrgActivities(oplanSubscription,
0375: orgActSubscription);
0376:
0377: if ((logOPlan != null) && orgActSubscription.hasChanged()) {
0378: resetLogOPlanForInventories();
0379: }
0380:
0381: // if our top level MI task got removed, clean out the references .
0382: if (!aggMILSubscription.getRemovedCollection().isEmpty()) {
0383: detReqHandler.resetAggMITask();
0384: if (logger.isDebugEnabled()) {
0385: logger.debug("Agent: "
0386: + getAgentIdentifier().toString()
0387: + " Top Level MI removed[" + supplyType + "]");
0388: }
0389: }
0390:
0391: //Extra debugging to check for same object on add and remove
0392: if (logger.isDebugEnabled()) {
0393: Collection addedRefills = refillSubscription
0394: .getAddedCollection();
0395: Collection removedRefills = refillSubscription
0396: .getRemovedCollection();
0397: Iterator addRefIt = addedRefills.iterator();
0398: while (addRefIt.hasNext()) {
0399: Task addedRefillTask = (Task) addRefIt.next();
0400: if (removedRefills.contains(addedRefillTask)) {
0401: logger
0402: .debug("Agent "
0403: + getAgentIdentifier().toString()
0404: + "InvPlugin["
0405: + getSupplyType()
0406: + "] Got a Refill Task added and removed in my subscription "
0407: + addedRefillTask.getVerb() + " "
0408: + addedRefillTask.getUID());
0409: }
0410: }
0411:
0412: Collection addedWithdraws = withdrawTaskSubscription
0413: .getAddedCollection();
0414: Collection removedWithdraws = withdrawTaskSubscription
0415: .getRemovedCollection();
0416: Iterator addWD = addedWithdraws.iterator();
0417: while (addWD.hasNext()) {
0418: Task addedWDTask = (Task) addWD.next();
0419: if (removedWithdraws.contains(addedWDTask)) {
0420: logger
0421: .debug("Agent "
0422: + getAgentIdentifier().toString()
0423: + "InvPlugin["
0424: + getSupplyType()
0425: + "] Got a Withdraw Task added and removed in my subscription "
0426: + addedWDTask.getVerb() + " "
0427: + addedWDTask.getUID());
0428: }
0429: }
0430: }
0431: if ((detReqHandler
0432: .getDetermineRequirementsTask(aggMILSubscription) != null)
0433: && (logOPlan != null)) {
0434: if (rehydrateInvs) {
0435: addRehydratedInventories(blackboard
0436: .query(new InventoryPredicate(supplyType)));
0437: if (logger.isDebugEnabled()) {
0438: logger.debug("Agent: "
0439: + getAgentIdentifier().toString()
0440: + "Rehydrating Inventories for InvPlugin["
0441: + supplyType + "]");
0442: }
0443: rehydrateInvs = false;
0444: }
0445:
0446: //Process all the removes at once - note that the supplyExpander.handleRemovedProjections sets the
0447: //touchedRemovedProjections boolean for use later.
0448: boolean touchedRemovedProjections = processRemoves();
0449: Collection addedSupply = supplyTaskScheduler
0450: .getAddedCollection();
0451:
0452: if (!commStatusSub.isEmpty()) {
0453: supplyExpander.determineCommStatus(commStatusSub,
0454: addedSupply);
0455: }
0456: TimeSpan timeSpan = null;
0457: if (turnOnTaskSched) {
0458: timeSpan = supplyTaskScheduler.getCurrentTimeSpan();
0459: } else {
0460: timeSpan = new ScheduleElementImpl(
0461: getLogOPlanStartTime(), getLogOPlanEndTime());
0462: }
0463: if (!addedSupply.isEmpty()) {
0464: expandIncomingRequisitions(getTasksWithoutPEs(addedSupply)); // fix for bug #1695
0465: }
0466: Collection changedSupply = supplyTaskScheduler
0467: .getChangedCollection();
0468: if (!changedSupply.isEmpty()) {
0469: supplyExpander.updateChangedRequisitions(changedSupply);
0470: }
0471: supplyTaskScheduler.finishedExecuteCycle();
0472:
0473: Collection addedProjections = projectionTaskScheduler
0474: .getAddedCollection();
0475: TimeSpan timeSpan2 = null;
0476: if (turnOnTaskSched) {
0477: timeSpan2 = projectionTaskScheduler
0478: .getCurrentTimeSpan();
0479: } else {
0480: timeSpan2 = new ScheduleElementImpl(
0481: getLogOPlanStartTime(), getLogOPlanEndTime());
0482: }
0483: if (!addedProjections.isEmpty()) {
0484: // getTasksWithoutPEs is fix for bug #1695
0485: touchedProjections = expandIncomingProjections(getTasksWithoutPEs(addedProjections));
0486: }
0487: Collection changedProjections = projectionTaskScheduler
0488: .getChangedCollection();
0489: if (!changedProjections.isEmpty()) {
0490: supplyExpander
0491: .updateChangedProjections(changedProjections);
0492: touchedChangedProjections = true;
0493: // System.out.println("Touched changed projections in " + getAgentIdentifier() +
0494: // " type is" + getSupplyType());
0495: }
0496: projectionTaskScheduler.finishedExecuteCycle();
0497:
0498: // Rescind tasks that no longer have a provider
0499: // and
0500: // Allocate any refill tasks from previous executions that were not allocated to providers
0501: // but only if we are not about to rip out previous work we have done
0502: if (didOrgRelationshipsChange()) {
0503: if (logger.isDebugEnabled()) {
0504: logger
0505: .debug("ORG RELATIONSHIPS CHANGED SDSD myorg: "
0506: + myOrganization
0507: + " supply type:"
0508: + supplyType
0509: + " role: "
0510: + getRole(supplyType) + "\n");
0511: }
0512: getOverlappingTasks(refillAllocationSubscription,
0513: Constants.Verb.Supply);
0514: getOverlappingTasks(refillAllocationSubscription,
0515: Constants.Verb.ProjectSupply);
0516:
0517: // Handle unallocated tasks
0518: Collection unalloc = null;
0519: if (addedSupply.isEmpty() && changedSupply.isEmpty()) {
0520: unalloc = getTaskUtils().getUnallocatedTasks(
0521: refillSubscription, Constants.Verb.Supply);
0522: if (!unalloc.isEmpty()) {
0523: if (logger.isInfoEnabled())
0524: logger
0525: .info("TRYING TO ALLOCATE SUPPLY REFILL TASKS...");
0526: externalAllocator.allocateRefillTasks(unalloc);
0527: }
0528: }
0529: if (addedProjections.isEmpty()
0530: && changedProjections.isEmpty()) {
0531: unalloc = getTaskUtils().getUnallocatedTasks(
0532: refillSubscription,
0533: Constants.Verb.ProjectSupply);
0534: if (!unalloc.isEmpty()) {
0535: if (logger.isInfoEnabled())
0536: logger
0537: .info("TRYING TO ALLOCATE PROJECTION REFILL TASKS...");
0538: externalAllocator.allocateRefillTasks(unalloc);
0539: }
0540: }
0541: }
0542:
0543: // call the Refill Generators if we have new demand
0544: if (!getTouchedInventories().isEmpty()) {
0545: // update the inventory customer hash tables when we have new demand
0546: rebuildPGCustomerHash();
0547: //check to see if we have new projections
0548: if (touchedProjections || touchedRemovedProjections
0549: || touchedChangedProjections) {
0550: if (logger.isDebugEnabled()) {
0551: logger.debug("Agent: "
0552: + getAgentIdentifier().toString()
0553: + "InvPlugin" + supplyType + "]"
0554: + "something touched: tprojections: "
0555: + touchedProjections + " tRemovedProj"
0556: + touchedRemovedProjections
0557: + " tChangedProj: "
0558: + touchedChangedProjections);
0559: }
0560: //check to see if the OM changed. If it did process all inventories
0561: //since we probably ignored some demand tasks before the change
0562: if (OMChange) {
0563: refillProjGenerator.calculateRefillProjections(
0564: getInventories(), criticalLevel,
0565: getEndOfLevelSix(), getEndOfLevelTwo(),
0566: refillComparator);
0567: } else {
0568: refillProjGenerator.calculateRefillProjections(
0569: getTouchedInventories(), criticalLevel,
0570: getEndOfLevelSix(), getEndOfLevelTwo(),
0571: refillComparator);
0572: }
0573: }
0574: refillGenerator.calculateRefills(
0575: getTouchedInventories(), refillComparator);
0576: externalAllocator.allocateRefillTasks(newRefills);
0577:
0578: //we might get new demand where we don't need to generate any new refills
0579: // such as small demand from the stimulator servlet - when this happens we
0580: // need to kick the allocation assessor to allocate the withdraws
0581: allocationAssessor
0582: .reconcileInventoryLevels(getActionableInventories());
0583:
0584: }
0585:
0586: // if we are in downward flow ONLY check the withdraw expansion results
0587: // note we may go through the whole list multiple times - but this seems like the
0588: // simplest fix to get rid of places where we miss change reports because the AA
0589: // compares previous results to new ones and leaves the old ones if they are equal.
0590: // note that the updates only occur if the reported result is not equal to the estimated
0591: // so we will not be waking up the whole chain by checking these more than once.
0592: HashSet backwardFlowTouched = null;
0593: if (getTouchedInventories().isEmpty()) {
0594: supplyExpander
0595: .updateAllocationResult(expansionSubscription);
0596: backwardFlowTouched = externalAllocator
0597: .updateAllocationResult(refillAllocationSubscription);
0598: // if the OM changed, process ALL inventories for demand projections and
0599: // allocation results since some results were likely ignored before
0600: // the OM level 6 window changed.
0601: if (OMChange) {
0602: refillProjGenerator.calculateRefillProjections(
0603: getInventories(), criticalLevel,
0604: getEndOfLevelSix(), getEndOfLevelTwo(),
0605: refillComparator);
0606: externalAllocator.allocateRefillTasks(newRefills);
0607: allocationAssessor
0608: .reconcileInventoryLevels(getInventories());
0609: } else {
0610: allocationAssessor
0611: .reconcileInventoryLevels(backwardFlowTouched);
0612: }
0613: } else {
0614: // if the we are not in backwards flow but the OM changed
0615: // process ARs anyway because we may not get woken up again to
0616: // process them if they have all come in already
0617: if (OMChange) {
0618: allocationAssessor
0619: .reconcileInventoryLevels(getInventories());
0620: }
0621: }
0622:
0623: // update the Maintain Inventory Expansion results
0624: PluginHelper
0625: .updateAllocationResult(MIExpansionSubscription);
0626: PluginHelper
0627: .updateAllocationResult(MITopExpansionSubscription);
0628: PluginHelper
0629: .updateAllocationResult(DetReqInvExpansionSubscription);
0630:
0631: if (backwardFlowTouched != null) {
0632: takeInventorySnapshot(backwardFlowTouched);
0633: }
0634: takeInventorySnapshot(getTouchedInventories());
0635: takeInventorySnapshot(getInventoriesWithDeletions());
0636:
0637: // touchedInventories and inventoriesWithDeletions should not be cleared until
0638: // the end of transaction
0639: touchedInventories.clear();
0640: inventoriesWithDeletions.clear();
0641: //backwardFlowInventories.clear(); //###
0642: touchedProjections = false;
0643: touchedChangedProjections = false;
0644: OMChange = false;
0645: //testBG();
0646: } else {
0647: //process any removes if the DetReq task returns null - this should catch the case where it gets rescinded.
0648: // to reduce the amount of times this gets run at start up - only do it if we don't have
0649: // a log oplan also. Note that if the oplan gets rescinded this might need to change.
0650: if (logOPlan != null) {
0651: processRemoves();
0652: takeInventorySnapshot(getTouchedInventories());
0653: touchedInventories.clear();
0654: }
0655: }
0656: supplyExpander.checkCommStatusAlarms();
0657: }
0658:
0659: protected boolean processRemoves() {
0660: if (logger.isDebugEnabled()) {
0661: logger.debug("Agent: " + getAgentIdentifier().toString()
0662: + " Processing Subscription Removes[" + supplyType
0663: + "]");
0664: }
0665: detReqHandler.handleMILTasks(milSubscription);
0666: boolean touchedRemovedProjections = supplyExpander
0667: .handleRemovedProjections(projectWithdrawTaskSubscription
0668: .getRemovedCollection());
0669: supplyExpander
0670: .handleRemovedRequisitions(withdrawTaskSubscription
0671: .getRemovedCollection());
0672: handleRemovedRefills(refillSubscription.getRemovedCollection());
0673: Collection removedDispositions = dispositions
0674: .getRemovedCollection();
0675: if (!removedDispositions.isEmpty()) {
0676: supplyExpander
0677: .handleRemovedDispositions(removedDispositions);
0678: }
0679: return touchedRemovedProjections;
0680: }
0681:
0682: protected void getProviderDates(HashMap providerStartDates,
0683: HashMap providerEndDates) {
0684: RelationshipSchedule relSched = myOrganization
0685: .getRelationshipSchedule();
0686: Collection relationships = relSched.getMatchingRelationships(
0687: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
0688: Iterator rit = relationships.iterator();
0689: Role myRole = getRole(supplyType);
0690: // System.out.println("SDSD myorg: " + myOrganization + " supply type:" +
0691: // supplyType + " role: " + getRole(supplyType) + "\n");
0692: Date date;
0693: while (rit.hasNext()) {
0694: Relationship r = (Relationship) rit.next();
0695: HasRelationships hr = relSched.getOther(r);
0696: if (hr instanceof Organization) {
0697: Role role = relSched.getOtherRole(r);
0698: if (role == myRole) {
0699: date = r.getEndDate();
0700: providerEndDates.put(hr, date);
0701: date = r.getStartDate();
0702: providerStartDates.put(hr, date);
0703: // System.out.println("SDSD org: " + hr + " end:" + date + "\n");
0704: }
0705: }
0706: }
0707: }
0708:
0709: protected HashMap relationshipScheduleMap() {
0710: HashMap providerAvailSched = new HashMap();
0711: RelationshipSchedule relSched = myOrganization
0712: .getRelationshipSchedule();
0713: Role myRole = getRole(supplyType);
0714: Collection relationships = relSched.getMatchingRelationships(
0715: myRole, new TimeSpan.Span(TimeSpan.MIN_VALUE,
0716: TimeSpan.MAX_VALUE));
0717: Iterator rit = relationships.iterator();
0718: Schedule sched = null;
0719:
0720: while (rit.hasNext()) {
0721: Relationship r = (Relationship) rit.next();
0722: HasRelationships hr = relSched.getOther(r);
0723: //String provider;
0724: if (hr instanceof Organization) {
0725: if (!providerAvailSched.containsKey(hr)) {
0726: sched = new ScheduleImpl();
0727: sched.add(r);
0728: providerAvailSched.put(hr, sched);
0729: if (myOrgName.indexOf("1-35-ARBN") >= 0
0730: && supplyType.equals("BulkPOL")
0731: && logger.isDebugEnabled()) {
0732: logger.debug(" adding a provider to the map "
0733: + hr);
0734: }
0735: } else {
0736: sched = (Schedule) providerAvailSched.get(hr);
0737: if (myOrgName.indexOf("1-35-ARBN") >= 0
0738: && supplyType.equals("BulkPOL")
0739: && logger.isDebugEnabled()) {
0740: logger
0741: .debug(" adding a relationship to the provider map "
0742: + hr);
0743: }
0744: sched.add(r);
0745: }
0746: if (myOrgName.indexOf("1-35-ARBN") >= 0
0747: && supplyType.equals("BulkPOL")
0748: && logger.isDebugEnabled()) {
0749: logger.debug("Time spans are " + r.getStartDate()
0750: + " - " + r.getEndDate() + hr);
0751: }
0752: }
0753: }
0754: return providerAvailSched;
0755: }
0756:
0757: // TODO: may not need this
0758: protected Set uniqueProviders() {
0759: RelationshipSchedule myOrgRelSched = myOrganization
0760: .getRelationshipSchedule();
0761: Role myRole = getRole(supplyType);
0762: Collection relationships = myOrgRelSched
0763: .getMatchingRelationships(myRole, new TimeSpan.Span(
0764: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE));
0765: Iterator rit = relationships.iterator();
0766: Set uniqueProviders = new HashSet();
0767: while (rit.hasNext()) {
0768: Relationship r = (Relationship) rit.next();
0769: HasRelationships hr = myOrgRelSched.getOther(r);
0770: if (hr instanceof Organization) {
0771: uniqueProviders.add(hr);
0772: }
0773: }
0774: return uniqueProviders;
0775: }
0776:
0777: protected class EnclosedPredicate implements UnaryPredicate {
0778: protected RelationshipSchedule schedule;
0779: protected Role role;
0780: HasRelationships other;
0781: long start, end;
0782:
0783: public EnclosedPredicate(RelationshipSchedule schedule,
0784: Role role, HasRelationships other, long start, long end) {
0785: this .schedule = schedule;
0786: this .role = role;
0787: this .other = other;
0788: this .start = start;
0789: this .end = end;
0790: }
0791:
0792: public boolean execute(Object obj) {
0793: Relationship relationship = (Relationship) obj;
0794: return ((schedule.getOtherRole(relationship).equals(role))
0795: && (schedule.getOther(relationship).equals(other)) && ((relationship
0796: .getStartTime() <= start) && (relationship
0797: .getEndTime() >= end)));
0798: }
0799: }
0800:
0801: protected class EnclosedSchedPredicate implements UnaryPredicate {
0802: long start;
0803: long end;
0804:
0805: public EnclosedSchedPredicate(long start, long end) {
0806: this .start = start;
0807: this .end = end;
0808: }
0809:
0810: public boolean execute(Object obj) {
0811: if (!(obj instanceof ScheduleElement)) {
0812: throw new IllegalArgumentException(
0813: new StringBuffer()
0814: .append(
0815: " EnclosedSchedPredicate was expecting a ScheduleElement ")
0816: .append(obj).toString());
0817: }
0818: ScheduleElement se = (ScheduleElement) obj;
0819: return se.getStartTime() <= start && se.getEndTime() >= end;
0820: }
0821: }
0822:
0823: protected Collection getUncoveredTasks(Collection tasks) {
0824: ArrayList uncoveredTasks = new ArrayList();
0825: HashMap providersSched = relationshipScheduleMap();
0826: boolean overlap;
0827:
0828: for (Iterator iterator = tasks.iterator(); iterator.hasNext();) {
0829: Task task = (Task) iterator.next();
0830: overlap = false;
0831: Iterator it = providersSched.values().iterator();
0832: while (it.hasNext()) {
0833: Schedule sched = (Schedule) it.next();
0834: if (task.getVerb().equals(Constants.Verb.ProjectSupply)) {
0835: long start = TaskUtils.getStartTime(task);
0836: long end = TaskUtils.getEndTime(task);
0837: if (sched.getEncapsulatedScheduleElements(start,
0838: end).size() > 0
0839: || sched.getOverlappingScheduleElements(
0840: start, end).size() > 0) {
0841: overlap = true;
0842: }
0843: } else { // It is a Supply Task
0844: if (sched.getScheduleElementsWithTime(
0845: TaskUtils.getEndTime(task)).size() > 0) {
0846: overlap = true;
0847: }
0848: }
0849: if (!overlap) {
0850: uncoveredTasks.add(task);
0851: }
0852: }
0853: }
0854: return uncoveredTasks;
0855: }
0856:
0857: protected void getOverlappingTasks(Collection refill_allocations,
0858: Verb verb) {
0859: //RelationshipSchedule myOrgRelSched = myOrganization.getRelationshipSchedule();
0860: HashMap providersSched = relationshipScheduleMap();
0861: Iterator raIt = refill_allocations.iterator();
0862: ArrayList unprovidedTasks = new ArrayList();
0863: ArrayList partial = new ArrayList();
0864: Role myRole = getRole(supplyType);
0865: while (raIt.hasNext()) {
0866: Allocation alloc = (Allocation) raIt.next();
0867: Task task = alloc.getTask();
0868: if ((alloc != null) && (task.getVerb().equals(verb))) {
0869: long taskEnd = TaskUtils.getEndTime(task);
0870: //if the task is totally in the past, don't touch it!
0871: if (currentTimeMillis() > taskEnd) {
0872: continue;
0873: }
0874: Organization provider = (Organization) alloc.getAsset();
0875: if (alloc.getRole() != getRole(supplyType)) {
0876: if (logger.isWarnEnabled())
0877: logger.warn("SDSD MISMATCH: " + alloc.getRole()
0878: + " " + task + "\n");
0879: }
0880: Schedule availSched = (Schedule) providersSched
0881: .get(provider);
0882:
0883: Date start = null; // just a place holder
0884: Collection enclosed;
0885: if (availSched != null) {
0886: if (verb.equals(Constants.Verb.ProjectSupply)) {
0887: // only need provider from start to end - bucketSize
0888: long taskStart = TaskUtils.getStartTime(task);
0889: start = new Date(taskStart);
0890:
0891: //EnclosedPredicate enclosedPred = new EnclosedPredicate(myOrgRelSched, myRole, provider, taskStart, taskEnd);
0892: EnclosedSchedPredicate enclosedPred = new EnclosedSchedPredicate(
0893: taskStart, taskEnd);
0894:
0895: int size = availSched.filter(enclosedPred)
0896: .size();
0897: //System.out.println("Task times " + new Date(taskStart) + " " + start + " size of enclosed" + size);
0898: if (size == 0) {
0899: //if (availSched.getEncapsulatedScheduleElements(taskStart, taskEnd - bucketSize).size() == 0) {
0900: if (availSched
0901: .getOverlappingScheduleElements(
0902: taskStart,
0903: taskEnd - bucketSize)
0904: .size() > 0) {
0905: partial.add(task);
0906: } else {
0907: unprovidedTasks.add(task);
0908: }
0909: }
0910: } else { // it is Supply Task
0911: enclosed = availSched
0912: .getScheduleElementsWithTime(taskEnd);
0913: if (enclosed.size() == 0) {
0914: if (myOrgName.indexOf("1-35-ARBN") >= 0
0915: && supplyType.equals("BulkPOL")
0916: && logger.isDebugEnabled()) {
0917: logger.debug("Adding task to list "
0918: + start + " "
0919: + new Date(taskEnd)
0920: + unprovidedTasks.size());
0921: }
0922: unprovidedTasks.add(task);
0923: }
0924: }
0925: }
0926: }
0927: }
0928: if (myOrgName.indexOf("1-35-ARBN") >= 0
0929: && supplyType.equals("BulkPOL")
0930: && logger.isDebugEnabled()) {
0931: logger.debug("number of unprovided tasks is "
0932: + unprovidedTasks.size());
0933: }
0934: if (!unprovidedTasks.isEmpty()) {
0935: if (logger.isInfoEnabled()) {
0936: logger
0937: .info("Trying to rescind and reallocate unprovided supply refill tasks...");
0938: }
0939: externalAllocator.rescindTaskAllocations(unprovidedTasks);
0940: externalAllocator.allocateRefillTasks(unprovidedTasks);
0941: }
0942: if (!partial.isEmpty()) {
0943: ArrayList originalTasks = new ArrayList();
0944: ArrayList partialsToAlloc = new ArrayList();
0945: Iterator partIt = partial.iterator();
0946: ArrayList failedSplits = new ArrayList();
0947: while (partIt.hasNext()) {
0948: Task taskToSplit = (Task) partIt.next();
0949: List splitTimes = getSplitTimes(taskToSplit,
0950: providersSched);
0951: if (splitTimes.isEmpty()) {
0952: failedSplits.add(taskToSplit);
0953: continue;
0954: }
0955: Collection newPartialTasks = getTaskUtils()
0956: .splitProjection(taskToSplit, splitTimes, this );
0957: originalTasks.add(taskToSplit);
0958: partialsToAlloc.addAll(newPartialTasks);
0959: }
0960:
0961: if (!failedSplits.isEmpty()) {
0962: externalAllocator.rescindTaskAllocations(failedSplits);
0963: externalAllocator.allocateRefillTasks(failedSplits);
0964: }
0965: if (!partialsToAlloc.isEmpty()) {
0966: externalAllocator.rescindTaskAllocations(originalTasks);
0967: externalAllocator.allocateRefillTasks(partialsToAlloc);
0968: }
0969: }
0970: //return unprovidedTasks;
0971: }
0972:
0973: protected List getSplitTimes(Task task, HashMap providerSched) {
0974: ArrayList splits = new ArrayList();
0975: long start = TaskUtils.getStartTime(task);
0976: long end = TaskUtils.getEndTime(task);
0977: PlanElement pe = task.getPlanElement();
0978: Organization provider = null;
0979: if (pe != null && pe instanceof Allocation) {
0980: provider = (Organization) ((Allocation) pe).getAsset();
0981: }
0982: Schedule sched = (Schedule) providerSched.get(provider);
0983: Collection overlaps = sched.getOverlappingScheduleElements(
0984: start, end);
0985: if (overlaps.isEmpty()) {
0986: logger
0987: .error("InvPlugin got no overlapping elements for task start "
0988: + new Date(start)
0989: + " end "
0990: + new Date(end)
0991: + " provider is: " + provider);
0992: return Collections.EMPTY_LIST;
0993: }
0994: ScheduleElement firstlap = (ScheduleElement) overlaps
0995: .iterator().next();
0996: TimeSpan first = new MutableTimeSpan();
0997: TimeSpan second = new MutableTimeSpan();
0998: if (start >= firstlap.getStartTime()) {
0999: if (logger.isInfoEnabled()) {
1000: logger.info("GetSplitTimes... task is: "
1001: + new Date(start) + " ... " + new Date(end)
1002: + " overlapping relationship is: "
1003: + new Date(firstlap.getStartTime()) + " ... "
1004: + new Date(firstlap.getEndTime()));
1005: }
1006: if (!(isValidSpan(start, firstlap.getEndTime()) && isValidSpan(
1007: firstlap.getEndTime(), end))) {
1008: return Collections.EMPTY_LIST;
1009: }
1010: ((NewTimeSpan) first).setTimeSpan(start, firstlap
1011: .getEndTime());
1012: ((NewTimeSpan) second).setTimeSpan(firstlap.getEndTime(),
1013: end);
1014: } else {
1015: if (logger.isInfoEnabled()) {
1016: logger.info("GetSplitTimes... task is: "
1017: + new Date(start) + " ... " + new Date(end)
1018: + " overlapping relationship is: "
1019: + new Date(firstlap.getStartTime()) + " ... "
1020: + new Date(firstlap.getEndTime()));
1021: }
1022: if (!(isValidSpan(firstlap.getStartTime(), end) && isValidSpan(
1023: start, firstlap.getStartTime()))) {
1024: return Collections.EMPTY_LIST;
1025: }
1026: ((NewTimeSpan) first).setTimeSpan(firstlap.getStartTime(),
1027: end);
1028: ((NewTimeSpan) second).setTimeSpan(start, firstlap
1029: .getStartTime());
1030: }
1031: splits.add(first);
1032: splits.add(second);
1033: return splits;
1034: }
1035:
1036: protected boolean isValidSpan(long start, long end) {
1037: if (start < end) {
1038: return true;
1039: } else {
1040: if (logger.isErrorEnabled()) {
1041: logger
1042: .error(" Invalid time span in Inventory plugin, start "
1043: + new Date(start)
1044: + " end "
1045: + new Date(end));
1046: }
1047: return false;
1048: }
1049: }
1050:
1051: /**
1052: * @param task
1053: * @return split times
1054: */
1055: public List getNewTaskSplitTimes(Task task) {
1056: HashMap provHashMap = relationshipScheduleMap();
1057: ArrayList splits = new ArrayList();
1058: long start = TaskUtils.getStartTime(task);
1059: long end = TaskUtils.getEndTime(task);
1060: Collection values = provHashMap.values();
1061: Schedule tmp = new ScheduleImpl();
1062: Iterator valIt = values.iterator();
1063: while (valIt.hasNext()) {
1064: Schedule sched = (Schedule) valIt.next();
1065: tmp.addAll(sched);
1066: }
1067: // Filter out the elements that enclose the span; if they exist, the relationship
1068: // schedule was updated and we are covered. Return an empty list and let the plugin run
1069: // again with the updated info.
1070: Collection enclosed = tmp.filter(new EnclosedSchedPredicate(
1071: start, end));
1072: if (!enclosed.isEmpty()) {
1073: return splits;
1074: }
1075: // if we make it here, then there can only be partial overlaps or none
1076: Collection overlaps = tmp.getOverlappingScheduleElements(start,
1077: end);
1078: if (overlaps.isEmpty()) {
1079: return Collections.EMPTY_LIST;
1080: }
1081: ScheduleElement firstlap = (ScheduleElement) overlaps
1082: .iterator().next();
1083: TimeSpan first = new MutableTimeSpan();
1084: TimeSpan second = new MutableTimeSpan();
1085: if (start >= firstlap.getStartTime()) {
1086: if (!(isValidSpan(firstlap.getEndTime(), end) && isValidSpan(
1087: start, firstlap.getEndTime()))) {
1088: return Collections.EMPTY_LIST;
1089: }
1090: ((NewTimeSpan) first).setTimeSpan(start, firstlap
1091: .getEndTime());
1092: ((NewTimeSpan) second).setTimeSpan(firstlap.getEndTime(),
1093: end);
1094: } else {
1095: if (!(isValidSpan(firstlap.getStartTime(), end) && isValidSpan(
1096: start, firstlap.getStartTime()))) {
1097: return Collections.EMPTY_LIST;
1098: }
1099: ((NewTimeSpan) first).setTimeSpan(firstlap.getStartTime(),
1100: end);
1101: ((NewTimeSpan) second).setTimeSpan(start, firstlap
1102: .getStartTime());
1103: }
1104: splits.add(first);
1105: splits.add(second);
1106: return splits;
1107: }
1108:
1109: protected Collection getUnprovidedTasks(
1110: Collection refill_allocations, Verb verb,
1111: HashMap providerStartDates, HashMap providerEndDates) {
1112: Iterator raIt = refill_allocations.iterator();
1113: ArrayList unprovidedTasks = new ArrayList();
1114: Task task;
1115: Organization provider;
1116: Allocation alloc;
1117: long taskEnd, taskStart;
1118: Date providerEndDate, providerStartDate;
1119: while (raIt.hasNext()) {
1120: alloc = (Allocation) raIt.next();
1121: task = alloc.getTask();
1122: if (task.getVerb().equals(verb)) {
1123: taskEnd = TaskUtils.getEndTime(task);
1124: provider = (Organization) alloc.getAsset();
1125: if (alloc.getRole() != getRole(supplyType)) {
1126: if (logger.isWarnEnabled()) {
1127: logger.warn("SDSD MISMATCH: " + alloc.getRole()
1128: + " " + task + "\n");
1129: }
1130: }
1131: providerEndDate = (Date) providerEndDates.get(provider);
1132: if (verb.equals(Constants.Verb.ProjectSupply)) {
1133: taskStart = TaskUtils.getStartTime(task);
1134: providerStartDate = (Date) providerStartDates
1135: .get(provider);
1136:
1137: // only need provider from start to end - bucketSize
1138: if ((providerEndDate != null && providerEndDate
1139: .getTime() < taskEnd - bucketSize)
1140: || (providerStartDate != null && providerStartDate
1141: .getTime() > taskStart)) {
1142:
1143: unprovidedTasks.add(task);
1144: }
1145: } else {
1146: if (providerEndDate != null
1147: && providerEndDate.getTime() < taskEnd) {
1148: unprovidedTasks.add(task);
1149: }
1150: }
1151: }
1152: }
1153: // if (! unprovidedTasks.isEmpty()) {
1154: // System.out.println("SDSD unprovided: " + unprovidedTasks + "\n");
1155: // }
1156: return unprovidedTasks;
1157: }
1158:
1159: /** Subscription for aggregatable support requests. **/
1160: protected IncrementalSubscription detReqSubscription;
1161:
1162: /** Subscription for the aggregated support request **/
1163: protected IncrementalSubscription aggMILSubscription;
1164:
1165: /** Subscription for the MIL tasks **/
1166: protected IncrementalSubscription milSubscription;
1167:
1168: /** Subscription for the Organization(s) in which this plugin resides **/
1169: protected IncrementalSubscription selfOrganizations;
1170:
1171: /** Subscription for incoming Supply tasks **/
1172: protected TaskScheduler supplyTaskScheduler;
1173: // protected IncrementalSubscription supplyTaskSubscription;
1174:
1175: /** Subscription for incoming Projection tasks **/
1176: protected TaskScheduler projectionTaskScheduler;
1177: // protected IncrementalSubscription projectionTaskSubscription;
1178:
1179: /** Subscription for Allocations on outgoing Refill (Supply & ProjectSupply) tasks **/
1180: protected IncrementalSubscription refillAllocationSubscription;
1181:
1182: /** Subscription for my Refill (Supply & ProjectSupply) tasks **/
1183: protected IncrementalSubscription refillSubscription;
1184:
1185: /** Subscription for my Non-Refill (Supply & ProjectSupply) tasks **/
1186: protected IncrementalSubscription nonrefillSubscription;
1187:
1188: /** Subscription for Supply/ProjectSupply Expansions **/
1189: protected IncrementalSubscription expansionSubscription;
1190:
1191: /** Subscription for InventoryPolicy **/
1192: protected IncrementalSubscription inventoryPolicySubscription;
1193:
1194: /** Subscription for OPlan object **/
1195: protected IncrementalSubscription oplanSubscription;
1196:
1197: /** Subscription for Withdraw tasks created by this plugin **/
1198: protected IncrementalSubscription withdrawTaskSubscription;
1199:
1200: /** Subscription for ProjectWithdraw tasks created by this plugin **/
1201: protected IncrementalSubscription projectWithdrawTaskSubscription;
1202:
1203: /** Subscription for MaintainInventory Expansion PlanElements created by this plugin**/
1204: protected IncrementalSubscription MIExpansionSubscription;
1205:
1206: /** Subscription for MaintainInventory Expansion for Top level MI task (Aggregate task) **/
1207: protected IncrementalSubscription MITopExpansionSubscription;
1208:
1209: /** Subscription for DetermineRequirements of type MaintainInventory Expansion **/
1210: protected IncrementalSubscription DetReqInvExpansionSubscription;
1211:
1212: /** special subscription to oms only used in subsistence to deal with the level2 -> level6
1213: * issue that occurs because subsistence does not generate level 2 tasks
1214: **/
1215: protected IncrementalSubscription Level6OMSubscription;
1216:
1217: //Org Activity subscription
1218: protected IncrementalSubscription orgActSubscription;
1219:
1220: /** Subscription for CommStatus object **/
1221: protected IncrementalSubscription commStatusSub;
1222:
1223: /** Subscription for removed dispositions, need to reconcile with prediction tasks **/
1224: protected IncrementalSubscription dispositions;
1225:
1226: protected IncrementalSubscription shortfallSummary;
1227:
1228: protected void setupSubscriptions() {
1229: if (!getBlackboardService().didRehydrate()) {
1230: setupOperatingModes();
1231: prevLevel6 = getEndOfLevelSix();
1232: } else {
1233: // if we did rehydrate set a flag to rehydrate the inventories
1234: //when we are ready in the execute block
1235: rehydrateInvs = true;
1236: Collection level2OMs = getBlackboardService().query(
1237: new OperatingModePredicate(supplyType,
1238: LEVEL_2_TIME_HORIZON));
1239: //there should only be one.
1240: Iterator level2it = level2OMs.iterator();
1241: if (level2it.hasNext()) {
1242: level2Horizon = (OperatingMode) level2it.next();
1243: }
1244: Collection level6OMs = getBlackboardService().query(
1245: new OperatingModePredicate(supplyType,
1246: LEVEL_6_TIME_HORIZON));
1247: //there should only be one.
1248: Iterator level6it = level6OMs.iterator();
1249: if (level6it.hasNext()) {
1250: level6Horizon = (OperatingMode) level6it.next();
1251: }
1252: prevLevel6 = getEndOfLevelSix();
1253: if (level2Horizon == null || level6Horizon == null) {
1254: if (logger.isErrorEnabled()) {
1255: logger
1256: .error("InventoryPlugin in agent: "
1257: + getAgentIdentifier()
1258: + " of supply type: "
1259: + supplyType
1260: + " is missing operating modes upon rehydration... level2 OM is: "
1261: + level2Horizon
1262: + " level 6 OM is: "
1263: + level6Horizon);
1264: }
1265: }
1266: }
1267:
1268: // Level6OMSubscription = (IncrementalSubscription) blackboard.subscribe(new InventoryPredicateHelper.OperatingModePredicate(supplyType, LEVEL_6_TIME_HORIZON));
1269: Level6OMSubscription = (IncrementalSubscription) blackboard
1270: .subscribe(new OperatingModePredicate(supplyType,
1271: LEVEL_6_TIME_HORIZON));
1272: detReqSubscription = (IncrementalSubscription) blackboard
1273: .subscribe(new DetInvReqPredicate(taskUtils));
1274: aggMILSubscription = (IncrementalSubscription) blackboard
1275: .subscribe(new AggMILPredicate());
1276: milSubscription = (IncrementalSubscription) blackboard
1277: .subscribe(new MILPredicate());
1278: detReqHandler.addMILTasks(milSubscription.elements());
1279: selfOrganizations = (IncrementalSubscription) blackboard
1280: .subscribe(orgsPredicate);
1281: inventoryPolicySubscription = (IncrementalSubscription) blackboard
1282: .subscribe(new InventoryPolicyPredicate(supplyType));
1283: oplanSubscription = (IncrementalSubscription) blackboard
1284: .subscribe(new OplanPredicate());
1285: //logisticsOPlanSubscription = (IncrementalSubscription) blackboard.subscribe(new LogisticsOPlanPredicate());
1286: withdrawTaskSubscription = (IncrementalSubscription) blackboard
1287: .subscribe(new WithdrawPredicate(supplyType));
1288: projectWithdrawTaskSubscription = (IncrementalSubscription) blackboard
1289: .subscribe(new ProjectWithdrawPredicate(supplyType));
1290: MIExpansionSubscription = (IncrementalSubscription) blackboard
1291: .subscribe(new MIExpansionPredicate(supplyType,
1292: taskUtils));
1293: MITopExpansionSubscription = (IncrementalSubscription) blackboard
1294: .subscribe(new MITopExpansionPredicate());
1295: DetReqInvExpansionSubscription = (IncrementalSubscription) blackboard
1296: .subscribe(new DetReqInvExpansionPredicate(taskUtils));
1297: commStatusSub = (IncrementalSubscription) blackboard
1298: .subscribe(new CommStatusPredicate());
1299: dispositions = (IncrementalSubscription) blackboard
1300: .subscribe(new DispositionsPredicate(supplyType,
1301: taskUtils));
1302:
1303: if (getAgentIdentifier() == null && logger.isErrorEnabled()) {
1304: logger
1305: .error("No agentIdentifier ... subscriptions need this info!! In plugin: "
1306: + this );
1307: }
1308: refillAllocationSubscription = (IncrementalSubscription) blackboard
1309: .subscribe(new RefillAllocPredicate(supplyType,
1310: getAgentIdentifier().toString(), taskUtils));
1311: expansionSubscription = (IncrementalSubscription) blackboard
1312: .subscribe(new ExpansionPredicate(supplyType,
1313: getAgentIdentifier().toString(), taskUtils));
1314: refillSubscription = (IncrementalSubscription) blackboard
1315: .subscribe(new RefillPredicate(supplyType,
1316: getAgentIdentifier().toString(), taskUtils));
1317: nonrefillSubscription = (IncrementalSubscription) blackboard
1318: .subscribe(new NonRefillPredicate(supplyType,
1319: getAgentIdentifier().toString(), taskUtils));
1320:
1321: shortfallSummary = (IncrementalSubscription) blackboard
1322: .subscribe(new ShortfallSumPredicate(getSupplyType()));
1323:
1324: //LogOPlan replacment
1325: orgActSubscription = (IncrementalSubscription) blackboard
1326: .subscribe(new OrgActivitiesPredicate());
1327:
1328: // Setup TaskSchedulers
1329: setupTaskSchedulers();
1330: }
1331:
1332: protected void setupTaskSchedulers() {
1333: String taskScheduler = (String) pluginParams
1334: .get(TASK_SCHEDULER_ON);
1335: turnOnTaskSched = new Boolean(taskScheduler).booleanValue();
1336: QuiescenceReportService qrs = (QuiescenceReportService) getServiceBroker()
1337: .getService(this , QuiescenceReportService.class, null);
1338: AgentIdentificationService ais = (AgentIdentificationService) getServiceBroker()
1339: .getService(this , AgentIdentificationService.class,
1340: null);
1341: qrs.setAgentIdentificationService(ais);
1342: QuiescenceAccumulator q = new QuiescenceAccumulator(qrs);
1343: String id = getAgentIdentifier().toString();
1344: if (turnOnTaskSched) {
1345: if (logger.isInfoEnabled())
1346: logger.info("Inv Plugin TASK SCHEDULER ON for " + id
1347: + getSupplyType());
1348: java.io.InputStream is = null;
1349: try {
1350: is = getConfigFinder().open("supplyTaskPolicy.xml");
1351: } catch (Exception e) {
1352: logger
1353: .error("Could not find file supplyTaskPolicy.xml");
1354: }
1355: supplyTaskScheduler = new TaskScheduler(
1356: new SupplyTaskPredicate(supplyType, id, taskUtils),
1357: TaskSchedulingPolicy.fromXML(is, this ,
1358: getAlarmService()), blackboard, q, logger,
1359: "supplyTasks for " + getBlackboardClientName());
1360: try {
1361: is = getConfigFinder().open("projectionTaskPolicy.xml");
1362: } catch (Exception e) {
1363: logger
1364: .error("Could not find file projectionTaskPolicy.xml");
1365: }
1366: projectionTaskScheduler = new TaskScheduler(
1367: new ProjectionTaskPredicate(supplyType, id,
1368: taskUtils), TaskSchedulingPolicy.fromXML(
1369: is, this , getAlarmService()), blackboard,
1370: q, logger, "projTasks for "
1371: + getBlackboardClientName());
1372: } else { // TaskScheduler OFF
1373: if (logger.isInfoEnabled())
1374: logger.info("Inv Plugin TASK SCHEDULER OFF for " + id
1375: + getSupplyType());
1376: supplyTaskScheduler = new TaskScheduler(
1377: new SupplyTaskPredicate(supplyType, id, taskUtils),
1378: new TaskSchedulingPolicy(
1379: new TaskSchedulingPolicy.Predicate[] { TaskSchedulingPolicy.PASSALL }),
1380: blackboard, q, logger, "supplyTasks for "
1381: + getBlackboardClientName());
1382:
1383: projectionTaskScheduler = new TaskScheduler(
1384: new ProjectionTaskPredicate(supplyType, id,
1385: taskUtils),
1386: new TaskSchedulingPolicy(
1387: new TaskSchedulingPolicy.Predicate[] { TaskSchedulingPolicy.PASSALL }),
1388: blackboard, q, logger, "projTasks for "
1389: + getBlackboardClientName());
1390: }
1391: // supplyTaskSubscription = (IncrementalSubscription) blackboard.
1392: // subscribe(new SupplyTaskPredicate(supplyType, id, taskUtils));
1393: // projectionTaskSubscription = (IncrementalSubscription) blackboard.
1394: // subscribe(new ProjectionTaskPredicate(supplyType, id, taskUtils));
1395: }
1396:
1397: protected static class OrgActivitiesPredicate implements
1398: UnaryPredicate {
1399: public OrgActivitiesPredicate() {
1400: }
1401:
1402: public boolean execute(Object o) {
1403: if (o instanceof OrgActivity) {
1404: return true;
1405: }
1406: return false;
1407: }
1408: }
1409:
1410: protected static UnaryPredicate orgsPredicate = new UnaryPredicate() {
1411: public boolean execute(Object o) {
1412: if (o instanceof Organization) {
1413: return ((Organization) o).isSelf();
1414: }
1415: return false;
1416: }
1417: };
1418:
1419: protected static class ShortfallSumPredicate implements
1420: UnaryPredicate {
1421:
1422: String supplyType;
1423:
1424: public ShortfallSumPredicate(String aSupplyType) {
1425: supplyType = aSupplyType;
1426: }
1427:
1428: public boolean execute(Object o) {
1429: if (o instanceof ShortfallSummary) {
1430: return (((ShortfallSummary) o).getSupplyType()
1431: .equals(supplyType));
1432: }
1433: return false;
1434: }
1435: };
1436:
1437: protected static class SupplyTaskPredicate implements
1438: TaskSchedulingPolicy.Predicate {
1439: String supplyType;
1440: String orgName;
1441: TaskUtils taskUtils;
1442:
1443: public SupplyTaskPredicate(String type, String myOrg,
1444: TaskUtils aTaskUtils) {
1445: supplyType = type;
1446: orgName = myOrg;
1447: taskUtils = aTaskUtils;
1448: }
1449:
1450: public boolean execute(Task task) {
1451: return task.getVerb().equals(Constants.Verb.SUPPLY)
1452: && taskUtils.isDirectObjectOfType(task, supplyType)
1453: && (!taskUtils.isMyRefillTask(task, orgName))
1454: && (taskUtils.getQuantity(task) > 0);
1455: }
1456: }
1457:
1458: protected static class ProjectionTaskPredicate implements
1459: TaskSchedulingPolicy.Predicate {
1460: String supplyType;
1461: String orgName;
1462: TaskUtils taskUtils;
1463:
1464: public ProjectionTaskPredicate(String type, String orgname,
1465: TaskUtils aTaskUtils) {
1466: supplyType = type;
1467: orgName = orgname;
1468: taskUtils = aTaskUtils;
1469: }
1470:
1471: public boolean execute(Task task) {
1472: return task.getVerb().equals(Constants.Verb.PROJECTSUPPLY)
1473: && taskUtils.isDirectObjectOfType(task, supplyType)
1474: && (!taskUtils.isMyInventoryProjection(task,
1475: orgName));
1476: }
1477: }
1478:
1479: /**
1480: Passes DetermineRequirements tasks of type MaintainInventory.
1481: **/
1482: protected static class DetInvReqPredicate implements UnaryPredicate {
1483:
1484: protected TaskUtils taskUtils;
1485:
1486: public DetInvReqPredicate(TaskUtils aTaskUtils) {
1487: taskUtils = aTaskUtils;
1488: }
1489:
1490: public boolean execute(Object o) {
1491: if (o instanceof Task) {
1492: Task t = (Task) o;
1493: if (t.getVerb().equals(
1494: Constants.Verb.DETERMINEREQUIREMENTS)) {
1495: return taskUtils.isTaskOfType(t,
1496: "MaintainInventory");
1497: }
1498: }
1499: return false;
1500: }
1501: }
1502:
1503: /** Grab the Expansion of DetReq MaintainInventory and update ARs **/
1504: protected static class DetReqInvExpansionPredicate implements
1505: UnaryPredicate {
1506: private TaskUtils taskUtils;
1507:
1508: public DetReqInvExpansionPredicate(TaskUtils aTaskUtils) {
1509: taskUtils = aTaskUtils;
1510: }
1511:
1512: public boolean execute(Object o) {
1513: if (o instanceof Expansion) {
1514: Task parent = ((Expansion) o).getTask();
1515: if (parent.getVerb().equals(
1516: Constants.Verb.DETERMINEREQUIREMENTS)) {
1517: return taskUtils.isTaskOfType(parent,
1518: "MaintainInventory");
1519: }
1520: }
1521: return false;
1522: }
1523: }
1524:
1525: /**
1526: Selects the per-inventory MaintainInventory tasks.
1527: **/
1528: protected static class MILPredicate implements UnaryPredicate {
1529: public boolean execute(Object o) {
1530: if (o instanceof Task) {
1531: Task t = (Task) o;
1532: if (t.getVerb()
1533: .equals(Constants.Verb.MAINTAININVENTORY)) {
1534: return t.getDirectObject() != null; // true if this is the agg task
1535: }
1536: }
1537: return false;
1538: }
1539: }
1540:
1541: /** get the Expansion for the TOP MI task
1542: * note that this means each instance for each class of supply will
1543: * be looking for the same task - but since the results are checked and only
1544: * changed if there's a difference it shouldn't be too bad.
1545: **/
1546: protected static class MITopExpansionPredicate implements
1547: UnaryPredicate {
1548: public boolean execute(Object o) {
1549: if (o instanceof Expansion) {
1550: Task parent = ((Expansion) o).getTask();
1551: if (parent.getVerb().equals(
1552: Constants.Verb.MAINTAININVENTORY)) {
1553: if (parent.getDirectObject() == null) {
1554: return true;
1555: }
1556: }
1557: }
1558: return false;
1559: }
1560: }
1561:
1562: /**
1563: Selects the aggregate MaintainInventory task
1564: **/
1565: protected static class AggMILPredicate implements UnaryPredicate {
1566: public boolean execute(Object o) {
1567: if (o instanceof Task) {
1568: Task t = (Task) o;
1569: if (t.getVerb()
1570: .equals(Constants.Verb.MAINTAININVENTORY)) {
1571: return t.getDirectObject() == null; // true if this is not the agg task
1572: }
1573: }
1574: return false;
1575: }
1576: }
1577:
1578: /** Selects the MaintainInventory Expansions we create **/
1579: protected static class MIExpansionPredicate implements
1580: UnaryPredicate {
1581: String supplyType;
1582: TaskUtils taskUtils;
1583:
1584: public MIExpansionPredicate(String type, TaskUtils utils) {
1585: supplyType = type;
1586: taskUtils = utils;
1587: }
1588:
1589: public boolean execute(Object o) {
1590: if (o instanceof Expansion) {
1591: Task parent = ((Expansion) o).getTask();
1592: if (parent.getVerb().equals(
1593: Constants.Verb.MAINTAININVENTORY)) {
1594: Asset directObject = parent.getDirectObject();
1595: if (directObject != null
1596: && directObject instanceof Inventory) {
1597: LogisticsInventoryPG thePG = (LogisticsInventoryPG) ((Inventory) directObject)
1598: .searchForPropertyGroup(LogisticsInventoryPG.class);
1599: Asset resource = thePG.getResource();
1600: SupplyClassPG pg = (SupplyClassPG) resource
1601: .searchForPropertyGroup(SupplyClassPG.class);
1602: if (pg != null) {
1603: if (supplyType.equals(pg.getSupplyType())) {
1604: // if (taskUtils.isDirectObjectOfType(parent, supplyType)) {
1605: return true;
1606: }
1607: }
1608: }
1609: }
1610: }
1611: return false;
1612: }
1613: }
1614:
1615: /**
1616: Selects the Oplan objects
1617: **/
1618: protected static class OplanPredicate implements UnaryPredicate {
1619: public boolean execute(Object o) {
1620: return o instanceof Oplan;
1621: }
1622: }
1623:
1624: /**
1625: Passes Inventory assets that have a valid LogisticsInventoryPG
1626: **/
1627:
1628: protected static class InventoryPredicate implements UnaryPredicate {
1629: String supplyType;
1630:
1631: public InventoryPredicate(String type) {
1632: supplyType = type;
1633: }
1634:
1635: public boolean execute(Object o) {
1636: if (o instanceof Inventory) {
1637: Inventory inv = (Inventory) o;
1638: LogisticsInventoryPG logInvpg = (LogisticsInventoryPG) inv
1639: .searchForPropertyGroup(LogisticsInventoryPG.class);
1640: if (logInvpg != null) {
1641: String type = getAssetType(logInvpg);
1642: if (supplyType.equals(type)) {
1643: return true;
1644: }
1645: }
1646: }
1647: return false;
1648: }
1649:
1650: protected String getAssetType(LogisticsInventoryPG invpg) {
1651: Asset a = invpg.getResource();
1652: if (a == null)
1653: return null;
1654: SupplyClassPG pg = (SupplyClassPG) a
1655: .searchForPropertyGroup(SupplyClassPG.class);
1656: return pg.getSupplyType();
1657: }
1658: }
1659:
1660: //Allocation of refill tasks
1661: protected static class RefillAllocPredicate implements
1662: UnaryPredicate {
1663: String type_;
1664: String orgName_;
1665: TaskUtils taskUtils;
1666:
1667: public RefillAllocPredicate(String type, String orgName,
1668: TaskUtils aTaskUtils) {
1669: type_ = type;
1670: orgName_ = orgName;
1671: taskUtils = aTaskUtils;
1672: }
1673:
1674: public boolean execute(Object o) {
1675: if (o instanceof Allocation) {
1676: Task task = ((Allocation) o).getTask();
1677: if (task.getVerb().equals(Constants.Verb.SUPPLY)
1678: || task.getVerb().equals(
1679: Constants.Verb.PROJECTSUPPLY)) {
1680: if (taskUtils.isDirectObjectOfType(task, type_)) {
1681: // need to check if externally allocated
1682: if (((Allocation) o).getAsset() instanceof Organization) {
1683: //if (taskUtils.isMyRefillTask(task, orgName_)){
1684: return true;
1685: //}
1686: }
1687: }
1688: }
1689: }
1690: return false;
1691: }
1692: }
1693:
1694: static class CommStatusPredicate implements UnaryPredicate {
1695: public boolean execute(Object o) {
1696: return o instanceof CommStatus;
1697: }
1698: }
1699:
1700: static class DispositionsPredicate implements UnaryPredicate {
1701: String type_;
1702: TaskUtils taskUtils;
1703:
1704: public DispositionsPredicate(String type, TaskUtils aTaskUtils) {
1705: type_ = type;
1706: taskUtils = aTaskUtils;
1707: }
1708:
1709: public boolean execute(Object o) {
1710: if (o instanceof Disposition) {
1711: Task task = ((Disposition) o).getTask();
1712: if (task.getVerb().equals(Constants.Verb.SUPPLY)
1713: && taskUtils.isDirectObjectOfType(task, type_)) {
1714: return true;
1715: }
1716: }
1717: return false;
1718: }
1719: }
1720:
1721: //Refill tasks
1722: protected static class RefillPredicate implements UnaryPredicate {
1723: String type_;
1724: String orgName_;
1725: TaskUtils taskUtils;
1726:
1727: public RefillPredicate(String type, String orgName,
1728: TaskUtils aTaskUtils) {
1729: type_ = type;
1730: orgName_ = orgName;
1731: taskUtils = aTaskUtils;
1732: }
1733:
1734: public boolean execute(Object o) {
1735: if (o instanceof Task) {
1736: Task task = (Task) o;
1737: if (task.getVerb().equals(Constants.Verb.SUPPLY)
1738: || task.getVerb().equals(
1739: Constants.Verb.PROJECTSUPPLY)) {
1740: if (taskUtils.isDirectObjectOfType(task, type_)) {
1741: if (taskUtils.isMyRefillTask(task, orgName_)) {
1742: return true;
1743: }
1744: }
1745: }
1746: }
1747: return false;
1748: }
1749: }
1750:
1751: //Non-Refill tasks
1752: static class NonRefillPredicate implements UnaryPredicate {
1753: String type_;
1754: String orgName_;
1755: TaskUtils taskUtils;
1756:
1757: public NonRefillPredicate(String type, String orgName,
1758: TaskUtils aTaskUtils) {
1759: type_ = type;
1760: orgName_ = orgName;
1761: taskUtils = aTaskUtils;
1762: }
1763:
1764: public boolean execute(Object o) {
1765: if (o instanceof Task) {
1766: Task task = (Task) o;
1767: if (task.getVerb().equals(Constants.Verb.SUPPLY)
1768: || task.getVerb().equals(
1769: Constants.Verb.PROJECTSUPPLY)) {
1770: if (taskUtils.isDirectObjectOfType(task, type_)) {
1771: if (taskUtils.isMyNonRefillTask(task, orgName_)) {
1772: return true;
1773: }
1774: }
1775: }
1776: }
1777: return false;
1778: }
1779: }
1780:
1781: protected class ExpansionPredicate implements UnaryPredicate {
1782: String supplyType;
1783: String orgName;
1784: TaskUtils taskUtils;
1785:
1786: public ExpansionPredicate(String type, String orgname,
1787: TaskUtils taskUtils) {
1788: supplyType = type;
1789: orgName = orgname;
1790: this .taskUtils = taskUtils;
1791: }
1792:
1793: public boolean execute(Object o) {
1794: if (o instanceof Expansion) {
1795: Task task = ((Expansion) o).getTask();
1796: if (task.getVerb().equals(Constants.Verb.SUPPLY)
1797: || task.getVerb().equals(
1798: Constants.Verb.PROJECTSUPPLY)) {
1799: if (taskUtils
1800: .isDirectObjectOfType(task, supplyType)) {
1801: if (!taskUtils.isMyRefillTask(task, orgName)) {
1802: return true;
1803: }
1804: }
1805: }
1806: }
1807: return false;
1808: }
1809: }
1810:
1811: protected class InventoryPolicyPredicate implements UnaryPredicate {
1812: String type;
1813:
1814: public InventoryPolicyPredicate(String type) {
1815: this .type = type;
1816: }
1817:
1818: public boolean execute(Object o) {
1819: if (o instanceof org.cougaar.logistics.plugin.inventory.InventoryPolicy) {
1820: String type = ((InventoryPolicy) o).getResourceType();
1821: if (type.equals(this .type)) {
1822: if (logger.isInfoEnabled()) {
1823: logger.info("Found an inventory policy for "
1824: + this .type + "agent is: "
1825: + getMyOrganization());
1826: }
1827: return true;
1828: } else {
1829: if (logger.isDebugEnabled()) {
1830: logger.debug("Ignoring type of: " + type
1831: + " in " + getMyOrganization()
1832: + " this type is: " + this .type);
1833: }
1834: }
1835: }
1836: return false;
1837: }
1838: }
1839:
1840: /**
1841: * Filters out tasks that already have PEs -- fix for bug #1695
1842: * @param tasks - possibly from added list
1843: * @return Collection - tasks that have no PEs
1844: */
1845: protected Collection getTasksWithoutPEs(Collection tasks) {
1846: Set tasksWithoutPEs = new HashSet();
1847: for (Iterator iter = tasks.iterator(); iter.hasNext();) {
1848: Task task = (Task) iter.next();
1849:
1850: if (task.getPlanElement() != null) {
1851: if (logger.isDebugEnabled()) {
1852: logger
1853: .debug(getMyOrganization()
1854: + " - found task that already had a p.e. attached? : "
1855: + task.getUID()
1856: + " - so skipping it.");
1857: }
1858: } else {
1859: tasksWithoutPEs.add(task);
1860: }
1861: }
1862:
1863: return tasksWithoutPEs;
1864: }
1865:
1866: protected class WithdrawPredicate implements UnaryPredicate {
1867: String supplyType;
1868:
1869: public WithdrawPredicate(String type) {
1870: supplyType = type;
1871: }
1872:
1873: public boolean execute(Object o) {
1874: if (o instanceof Task) {
1875: Task task = (Task) o;
1876: if (task.getVerb().equals(Constants.Verb.WITHDRAW)) {
1877: if (taskUtils
1878: .isDirectObjectOfType(task, supplyType)) {
1879: return true;
1880: }
1881: }
1882: }
1883: return false;
1884: }
1885: }
1886:
1887: protected class ProjectWithdrawPredicate implements UnaryPredicate {
1888: String supplyType;
1889:
1890: public ProjectWithdrawPredicate(String type) {
1891: supplyType = type;
1892: }
1893:
1894: public boolean execute(Object o) {
1895: if (o instanceof Task) {
1896: Task task = (Task) o;
1897: if (task.getVerb().equals(
1898: Constants.Verb.PROJECTWITHDRAW)) {
1899: if (taskUtils
1900: .isDirectObjectOfType(task, supplyType)) {
1901: return true;
1902: }
1903: }
1904: }
1905: return false;
1906: }
1907: }
1908:
1909: protected class OperatingModePredicate implements UnaryPredicate {
1910: String supplyType;
1911: String level;
1912:
1913: public OperatingModePredicate(String type, String level) {
1914: supplyType = type;
1915: this .level = level;
1916: }
1917:
1918: public boolean execute(Object o) {
1919: if (o instanceof OperatingMode) {
1920: OperatingMode om = (OperatingMode) o;
1921: if (om.getName().equals(level + "_" + supplyType)) {
1922: return true;
1923: }
1924: }
1925: return false;
1926: }
1927: }
1928:
1929: protected void expandIncomingRequisitions(Collection tasks) {
1930: supplyExpander.expandAndDistributeRequisitions(tasks);
1931: }
1932:
1933: protected boolean expandIncomingProjections(Collection tasks) {
1934: return supplyExpander.expandAndDistributeProjections(tasks);
1935: }
1936:
1937: /**
1938: Add some inventories to the inventoryHash.
1939: Method called during rehydration to populate inventory hash
1940: **/
1941: protected void addRehydratedInventories(Collection inventories) {
1942: for (Iterator i = inventories.iterator(); i.hasNext();) {
1943: Inventory inv = (Inventory) i.next();
1944: LogisticsInventoryPG logInvPG = (LogisticsInventoryPG) inv
1945: .searchForPropertyGroup(LogisticsInventoryPG.class);
1946: logInvPG.setStartCDay(logOPlan.getOplanCday());
1947: logInvPG.reinitialize(logToCSV, this );
1948: addInventory(inv);
1949: }
1950: }
1951:
1952: //AHF
1953: protected void resetLogOPlanForInventories() {
1954: Iterator inventories = getInventories().iterator();
1955: while (inventories.hasNext()) {
1956: Inventory inv = (Inventory) inventories.next();
1957: LogisticsInventoryPG logInvPG = (LogisticsInventoryPG) inv
1958: .searchForPropertyGroup(LogisticsInventoryPG.class);
1959: if (logInvPG.getArrivalTime() != getOPlanArrivalInTheaterTime()) {
1960: if (logInvPG.getSupplierArrivalTime() != -1) {
1961: long newSupplierArrivalTime = logInvPG
1962: .getSupplierArrivalTime()
1963: + (getOPlanArrivalInTheaterTime() - logInvPG
1964: .getArrivalTime());
1965: ((NewLogisticsInventoryPG) logInvPG)
1966: .setSupplierArrivalTime(newSupplierArrivalTime);
1967: }
1968: logInvPG.setArrivalTime(getOPlanArrivalInTheaterTime());
1969: logInvPG.setStartCDay(logOPlan.getOplanCday());
1970: publishChange(inv);
1971: touchInventory(inv);
1972: touchedChangedProjections = true;
1973: }
1974: }
1975: }
1976:
1977: protected void addInventory(Inventory inventory) {
1978: String item = getInventoryType(inventory);
1979: inventoryHash.put(item, inventory);
1980: }
1981:
1982: protected void removeInventories(Enumeration inventories) {
1983: while (inventories.hasMoreElements()) {
1984: removeInventory((Inventory) inventories.nextElement());
1985: }
1986: }
1987:
1988: protected void removeInventory(Inventory inventory) {
1989: String item = getInventoryType(inventory);
1990: inventoryHash.remove(item);
1991: }
1992:
1993: public String getInventoryType(Inventory inventory) {
1994: ScheduledContentPG scp = inventory.getScheduledContentPG();
1995: Asset proto = scp.getAsset();
1996: if (proto == null) {
1997: if (logger.isErrorEnabled()) {
1998: logger
1999: .error("getInventoryType failed to get asset for "
2000: + inventory.getScheduledContentPG()
2001: .getAsset()
2002: .getTypeIdentificationPG());
2003: }
2004: return "";
2005: }
2006: return proto.getTypeIdentificationPG().getTypeIdentification();
2007: }
2008:
2009: public void touchInventoryForTask(Task taskWithInventory,
2010: Inventory inventory) {
2011: touchInventory(inventory);
2012: }
2013:
2014: public Inventory findOrMakeInventory(Task task) {
2015: throw new IllegalArgumentException(
2016: "this method should not be called in AL.");
2017: //return null;
2018: }
2019:
2020: public Inventory findOrMakeInventory(Asset resource) {
2021: Inventory inventory = null;
2022: String item = resource.getTypeIdentificationPG()
2023: .getTypeIdentification();
2024: inventory = (Inventory) inventoryHash.get(item);
2025: if (inventory != null) {
2026: if (logger.isDebugEnabled()) {
2027: logger
2028: .debug("findOrMakeInventory(), FOUND inventory bing for: "
2029: + AssetUtils.assetDesc(inventory
2030: .getScheduledContentPG()
2031: .getAsset()));
2032: }
2033: return inventory;
2034: } else {
2035: inventory = createInventory(resource, item);
2036: addInventory(inventory);
2037: publishAdd(inventory);
2038: detReqHandler.findOrMakeMILTask(inventory,
2039: aggMILSubscription);
2040: }
2041: if (logger.isDebugEnabled()) {
2042: logger
2043: .debug("findOrMakeInventory(), CREATED inventory bin for: "
2044: + AssetUtils
2045: .assetDesc(inventory
2046: .getScheduledContentPG()
2047: .getAsset()));
2048: }
2049: return inventory;
2050: }
2051:
2052: protected Inventory createInventory(Asset resource, String item) {
2053: // double levels[] = null;
2054: Inventory inventory = null;
2055: // levels = (double[]) inventoryInitHash.get(item);
2056: // if (levels == null) {
2057: // levels = new double[2];
2058: double capacity = getFuelCapacity(item);
2059: double initialLevel = getInitialLevel(item);
2060: // }
2061: inventory = (Inventory) getPlanningFactory().createAsset(
2062: "Inventory");
2063: NewLogisticsInventoryPG logInvPG = (NewLogisticsInventoryPG) PropertyGroupFactory
2064: .newLogisticsInventoryPG();
2065: inventory.addOtherPropertyGroup(logInvPG);
2066: if (getAssetUtils().isLevel2Asset(resource)) {
2067: logInvPG.setIsLevel2(true); // will need to key off asset to identify level2 item
2068: // Need to distinguish Level2Package aggregates of different supply types otherwise
2069: // they are determined to be the same asset and are removed from the blackboard
2070: ((NewItemIdentificationPG) inventory
2071: .getItemIdentificationPG())
2072: .setItemIdentification("Inventory:" + item + ":"
2073: + supplyType);
2074: } else {
2075: logInvPG.setIsLevel2(false);
2076: ((NewItemIdentificationPG) inventory
2077: .getItemIdentificationPG())
2078: .setItemIdentification("Inventory:" + item);
2079: }
2080: logInvPG.setCapacity(capacity);
2081: logInvPG.setFillToCapacity(fillToCapacity);
2082: logInvPG.setInitialLevel(initialLevel);
2083: logInvPG.setResource(resource);
2084: logInvPG.setOrg(getMyOrganization());
2085: logInvPG.setSupplierArrivalTime(getSupplierArrivalTime());
2086: logInvPG.setLogInvBG(new LogisticsInventoryBG(logInvPG));
2087: logInvPG.initialize(startTime, this .getOPlanEndTime(),
2088: criticalLevel, reorderPeriod, getOrderShipTime(),
2089: bucketSize, getCurrentTimeMillis(), logToCSV, this );
2090: logInvPG.setArrivalTime(getOPlanArrivalInTheaterTime());
2091: logInvPG.setStartCDay(logOPlan.getOplanCday());
2092:
2093: NewTypeIdentificationPG ti = (NewTypeIdentificationPG) inventory
2094: .getTypeIdentificationPG();
2095: ti.setTypeIdentification("InventoryAsset");
2096: ti.setNomenclature("Inventory Asset");
2097:
2098: NewScheduledContentPG scp;
2099: scp = (NewScheduledContentPG) inventory.getScheduledContentPG();
2100: scp.setAsset(resource);
2101: scp.setSchedule(scheduleUtils.buildSimpleQuantitySchedule(
2102: initialLevel, startTime, startTime
2103: + (TimeUtils.MSEC_PER_DAY * 10)));
2104:
2105: return inventory;
2106: }
2107:
2108: // Override these in a subclass if necessary
2109: protected double getFuelCapacity(String item) {
2110: return 0.0;
2111: }
2112:
2113: protected double getInitialLevel(String item) {
2114: return 0.0;
2115: }
2116:
2117: public void touchInventory(Inventory inventory) {
2118: if (!touchedInventories.contains(inventory)) {
2119: touchedInventories.add(inventory);
2120: }
2121: }
2122:
2123: public Collection getTouchedInventories() {
2124: return touchedInventories;
2125: }
2126:
2127: public Collection getInventories() {
2128: return inventoryHash.values();
2129: }
2130:
2131: public void touchInventoryWithDeletions(Inventory inventory) {
2132: if (!inventoriesWithDeletions.contains(inventory)) {
2133: inventoriesWithDeletions.add(inventory);
2134: }
2135: }
2136:
2137: public Collection getInventoriesWithDeletions() {
2138: return inventoriesWithDeletions;
2139: }
2140:
2141: public void takeInventorySnapshot(Collection inventories) {
2142: Inventory inv;
2143: Iterator inv_it = inventories.iterator();
2144: LogisticsInventoryPG logInvPG = null;
2145: while (inv_it.hasNext()) {
2146: inv = (Inventory) inv_it.next();
2147: logInvPG = (LogisticsInventoryPG) inv
2148: .searchForPropertyGroup(LogisticsInventoryPG.class);
2149: logInvPG.takeSnapshot(inv);
2150: if (logToCSV) {
2151: logInvPG.logAllToCSVFile(cycleStamp);
2152: }
2153:
2154: // Force incremental persistence snapshots to include changes to these
2155: publishChange(inv);
2156: }
2157: checkShortfallStatus(inventories);
2158: }
2159:
2160: public void checkShortfallStatus(Collection inventories) {
2161: Inventory inv;
2162: Iterator inv_it = inventories.iterator();
2163: LogisticsInventoryPG logInvPG = null;
2164: ArrayList shortfallInvs = new ArrayList();
2165: ArrayList nonShortfallInvs = new ArrayList();
2166: while (inv_it.hasNext()) {
2167: inv = (Inventory) inv_it.next();
2168: String invID = LogisticsInventoryServlet
2169: .getNomenclature(inv);
2170:
2171: ShortfallInventory shortfallInv = checkForShortfall(inv);
2172: if (shortfallInv != null) {
2173: shortfallInvs.add(shortfallInv);
2174: } else {
2175: nonShortfallInvs.add(invID);
2176: }
2177: }
2178: ShortfallSummary shortSum = null;
2179: if (!shortfallSummary.isEmpty()) {
2180: shortSum = (ShortfallSummary) shortfallSummary.iterator()
2181: .next();
2182: }
2183: //If the shortfall summary doesn't exist yet and there are shortfall inventories
2184: //Create and publish add the shortfall summary.
2185: if (shortSum == null) {
2186: if (!shortfallInvs.isEmpty()) {
2187: shortSum = new ShortfallSummary(getSupplyType(),
2188: uidService.nextUID(), bucketSize);
2189: Iterator it = shortfallInvs.iterator();
2190: shortSum.setShortfallInventories(shortfallInvs);
2191: publishAdd(shortSum);
2192: }
2193: return;
2194: }
2195: boolean addedShort = shortSum
2196: .addShortfallInventories(shortfallInvs);
2197: boolean removedShort = shortSum
2198: .removeShortfallInventories(nonShortfallInvs);
2199:
2200: if (addedShort || removedShort) {
2201: if (!shortSum.getShortfallInventories().isEmpty()) {
2202: /***
2203: if(getOrgName().startsWith("47-FSB")) {
2204: logger.warn("47-FSB - num short:" + shortSum);
2205: }
2206: **/
2207: publishChange(shortSum);
2208: } else {
2209: publishRemove(shortSum);
2210: /***
2211: if(getOrgName().startsWith("47-FSB")) {
2212: logger.warn("47-FSB - Removing ShortfallSummary");
2213: }
2214: **/
2215:
2216: }
2217: }
2218:
2219: }
2220:
2221: public ShortfallInventory checkForShortfall(Inventory inv) {
2222: String invID = LogisticsInventoryServlet.getNomenclature(inv);
2223: LogisticsInventoryPG logInvPG = (LogisticsInventoryPG) inv
2224: .searchForPropertyGroup(LogisticsInventoryPG.class);
2225: String unitOfIssue = LogisticsInventoryFormatter
2226: .getUnitForAsset(inv);
2227: return logInvPG.checkForShortfall(invID, unitOfIssue);
2228: }
2229:
2230: /**
2231: Read the Plugin parameters(Accepts key/value pairs)
2232: Initializes supplyType and inventoryFile
2233: **/
2234: protected HashMap readParameters() {
2235: Collection p = getParameters();
2236:
2237: if (p.isEmpty()) {
2238: if (logger.isErrorEnabled()) {
2239: logger
2240: .error("No parameters: InventoryPlugin requires 1 parameter, Supply Type. Additional parameter for csv logging, default is disabled. e.g. org.cougaar.logistics.plugin.inventory.InventoryPlugin("
2241: + SUPPLY_TYPE
2242: + "=BulkPOL, ENABLE_CSV_LOGGING=true)");
2243: }
2244: return null;
2245: }
2246: HashMap map = new HashMap();
2247: int idx;
2248:
2249: for (Iterator i = p.iterator(); i.hasNext();) {
2250: String s = (String) i.next();
2251: if ((idx = s.indexOf('=')) != -1) {
2252: String key = new String(s.substring(0, idx));
2253: String value = new String(s.substring(idx + 1, s
2254: .length()));
2255: map.put(key.trim(), value.trim());
2256: }
2257: }
2258: supplyType = (String) map.get(SUPPLY_TYPE);
2259: // inventoryFile = (String)map.get(INVENTORY_FILE);
2260: if (supplyType == null && logger.isErrorEnabled()) {
2261: logger
2262: .error("No SUPPLY_TYPE parameter: InventoryPlugin requires 1 parameter, Supply Type. Additional parameter for csv logging, default is disabled. e.g. org.cougaar.logistics.plugin.inventory.InventoryPlugin("
2263: + SUPPLY_TYPE
2264: + "=BulkPOL, ENABLE_CSV_LOGGING=true)");
2265: }
2266: String loggingEnabled = (String) map.get(ENABLE_CSV_LOGGING);
2267: if ((loggingEnabled != null)
2268: && (loggingEnabled.trim().equals("true"))) {
2269: logToCSV = true;
2270: }
2271:
2272: String prepoOffsetStr = (String) map.get(PREPO_ARRIVAL_OFFSET);
2273: if ((prepoOffsetStr != null)
2274: && !(prepoOffsetStr.trim().equals(""))) {
2275: try {
2276: int prepoOffset = Integer.parseInt(prepoOffsetStr);
2277: prepoArrivalOffset = prepoOffset;
2278: } catch (NumberFormatException ex) {
2279: logger
2280: .error("InventoryPlugin("
2281: + PREPO_ARRIVAL_OFFSET
2282: + "="
2283: + prepoOffsetStr
2284: + ") value is not a parseable integer. Defaulting to "
2285: + prepoArrivalOffset);
2286: }
2287:
2288: }
2289: return map;
2290: }
2291:
2292: // protected String getInventoryFile(String type) {
2293: // String result = null;
2294: // // if defined in plugin argument list
2295: // String inv_file = null;
2296: // if ((inv_file = (String) pluginParams.get(INVENTORY_FILE)) != null) {
2297: // result = inv_file;
2298: // // }
2299: // // else {
2300: // // result = getClusterSuffix(myOrganization.getClusterPG().getMessageAddress().toString()) +
2301: // // "_"+type.toLowerCase()+".inv";
2302: // } else if (type.equals("Ammunition")) {
2303: // result = getAgentPrefix(getAgentIdentifier().toString()) +
2304: // "_" + type.toLowerCase() + ".inv";
2305: // } else {
2306: // result = getClusterSuffix(getAgentPrefix(getAgentIdentifier().toString())) +
2307: // "_" + type.toLowerCase() + ".inv";
2308: // }
2309: // return result;
2310: // }
2311:
2312: protected String getAgentPrefix(String agentId) {
2313: int i = agentId.indexOf(".");
2314: if (i <= 0) {
2315: return agentId;
2316: } else {
2317: return agentId.substring(0, i);
2318: }
2319: }
2320:
2321: protected String getClusterSuffix(String clusterId) {
2322: String result = null;
2323: int i = clusterId.lastIndexOf("-");
2324: if (i == -1) {
2325: result = clusterId;
2326: } else {
2327: result = clusterId.substring(i + 1);
2328: }
2329: return result;
2330: }
2331:
2332: public void publishAddToExpansion(Task parent, Task subtask) {
2333: //attach the subtask to its parent and the parent's workflow
2334: PlanElement pe = parent.getPlanElement();
2335: Expansion expansion;
2336: NewWorkflow wf;
2337: ((NewTask) subtask).setParentTask(parent);
2338: ((NewTask) subtask).setContext(parent.getContext());
2339: ((NewTask) subtask).setPlan(parent.getPlan());
2340: // Task has not been expanded, create an expansion
2341: if (pe instanceof Disposition) {
2342: publishRemove(pe);
2343: pe = null;
2344: }
2345: if (pe == null) {
2346: PlanningFactory factory = getPlanningFactory();
2347: // Create workflow
2348: wf = (NewWorkflow) factory.newWorkflow();
2349: wf.setParentTask(parent);
2350: wf.setIsPropagatingToSubtasks(true);
2351: wf.addTask(subtask);
2352: ((NewTask) subtask).setWorkflow(wf);
2353: // Build Expansion
2354: expansion = factory.createExpansion(parent.getPlan(),
2355: parent, wf, null);
2356: // Publish Expansion
2357: publishAdd(expansion);
2358: if (logger.isDebugEnabled()) {
2359: logger.debug("Agent: "
2360: + getAgentIdentifier().toString()
2361: + "Inv Plugin[" + supplyType + "]"
2362: + "publish adding expansion: "
2363: + expansion.getUID() + " parent "
2364: + parent.getVerb() + " task is: "
2365: + parent.getUID());
2366: }
2367: }
2368: // Task already has expansion, add task to the workflow and publish the change
2369: else if (pe instanceof Expansion) {
2370: expansion = (Expansion) pe;
2371: wf = (NewWorkflow) expansion.getWorkflow();
2372: wf.addTask(subtask);
2373: ((NewTask) subtask).setWorkflow(wf);
2374: publishChange(expansion);
2375: if (logger.isDebugEnabled()) {
2376: logger.debug("Agent: "
2377: + getAgentIdentifier().toString()
2378: + "Inv Plugin[" + supplyType + "]"
2379: + "publish changing expansion: "
2380: + expansion.getUID() + " parent "
2381: + parent.getVerb() + " task is: "
2382: + parent.getUID());
2383: }
2384: } else {
2385: if (logger.isErrorEnabled()) {
2386: logger
2387: .error("publishAddToExpansion: problem pe not Expansion? "
2388: + pe);
2389: }
2390: }
2391:
2392: // Publish new task
2393: publishAdd(subtask);
2394: if (logger.isDebugEnabled()) {
2395: logger.debug("Agent: " + getAgentIdentifier().toString()
2396: + "Inv Plugin[" + supplyType + "]"
2397: + "publish adding a " + subtask.getVerb()
2398: + " subtask: " + subtask.getUID());
2399: }
2400:
2401: if (((subtask.getVerb().equals(Constants.Verb.SUPPLY)) || (subtask
2402: .getVerb().equals(Constants.Verb.PROJECTSUPPLY)))
2403: && (subtask.getPrepositionalPhrase("SplitTask") == null)) {
2404: newRefills.add(subtask);
2405: }
2406: }
2407:
2408: // called by the RefillGenerator to hook up the refill task to the maintain
2409: // inventory parent task and workflow.
2410: public boolean publishRefillTask(Task task, Inventory inventory) {
2411: Task milTask = detReqHandler.findOrMakeMILTask(inventory,
2412: aggMILSubscription);
2413: if (milTask != null) {
2414: publishAddToExpansion(milTask, task);
2415: return true;
2416: }
2417: return false;
2418: }
2419:
2420: public void disposeOfUnusedMILTask(Inventory inventory,
2421: boolean noRefills) {
2422: if (noRefills) {
2423: Task milTask = detReqHandler.findOrMakeMILTask(inventory,
2424: aggMILSubscription);
2425: // If the milTask couldn't be made - just return
2426: if (milTask == null) {
2427: return;
2428: }
2429: PlanElement pe = milTask.getPlanElement();
2430: // If the PlanElement is already a Disposition then do nothing
2431: if (!(pe instanceof Disposition)) {
2432: // If the PlanElement is not null then it is an expansion.
2433: // Only Remove expansion if there is nothing in the workflow.
2434: if (pe instanceof Expansion) {
2435: Enumeration tasks = ((Expansion) pe).getWorkflow()
2436: .getTasks();
2437: if (!tasks.hasMoreElements()) {
2438: publishRemove(pe);
2439: pe = null;
2440: }
2441: }
2442: if (pe == null) {
2443: // Create Disposition
2444: AllocationResultHelper helper = new AllocationResultHelper(
2445: milTask, null);
2446: AllocationResult dispAR = helper
2447: .getAllocationResult(
2448: Constants.Confidence.OBSERVED, true);
2449: Disposition disposition = getPlanningFactory()
2450: .createDisposition(milTask.getPlan(),
2451: milTask, dispAR);
2452: publishAdd(disposition);
2453: }
2454: }
2455: }
2456: }
2457:
2458: protected Organization getMyOrganization(Enumeration orgs) {
2459: Organization myOrg = null;
2460: // look for this organization
2461: if (orgs.hasMoreElements()) {
2462: myOrg = (Organization) orgs.nextElement();
2463: }
2464: return myOrg;
2465: }
2466:
2467: public long getOPlanStartTime() {
2468: return logOPlan.getStartTime();
2469: }
2470:
2471: public long getOPlanEndTime() {
2472: return logOPlan.getEndTime();
2473: }
2474:
2475: public long getOPlanArrivalInTheaterTime() {
2476: //Before the arrivalt time is updated in the log oplan
2477: //the default value is just the start time.
2478: if (logOPlan.getArrivalTime() == Long.MIN_VALUE) {
2479: if (logger.isErrorEnabled()) {
2480: logger
2481: .error("Asking for arrival time in theater, before it is known");
2482: }
2483: return startTime;
2484: } else {
2485: return logOPlan.getArrivalTime();
2486: }
2487: }
2488:
2489: public long getPrepoArrivalTime() {
2490: return getOPlanArrivalInTheaterTime()
2491: - (bucketSize * prepoArrivalOffset);
2492: }
2493:
2494: // public void getInventoryData() {
2495: // String invFile = getInventoryFileName();
2496: // if (invFile != null) {
2497: // Enumeration initialInv = FileUtils.readConfigFile(invFile, getConfigFinder());
2498: // if (initialInv != null) {
2499: // stashInventoryInformation(initialInv);
2500: // }
2501: // }
2502: // }
2503:
2504: // private void stashInventoryInformation(Enumeration initInv) {
2505: // String line;
2506: // String item = null;
2507: // double capacity, level;
2508:
2509: // while (initInv.hasMoreElements()) {
2510: // line = (String) initInv.nextElement();
2511: // // Find the fields in the line, values seperated by ','
2512: // Vector fields = FileUtils.findFields(line, ',');
2513: // if (fields.size() < 3)
2514: // continue;
2515: // item = (String) fields.elementAt(0);
2516: // capacity = Double.valueOf((String) fields.elementAt(1)).doubleValue();
2517: // level = Double.valueOf((String) fields.elementAt(2)).doubleValue();
2518: // double[] levels = {capacity, level};
2519: // inventoryInitHash.put(item, levels);
2520: // }
2521: // }
2522:
2523: protected Role getRole(String supply_type) {
2524: if (supply_type.equals("Ammunition"))
2525: return Constants.Role.AMMUNITIONPROVIDER;
2526: if (supply_type.equals("BulkPOL"))
2527: return Constants.Role.FUELSUPPLYPROVIDER;
2528: if (supply_type.equals("Consumable"))
2529: return Constants.Role.SPAREPARTSPROVIDER;
2530: if (supply_type.equals("PackagedPOL"))
2531: return Constants.Role.PACKAGEDPOLSUPPLYPROVIDER;
2532: if (supply_type.equals("Subsistence"))
2533: return Constants.Role.SUBSISTENCESUPPLYPROVIDER;
2534: if (logger.isErrorEnabled()) {
2535: logger.error("Unsupported Supply Type");
2536: }
2537: return null;
2538: }
2539:
2540: protected boolean updateInventoryPolicy(Collection policies) {
2541: InventoryPolicy pol;
2542: boolean changed = false;
2543: Iterator policy_iterator = policies.iterator();
2544: while (policy_iterator.hasNext()) {
2545: pol = (InventoryPolicy) policy_iterator.next();
2546: inventoryPolicy = pol;
2547: int cl = pol.getCriticalLevel();
2548: if ((cl >= 0) && (cl != criticalLevel)) {
2549: criticalLevel = cl;
2550: changed = true;
2551: }
2552: int rp = pol.getReorderPeriod();
2553: if ((rp >= 0) && (rp != reorderPeriod)) {
2554: reorderPeriod = rp;
2555: changed = true;
2556: }
2557: long bucket = pol.getBucketSize();
2558: if (bucket >= TimeUtils.MSEC_PER_HOUR) {
2559: bucketSize = bucket;
2560: changed = true;
2561: }
2562: boolean ftc = pol.getFillToCapacity();
2563: if (ftc != fillToCapacity) {
2564: fillToCapacity = ftc;
2565: changed = true;
2566: }
2567: }
2568: return changed;
2569: }
2570:
2571: public int getOrderShipTime() {
2572: return inventoryPolicy.getOrderShipTime();
2573: }
2574:
2575: public long getSupplierArrivalTime() {
2576: return inventoryPolicy.getSupplierArrivalTime();
2577: }
2578:
2579: public long getRefillStartTime() {
2580: return Math.max(getOPlanArrivalInTheaterTime(),
2581: getSupplierArrivalTime());
2582: }
2583:
2584: public int getMaxLeadTime() {
2585: return inventoryPolicy.getSupplierAdvanceNoticeTime()
2586: + getOrderShipTime();
2587: }
2588:
2589: public boolean getFillToCapacity() {
2590: return inventoryPolicy.getFillToCapacity();
2591: }
2592:
2593: public int getCriticalLevel() {
2594: return inventoryPolicy.getCriticalLevel();
2595: }
2596:
2597: /** VTH operating modes */
2598: protected OperatingMode level2Horizon, level6Horizon;
2599:
2600: /** create and publish VTH Operating Modes */
2601: protected void setupOperatingModes() {
2602: try {
2603: //getBlackboardService().openTransaction();
2604: OMCRange level2Range = new IntRange(LEVEL_2_MIN.intValue(),
2605: LEVEL_2_MAX.intValue());
2606: OMCRangeList rangeList = new OMCRangeList(level2Range);
2607: publishAdd(level2Horizon = new OperatingModeImpl(
2608: LEVEL_2_TIME_HORIZON + "_" + supplyType, rangeList,
2609: LEVEL_2_TIME_HORIZON_DEFAULT));
2610:
2611: OMCRange level6Range = new IntRange(LEVEL_6_MIN.intValue(),
2612: LEVEL_6_MAX.intValue());
2613: rangeList = new OMCRangeList(level6Range);
2614: publishAdd(level6Horizon = new OperatingModeImpl(
2615: LEVEL_6_TIME_HORIZON + "_" + supplyType, rangeList,
2616: LEVEL_6_TIME_HORIZON_DEFAULT));
2617: } catch (Exception e) {
2618: if (logger.isErrorEnabled()) {
2619: logger
2620: .error(
2621: ""
2622: + getMyOrganization()
2623: + " got exception creating operating modes.",
2624: e);
2625: }
2626: //} finally {
2627: //getBlackboardService().closeTransaction();
2628: }
2629:
2630: if (logger.isInfoEnabled()) {
2631: logger.info("" + getMyOrganization()
2632: + " created operating modes - "
2633: + "level 2 time horizon is " + level2Horizon
2634: + " and level 6 is " + level6Horizon);
2635: }
2636: }
2637:
2638: /** tiny helper class for VTH Operating Modes */
2639: protected static class IntRange extends OMCRange {
2640: public IntRange(int a, int b) {
2641: super (a, b);
2642: }
2643: }
2644:
2645: /** relative to now -- this is correct, isn't it? */
2646: protected long getEndOfLevelSix() {
2647: long now = currentTimeMillis();
2648: int days = ((Integer) level6Horizon.getValue()).intValue();
2649:
2650: return timeUtils.addNDays(now, days);
2651: }
2652:
2653: /** relative to now -- this is correct, isn't it? */
2654: public long getEndOfLevelTwo() {
2655: long now = currentTimeMillis();
2656: int days = ((Integer) level2Horizon.getValue()).intValue();
2657:
2658: return timeUtils.addNDays(now, days);
2659: }
2660:
2661: /** When one of our Refill tasks gets removed (Supply or ProjectSupply),
2662: * remove it from the BG list.
2663: * @param removedTasks The collection of removed refill tasks.
2664: **/
2665: public void handleRemovedRefills(Collection removedTasks) {
2666: Iterator removedIter = removedTasks.iterator();
2667: while (removedIter.hasNext()) {
2668: Task removed = (Task) removedIter.next();
2669: if (logger.isDebugEnabled()) {
2670: logger.debug("Agent: "
2671: + getAgentIdentifier().toString()
2672: + "Inv Plugin[" + supplyType + "]"
2673: + "processing removal of refill: "
2674: + removed.getUID());
2675: }
2676: String item = removed.getDirectObject()
2677: .getTypeIdentificationPG().getTypeIdentification();
2678: Inventory inventory = (Inventory) inventoryHash.get(item);
2679: LogisticsInventoryPG invPG = (LogisticsInventoryPG) inventory
2680: .searchForPropertyGroup(LogisticsInventoryPG.class);
2681: if (removed.getVerb().equals(Constants.Verb.SUPPLY)) {
2682: invPG.removeRefillRequisition(removed);
2683: } else {
2684: invPG.removeRefillProjection(removed);
2685: }
2686: if (removed.isDeleted()) {
2687: touchInventoryWithDeletions(inventory);
2688: } else {
2689: touchInventory(inventory);
2690: }
2691: }
2692: }
2693:
2694: public MessageAddress getClusterId() {
2695: return getAgentIdentifier();
2696: }
2697:
2698: public TaskScheduler getSupplyTaskScheduler() {
2699: return supplyTaskScheduler;
2700: }
2701:
2702: public Collection getCommStatusSubscription() {
2703: return commStatusSub;
2704: }
2705:
2706: public Collection getSupplyTasks() {
2707: return supplyTaskScheduler.getAllTasksCollection();
2708: }
2709:
2710: public Alarm addAlarm(long timeOut) {
2711: Alarm alarm = new CougTimeAlarm(timeOut);
2712: alarmService.addAlarm(alarm);
2713: return alarm;
2714: }
2715:
2716: public Alarm addRealTimeAlarm(long timeOut) {
2717: Alarm alarm = new CougTimeAlarm(timeOut);
2718: alarmService.addRealTimeAlarm(alarm);
2719: return alarm;
2720: }
2721:
2722: //
2723: protected void processDetReq(Collection addedDRs) {
2724: // with one oplan we should only have one DR for MI.
2725: Iterator drIt = addedDRs.iterator();
2726: if (drIt.hasNext()) {
2727: Task detReq = (Task) drIt.next();
2728: //synch on the detReq task so only one instance of this plugin
2729: // checks and creates a single agg task and then creates an
2730: // empty expansion (wf) for the maintain inventory for each item tasks
2731: synchronized (detReq) {
2732: if (detReq.getPlanElement() == null) {
2733: detReqHandler.createAggTask(addedDRs);
2734: }
2735: }
2736: }
2737: }
2738:
2739: // We only want to process inventories that we have no new refills for.
2740: protected Collection getActionableInventories() {
2741: ArrayList actionableInvs = new ArrayList(touchedInventories);
2742: Task refill;
2743: Asset asset;
2744: Inventory inventory;
2745: Iterator refillIt = newRefills.iterator();
2746: while (refillIt.hasNext()) {
2747: refill = (Task) refillIt.next();
2748: asset = (Asset) refill.getDirectObject();
2749: inventory = findOrMakeInventory(asset);
2750: actionableInvs.remove(inventory);
2751: }
2752: return actionableInvs;
2753: }
2754:
2755: protected void rebuildPGCustomerHash() {
2756: Collection changedInventories = getTouchedInventories();
2757: Iterator invIter = changedInventories.iterator();
2758: Inventory inventory;
2759: LogisticsInventoryPG thePG;
2760: while (invIter.hasNext()) {
2761: inventory = (Inventory) invIter.next();
2762: thePG = (LogisticsInventoryPG) inventory
2763: .searchForPropertyGroup(LogisticsInventoryPG.class);
2764: thePG.rebuildCustomerHash();
2765: }
2766: }
2767:
2768: protected boolean didOrgRelationshipsChange() {
2769: boolean relSchedChange = false;
2770: if (selfOrganizations.hasChanged()) {
2771: Set changeReports = selfOrganizations
2772: .getChangeReports(getMyOrganization());
2773:
2774: Iterator crits = changeReports.iterator();
2775: while (crits.hasNext()) {
2776: if (crits.next() instanceof RelationshipSchedule.RelationshipScheduleChangeReport) {
2777: relSchedChange = true;
2778: break;
2779: }
2780: }
2781: }
2782: return relSchedChange;
2783: }
2784:
2785: // get the first day in theater
2786: public long getLogOPlanStartTime() {
2787: return logOPlan.getStartTime();
2788: }
2789:
2790: // get the last day in theater
2791: public long getLogOPlanEndTime() {
2792: return logOPlan.getEndTime();
2793: }
2794:
2795: protected AllocatorModule getAllocatorModule() {
2796: return new ExternalAllocator(this , getRole(supplyType));
2797: }
2798:
2799: protected RefillGeneratorModule getRefillGeneratorModule() {
2800: return new RefillGenerator(this );
2801: }
2802:
2803: protected RefillProjectionGeneratorModule getRefillProjectionGeneratorModule() {
2804: return new RefillProjectionGenerator(this , this );
2805: }
2806:
2807: protected ComparatorModule getComparatorModule() {
2808: String comparatorClass = (String) pluginParams
2809: .get("COMPARATOR");
2810: if (comparatorClass == null) {
2811: return new DiffBasedComparator(this );
2812: } else {
2813: if (comparatorClass.indexOf('.') == -1) {
2814: comparatorClass = "org.cougaar.logistics.plugin.inventory."
2815: + comparatorClass;
2816: }
2817: try {
2818: Class[] paramTypes = { this .getClass() };
2819: Object[] initArgs = { this };
2820: Class cls = Class.forName(comparatorClass);
2821: Constructor constructor = cls
2822: .getConstructor(paramTypes);
2823: ComparatorModule comparator = (ComparatorModule) constructor
2824: .newInstance(initArgs);
2825: if (logger.isInfoEnabled())
2826: logger.info("Using comparator " + comparatorClass);
2827: return comparator;
2828: } catch (Exception e) {
2829: logger
2830: .error(e
2831: + " Unable to create Expander instance of "
2832: + comparatorClass
2833: + ". "
2834: + "Loading default org.cougaar.logistics.plugin.inventory.DiffBasedComparator");
2835: }
2836: }
2837: return new RefillComparator(this );
2838: }
2839:
2840: protected ExpanderModule getExpanderModule() {
2841: ExpanderModule em;
2842: String expanderClass = (String) pluginParams.get("EXPANDER");
2843: if (expanderClass == null) {
2844: em = new SupplyExpander(this );
2845: } else {
2846: if (expanderClass.indexOf('.') == -1) {
2847: expanderClass = "org.cougaar.logistics.plugin.inventory."
2848: + expanderClass;
2849: }
2850: try {
2851: Class[] paramTypes = { this .getClass() };
2852: Object[] initArgs = { this };
2853: Class cls = Class.forName(expanderClass);
2854: Constructor constructor = cls
2855: .getConstructor(paramTypes);
2856: em = (ExpanderModule) constructor.newInstance(initArgs);
2857: } catch (Exception e) {
2858: logger
2859: .error(e
2860: + " Unable to create Expander instance of "
2861: + expanderClass
2862: + ". "
2863: + "Loading default org.cougaar.logistics.plugin.inventory.SupplyExpander");
2864: em = new SupplyExpander(this );
2865: }
2866: }
2867: if (logger.isInfoEnabled()) {
2868: expanderClass = em.getClass().toString();
2869: logger.info("Using expander " + expanderClass);
2870: }
2871: return em;
2872: }
2873:
2874: public void updateStartAndEndTimes() {
2875: if (logOPlan != null) {
2876: if (!orgActSubscription.isEmpty()) {
2877: logOPlan.updateOrgActivities(orgActSubscription);
2878: }
2879: }
2880: }
2881:
2882: public long getNextLegalRefillTime(long today) {
2883: TimeSpanSet orderedOrgActs = new TimeSpanSet(orgActSubscription);
2884: Iterator orgActIt = orderedOrgActs.iterator();
2885: boolean findNext = false;
2886: while (orgActIt.hasNext()) {
2887: OrgActivity orgAct = (OrgActivity) orgActIt.next();
2888: boolean legalOrg = ((!(orgAct.getActivityType()
2889: .equals(orgAct.DEPLOYMENT))) && (!(orgAct
2890: .getActivityType().equals("Transit"))));
2891: if ((orgAct.getStartTime() <= today)
2892: && (orgAct.getEndTime() >= today)) {
2893: if (legalOrg) {
2894: return today;
2895: } else {
2896: findNext = true;
2897: }
2898: }
2899: if (findNext && legalOrg) {
2900: return orgAct.getStartTime();
2901: }
2902: }
2903:
2904: if (!findNext) {
2905: return today;
2906: } else {
2907: return logOPlan.getEndTime();
2908: }
2909: }
2910:
2911: /**
2912: Self-Test
2913: **/
2914: public void automatedSelfTest() {
2915: if (logger.isErrorEnabled()) {
2916: if (supplyType == null)
2917: logger.error("No SupplyType Plugin parameter.");
2918: // if (inventoryFile == null) logger.error("No Inventory File Plugin parameter.");
2919: // if (inventoryInitHash.isEmpty()) {
2920: // logger.error("No initial inventory information. Inventory File is empty or non-existant.");
2921: // logger.error("Could not find Inventory file : " + inventoryFile);
2922: // }
2923: if (detReqHandler
2924: .getDetermineRequirementsTask(aggMILSubscription) == null)
2925: logger
2926: .error("Missing DetermineRequirements for MaintainInventory task.");
2927: if (logOPlan == null)
2928: logger
2929: .error("Missing LogisticsOPlan object. Is the LogisticsOPlanPlugin loaded?");
2930: if (myOrganization == null)
2931: logger.error("Missing myorganization");
2932: logger.error("Critical Level is " + criticalLevel);
2933: logger.error("Reorder Period is " + reorderPeriod);
2934: logger.error("Days per bucket is " + bucketSize);
2935: }
2936: }
2937:
2938: protected final class CougTimeAlarm implements Alarm {
2939: private long expirationTime;
2940: private boolean expired = false;
2941:
2942: public CougTimeAlarm(long expiration) {
2943: this .expirationTime = expiration;
2944: }
2945:
2946: public long getExpirationTime() {
2947: return expirationTime;
2948: }
2949:
2950: public synchronized void expire() {
2951: if (!expired) {
2952: expired = true;
2953: BlackboardService bb = getBlackboardService();
2954: if (bb != null) {
2955: bb.signalClientActivity();
2956: } else {
2957: if (logger != null && logger.isWarnEnabled()) {
2958: logger
2959: .warn("Alarm to trigger at "
2960: + (new Date(expirationTime))
2961: + " has expired,"
2962: + " but the blackboard service is null. Plugin "
2963: + " model state is "
2964: + getModelState());
2965: }
2966: }
2967: }
2968: }
2969:
2970: public synchronized boolean hasExpired() {
2971: return expired;
2972: }
2973:
2974: public synchronized boolean cancel() {
2975: boolean was = expired;
2976: expired = true;
2977: return was;
2978: }
2979: }
2980:
2981: protected void testBG() {
2982: Iterator inv_it = inventoryHash.values().iterator();
2983: Inventory inv;
2984: LogisticsInventoryPG logInvPG = null;
2985: cycleStamp = (new Date()).getTime();
2986: while (inv_it.hasNext()) {
2987: inv = (Inventory) inv_it.next();
2988: if (logger.isErrorEnabled()) {
2989: logger.error("***"
2990: + inv.getItemIdentificationPG()
2991: .getItemIdentification());
2992: }
2993: logInvPG = (LogisticsInventoryPG) inv
2994: .searchForPropertyGroup(LogisticsInventoryPG.class);
2995: logInvPG.takeSnapshot(inv);
2996: if (logToCSV) {
2997: logInvPG.logAllToCSVFile(cycleStamp);
2998: }
2999: logInvPG.Test();
3000: }
3001: }
3002:
3003: }
|