001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.glm.plugins.inventory;
027:
028: import org.cougaar.core.blackboard.CollectionSubscription;
029: import org.cougaar.core.blackboard.IncrementalSubscription;
030: import org.cougaar.glm.ldm.Constants;
031: import org.cougaar.glm.ldm.asset.Inventory;
032: import org.cougaar.glm.ldm.asset.InventoryPG;
033: import org.cougaar.glm.ldm.asset.NewInventoryPG;
034: import org.cougaar.glm.ldm.asset.ProjectionWeight;
035: import org.cougaar.glm.ldm.asset.ProjectionWeightImpl;
036: import org.cougaar.glm.ldm.asset.ScheduledContentPG;
037: import org.cougaar.glm.ldm.asset.SupplyClassPG;
038: import org.cougaar.glm.plugins.AssetUtils;
039: import org.cougaar.glm.plugins.FileUtils;
040: import org.cougaar.glm.plugins.GLMDecorationPlugin;
041: import org.cougaar.glm.plugins.TaskUtils;
042: import org.cougaar.planning.ldm.asset.Asset;
043: import org.cougaar.planning.ldm.plan.Aggregation;
044: import org.cougaar.planning.ldm.plan.AllocationResult;
045: import org.cougaar.planning.ldm.plan.AspectType;
046: import org.cougaar.planning.ldm.plan.AspectValue;
047: import org.cougaar.planning.ldm.plan.NewComposition;
048: import org.cougaar.planning.ldm.plan.NewMPTask;
049: import org.cougaar.planning.ldm.plan.NewTask;
050: import org.cougaar.planning.ldm.plan.Preference;
051: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
052: import org.cougaar.planning.ldm.plan.ScoringFunction;
053: import org.cougaar.planning.ldm.plan.Task;
054: import org.cougaar.planning.ldm.plan.Verb;
055: import org.cougaar.planning.plugin.util.PluginHelper;
056: import org.cougaar.util.Enumerator;
057: import org.cougaar.util.UnaryPredicate;
058:
059: import java.text.DateFormat;
060: import java.text.ParseException;
061: import java.text.SimpleDateFormat;
062: import java.util.Collection;
063: import java.util.Enumeration;
064: import java.util.GregorianCalendar;
065: import java.util.Hashtable;
066: import java.util.Iterator;
067: import java.util.Vector;
068:
069: public abstract class InventoryPlugin extends GLMDecorationPlugin {
070:
071: public void recordCustomerForTask(Task task) {
072: recordCustomer(taskConsumerName(task));
073: }
074:
075: private String taskConsumerName(Task task) {
076: PrepositionalPhrase pp = task
077: .getPrepositionalPhrase(Constants.Preposition.FOR);
078: if (pp == null) {
079: return "unknown consumer";
080: }
081: Object io = pp.getIndirectObject();
082: if (io instanceof String) {
083: return (String) io;
084: } else {
085: return "unknown consumer";
086: }
087: }
088:
089: public static class InventoryItemInfo {
090: public double[] levels;
091: public GregorianCalendar reportBase;
092: public int reportStepKind;
093:
094: public InventoryItemInfo(double[] levels,
095: GregorianCalendar reportBase, int reportStepKind) {
096: this .levels = levels;
097: this .reportBase = reportBase;
098: this .reportStepKind = reportStepKind;
099: }
100: }
101:
102: private static class InventoryTypeHashEntry {
103: Vector invBins = new Vector();
104: UnaryPredicate dueOutPredicate;
105: ProjectionWeight projectionWeight;
106: boolean fillToCapacity;
107: boolean maintainAtCapacity;
108:
109: public InventoryTypeHashEntry(UnaryPredicate predicate,
110: ProjectionWeight weight) {
111: dueOutPredicate = predicate;
112: projectionWeight = weight;
113: fillToCapacity = false;
114: maintainAtCapacity = false;
115: }
116: }
117:
118: public static class WithdrawTaskPredicate implements UnaryPredicate {
119: String supplyType_;
120:
121: public WithdrawTaskPredicate(String type) {
122: supplyType_ = type;
123: }
124:
125: public boolean execute(Object o) {
126: if (o instanceof Task) {
127: Task task = (Task) o;
128: if (task.getVerb().equals(Constants.Verb.WITHDRAW)
129: || task.getVerb().equals(
130: Constants.Verb.PROJECTWITHDRAW)) {
131: if (TaskUtils.isDirectObjectOfType(task,
132: supplyType_)
133: || TaskUtils.isTaskPrepOfType(task,
134: supplyType_)) {
135: // if (TaskUtils.getQuantity(task) > 0.0){
136: return true;
137: // }
138: }
139: }
140: }
141: return false;
142: }
143: }
144:
145: /** Subscription for aggregatable support requests. **/
146: private IncrementalSubscription detReqSubscription_;
147:
148: /** Subscription for the aggregated support request **/
149: private CollectionSubscription aggMILSubscription_;
150:
151: /** Subscription for the MIL tasks **/
152: private IncrementalSubscription milSubscription_;
153:
154: /** The aggMIL task found/created during the current transaction **/
155: private Task aggMILTask_ = null;
156:
157: // Hashtable - keys asset id (nsn), elements array of levels
158: // filled in from file during initialization. Used to create inventories as needed.
159: protected Hashtable inventoryInitHash_ = new Hashtable();
160:
161: /** key is type id, value is an Inventory */
162: // cleared in initInventories() and added to initInventories and publishInventories
163: private Hashtable inventoryHash_ = new Hashtable();
164: private Hashtable inventoryTypeHash_ = new Hashtable();
165: private Hashtable MILTaskHash_ = new Hashtable();
166:
167: // protected CollectionSubscription inventorySubscription_ = null;
168:
169: public InventoryPlugin() {
170: super ();
171: // setExecutionDelay(30000,30000);
172: }
173:
174: public synchronized void execute() {
175: String clusterId = "unitialized clusterId";
176: if (myOrganization_ != null) {
177: clusterId = myOrganization_.getClusterPG()
178: .getMessageAddress().toString();
179: }
180: aggMILTask_ = null;
181: if (detReqSubscription_.hasChanged()) {
182: aggregateDetermineRequirementsTasks(
183: (NewMPTask) getDetermineRequirementsTask(),
184: detReqSubscription_.getAddedList());
185: }
186: if (milSubscription_.hasChanged()) {
187: //Added tasks are handled at the time of creation
188: removeMILTasks(milSubscription_.getRemovedList());
189: }
190: super .execute();
191: }
192:
193: protected void setupSubscriptions() {
194: super .setupSubscriptions();
195: // inventorySubscription_ = (CollectionSubscription) subscribe(new InventoryPredicate());
196: aggMILSubscription_ = (CollectionSubscription) subscribe(
197: new AggMILPredicate(), false);
198: // Determine requirements task subscription
199: detReqSubscription_ = (IncrementalSubscription) subscribe(new DetInvReqPredicate());
200: milSubscription_ = (IncrementalSubscription) subscribe(new MILPredicate());
201: addInventories(query(new InventoryPredicate()));
202: addMILTasks(milSubscription_.elements());
203: }
204:
205: // Predicates
206:
207: /**
208: Passes Inventory assets that have a valied InventoryPG
209: **/
210: private static class InventoryPredicate implements UnaryPredicate {
211: public boolean execute(Object o) {
212: if (o instanceof Inventory) {
213: InventoryPG invpg = (InventoryPG) ((Inventory) o)
214: .getInventoryPG();
215: if (invpg != null) {
216: return true;
217: }
218: }
219: return false;
220: }
221: }
222:
223: /**
224: Passes DetermineRequirements tasks of type MaintainInventory.
225: **/
226: private static class DetInvReqPredicate implements UnaryPredicate {
227: public boolean execute(Object o) {
228: if (o instanceof Task) {
229: Task t = (Task) o;
230: if (t.getVerb().equals(
231: Constants.Verb.DETERMINEREQUIREMENTS)) {
232: return TaskUtils.isTaskOfType(t,
233: "MaintainInventory");
234: }
235: }
236: return false;
237: }
238: }
239:
240: /**
241: Selects the per-inventory MaintainInventory tasks.
242: **/
243: private static class MILPredicate implements UnaryPredicate {
244: public boolean execute(Object o) {
245: if (o instanceof Task) {
246: Task t = (Task) o;
247: if (t.getVerb()
248: .equals(Constants.Verb.MAINTAININVENTORY)) {
249: return t.getDirectObject() != null; // true if this is the agg task
250: }
251: }
252: return false;
253: }
254: }
255:
256: /**
257: Selects the aggregate MaintainInventory task
258: **/
259: private static class AggMILPredicate implements UnaryPredicate {
260: public boolean execute(Object o) {
261: if (o instanceof Task) {
262: Task t = (Task) o;
263: if (t.getVerb()
264: .equals(Constants.Verb.MAINTAININVENTORY)) {
265: return t.getDirectObject() == null; // true if this is not the agg task
266: }
267: }
268: return false;
269: }
270: }
271:
272: /**
273: Add some inventories to the inventoryHash_.
274: **/
275: private void addInventories(Collection inventories) {
276: for (Iterator i = inventories.iterator(); i.hasNext();) {
277: addInventory((Inventory) i.next());
278: }
279: }
280:
281: private void removeInventories(Enumeration inventories) {
282: while (inventories.hasMoreElements()) {
283: removeInventory((Inventory) inventories.nextElement());
284: }
285: }
286:
287: private void addInventory(Inventory inventory) {
288: addInventory(inventory, getInventoryType(inventory));
289: }
290:
291: private void addInventory(Inventory inventory, String item) {
292: inventoryHash_.put(item, inventory);
293: String assetType = getAssetType(inventory);
294: if (assetType == null) {
295: if (logger.isErrorEnabled()) {
296: logger.error("addInventory failed to add " + item);
297: }
298: } else {
299: getInventoryTypeHashEntry(assetType).invBins.add(inventory);
300: }
301: }
302:
303: private void removeInventory(Inventory inventory) {
304: removeInventory(inventory, getInventoryType(inventory));
305: }
306:
307: private void removeInventory(Inventory inventory, String item) {
308: inventoryHash_.remove(item);
309: String assetType = getAssetType(inventory);
310: if (assetType == null) {
311: if (logger.isErrorEnabled()) {
312: logger
313: .error("removeInventory failed to remove "
314: + item);
315: }
316: } else {
317: getInventoryTypeHashEntry(assetType).invBins
318: .remove(inventory);
319: }
320: }
321:
322: private void addMILTasks(Enumeration milTasks) {
323: while (milTasks.hasMoreElements()) {
324: Task task = (Task) milTasks.nextElement();
325: Inventory inventory = (Inventory) task.getDirectObject();
326: MILTaskHash_.put(inventory, task);
327: }
328: }
329:
330: private void removeMILTasks(Enumeration milTasks) {
331: boolean clear = false;
332:
333: while (milTasks.hasMoreElements()) {
334: Task task = (Task) milTasks.nextElement();
335: Inventory inventory = (Inventory) task.getDirectObject();
336: MILTaskHash_.remove(inventory);
337: clear = true;
338: }
339:
340: // clear the recorded customers if MaintainInventory has been rescinded
341: // ????? Should I wait until all mil tasks have been rescinded?
342: if (clear) {
343: clearRecordedCustomers();
344: }
345: }
346:
347: /**
348: Get _the_ aggregate MIL task. This is complicated because we
349: want to detect when the task has been deleted, but we only want
350: to create one of them. The lag between publishing a new task
351: and its appearance in the subscription poses a problem because,
352: typically, this method is called repeatedly in one transaction.
353: We store the task temporarily in a variable (aggMILTask_) to
354: prevent multiple creation, but clear the variable at the
355: beginning of each new transaction. If the task has not yet been
356: created, we try to create it by aggregating all the existing
357: per-oplan DetermineRequirements tasks into it. Subsequent
358: per-oplan tasks will be aggregated in as they arrive. There
359: will be no task if there are no DetermineRequirements tasks to
360: be aggregated.
361: **/
362: public Task getDetermineRequirementsTask() {
363: if (aggMILTask_ == null) {
364: if (!aggMILSubscription_.isEmpty()) {
365: aggMILTask_ = (Task) aggMILSubscription_.elements()
366: .nextElement();
367: } else if (!detReqSubscription_.isEmpty()) {
368: aggMILTask_ = createAggTask(detReqSubscription_
369: .elements());
370: publishAdd(aggMILTask_);
371: }
372: }
373: return aggMILTask_;
374: }
375:
376: /**
377: Aggregate some DetermineRequirements tasks
378: **/
379: private void aggregateDetermineRequirementsTasks(NewMPTask mpTask,
380: Enumeration e) {
381: if (!e.hasMoreElements())
382: return;
383: if (mpTask == null)
384: return;
385: NewComposition composition = (NewComposition) mpTask
386: .getComposition();
387: long minStartTime;
388: long maxEndTime;
389: try {
390: maxEndTime = TaskUtils.getEndTime(mpTask);
391: } catch (IllegalArgumentException iae) {
392: maxEndTime = Long.MIN_VALUE;
393: }
394: try {
395: minStartTime = TaskUtils.getStartTime(mpTask);
396: } catch (IllegalArgumentException iae) {
397: minStartTime = Long.MAX_VALUE;
398: }
399: while (e.hasMoreElements()) {
400: Task parent = (Task) e.nextElement();
401: if (parent.getPlanElement() != null)
402: continue; // Already aggregated
403: minStartTime = Math.min(minStartTime, TaskUtils
404: .getStartTime(parent));
405: maxEndTime = Math.max(maxEndTime, TaskUtils
406: .getEndTime(parent));
407: if (parent.getPlanElement() != null)
408: continue;
409: AllocationResult estAR = PluginHelper
410: .createEstimatedAllocationResult(parent, theLDMF,
411: 1.0, true);
412: Aggregation agg = theLDMF.createAggregation(parent
413: .getPlan(), parent, composition, estAR);
414: publishAdd(agg);
415: composition.addAggregation(agg);
416: }
417: setStartTimePreference(mpTask, minStartTime);
418: setEndTimePreference(mpTask, maxEndTime);
419: mpTask.setParentTasks(new Enumerator(composition
420: .getParentTasks()));
421: }
422:
423: private void setStartTimePreference(NewTask mpTask,
424: long newStartTime) {
425: ScoringFunction sf;
426: Preference pref;
427: sf = ScoringFunction.createStrictlyAtValue(AspectValue
428: .newAspectValue(AspectType.START_TIME, newStartTime));
429: pref = theLDMF.newPreference(AspectType.START_TIME, sf);
430: mpTask.setPreference(pref);
431: // mpTask.setCommitmentDate(new Date(newStartTime));
432:
433: }
434:
435: private void setEndTimePreference(NewTask mpTask, long newEndTime) {
436: ScoringFunction sf;
437: Preference pref;
438: sf = ScoringFunction.createStrictlyAtValue(AspectValue
439: .newAspectValue(AspectType.END_TIME, newEndTime));
440: pref = theLDMF.newPreference(AspectType.END_TIME, sf);
441: mpTask.setPreference(pref);
442: }
443:
444: /**
445: Find or make the aggregated MIL task for an inventory. If the
446: MILTaskHash_ does not contain an existing task, create a new
447: one and link it to the determine requirements tasks.
448: **/
449: public Task findOrMakeMILTask(Inventory inventory) {
450: // Creates the MaintainInventoryLevels Task for this item
451: // if one does not already exist
452: NewTask milTask = (NewTask) MILTaskHash_.get(inventory);
453: if (milTask == null) {
454: Task parent = getDetermineRequirementsTask();
455: if (parent == null) {
456: /**
457: This might happen just after the last determine
458: requirements task is removed. Because of inertia,
459: the inventory manager might still be trying to
460: refill the inventory although, in fact the demand
461: for that inventory is in the process of
462: disappearing. The caller, getting a null return will
463: simply abandon the attempt to do the refill.
464: **/
465: if (logger.isDebugEnabled()) {
466: logger
467: .debug("findOrMakeMILTask(), CANNOT CREATE MILTASK, no parent, inventory: "
468: + AssetUtils.assetDesc(inventory
469: .getScheduledContentPG()
470: .getAsset()));
471: }
472: return null; // Can't make one
473: }
474: milTask = createMILTask(parent, inventory);
475: publishAddToExpansion(parent, milTask);
476: MILTaskHash_.put(inventory, milTask);
477: }
478: return milTask;
479: }
480:
481: public synchronized Inventory findOrMakeInventory(
482: String supplytype, String id) {
483: if (id == null)
484: return null;
485: Asset resource = theLDMF.getPrototype(id);
486: if (resource == null) {
487: if (logger.isDebugEnabled()) {
488: logger
489: .debug("<"
490: + supplytype
491: + "> createInventory fail to get prototype for "
492: + id);
493: }
494: resource = theLDMF.createPrototype(supplytype, id);
495: }
496: if (resource == null) {
497: if (logger.isErrorEnabled()) {
498: logger
499: .error("<"
500: + supplytype
501: + "> createInventory fail to make prototype for "
502: + id);
503: }
504: return null;
505: }
506: return findOrMakeInventory(supplytype, resource);
507: }
508:
509: /**
510: Override this if you want to use a different predicate for selecting due out tasks
511: **/
512:
513: protected UnaryPredicate createDueOutPredicate(String supplyType) {
514: return new WithdrawTaskPredicate(supplyType);
515: }
516:
517: private InventoryTypeHashEntry getInventoryTypeHashEntry(
518: String supplyType) {
519: InventoryTypeHashEntry result = (InventoryTypeHashEntry) inventoryTypeHash_
520: .get(supplyType);
521: if (result == null) {
522: ProjectionWeight weight = createProjectionWeight(supplyType);
523: result = new InventoryTypeHashEntry(
524: createDueOutPredicate(supplyType), weight);
525: inventoryTypeHash_.put(supplyType, result);
526: }
527: return result;
528: }
529:
530: public ProjectionWeight getProjectionWeight(String supplyType) {
531: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
532: return entry.projectionWeight;
533: }
534:
535: /**
536: * Set the ProjectionWeight for a class of supply. This becomes
537: * the default ProjectionWeight for new Inventory Assets for the
538: * class of supply. The ProjectionWeight of existing Inventory
539: * assets is updated to the new ProjectionWeight. Override this if
540: * you don't want this behavior.
541: **/
542: public void setProjectionWeight(String supplyType,
543: ProjectionWeight weight) {
544: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
545: entry.projectionWeight = weight;
546: Enumeration e = entry.invBins.elements();
547: while (e.hasMoreElements()) {
548: Inventory inv = (Inventory) e.nextElement();
549: NewInventoryPG invpg = (NewInventoryPG) inv
550: .getInventoryPG();
551: invpg.setProjectionWeight(weight);
552: }
553: }
554:
555: /**
556: * Create a default ProjectWeight for a class of supply. This
557: * implementation creates a new ProjectionWeightImpl with default
558: * settings. Override this if you want a different default.
559: **/
560: protected ProjectionWeight createProjectionWeight(String supplyType) {
561: return new ProjectionWeightImpl();
562: }
563:
564: public boolean getFillToCapacity(String supplyType) {
565: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
566: return entry.fillToCapacity;
567: }
568:
569: /**
570: * Set the fillToCapacity for a class of supply. This becomes
571: * the default fillToCapacity for new Inventory Assets for the
572: * class of supply. The fillToCapacity of existing Inventory
573: * assets is updated to the new value (true/false). Override this if
574: * you don't want this behavior.
575: **/
576: public void setFillToCapacity(String supplyType,
577: boolean fill_to_capacity) {
578: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
579: entry.fillToCapacity = fill_to_capacity;
580: Enumeration e = entry.invBins.elements();
581: while (e.hasMoreElements()) {
582: Inventory inv = (Inventory) e.nextElement();
583: NewInventoryPG invpg = (NewInventoryPG) inv
584: .getInventoryPG();
585: invpg.setFillToCapacity(fill_to_capacity);
586: }
587: }
588:
589: public boolean getMaintainAtCapacity(String supplyType) {
590: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
591: return entry.maintainAtCapacity;
592: }
593:
594: /**
595: * Set the maintainAtCapacity for a class of supply. This becomes
596: * the default maintainAtCapacity for new Inventory Assets for the
597: * class of supply. The maintainAtCapacity of existing Inventory
598: * assets is updated to the new value (true/false). Override this if
599: * you don't want this behavior.
600: **/
601: public void setMaintainAtCapacity(String supplyType,
602: boolean maintain_at_capacity) {
603: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
604: entry.maintainAtCapacity = maintain_at_capacity;
605: Enumeration e = entry.invBins.elements();
606: while (e.hasMoreElements()) {
607: Inventory inv = (Inventory) e.nextElement();
608: NewInventoryPG invpg = (NewInventoryPG) inv
609: .getInventoryPG();
610: invpg.setMaintainAtCapacity(maintain_at_capacity);
611:
612: }
613: }
614:
615: public synchronized Inventory findOrMakeInventory(
616: String supplytype, Asset resource) {
617: Inventory inventory = null;
618: // only need to sync if each processor is running on its own thread.
619: // currently, ANTS is single-threaded but could easily be made multi-threaded.
620: String id = resource.getTypeIdentificationPG()
621: .getTypeIdentification();
622: inventory = (Inventory) inventoryHash_.get(id);
623: if (inventory == null) {
624: inventory = createInventory(supplytype, resource);
625: if (inventory != null) {
626: addInventory(inventory, id);
627: getDelegate().publishAdd(inventory);
628: if (logger.isDebugEnabled()) {
629: logger
630: .debug("findOrMakeInventory(), CREATED inventory bin for: "
631: + AssetUtils.assetDesc(inventory
632: .getScheduledContentPG()
633: .getAsset()));
634: }
635: findOrMakeMILTask(inventory);
636: }
637: }
638: return inventory;
639: }
640:
641: public final synchronized UnaryPredicate getDueOutPredicate(
642: String supplyType) {
643: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(supplyType);
644: return entry.dueOutPredicate;
645: }
646:
647: public abstract Inventory createInventory(String supplytype,
648: Asset resource);
649:
650: public String getInventoryType(Inventory inventory) {
651: ScheduledContentPG scp = inventory.getScheduledContentPG();
652: Asset proto = scp.getAsset();
653: if (proto == null) {
654: if (logger.isDebugEnabled()) {
655: logger
656: .debug("getInventoryType failed to get asset for "
657: + inventory.getScheduledContentPG()
658: .getAsset()
659: .getTypeIdentificationPG());
660: }
661: return "";
662: }
663: return proto.getTypeIdentificationPG().getTypeIdentification();
664: }
665:
666: public String getAssetType(Inventory inventory) {
667:
668: // Asset a = inventory.getScheduledContentPG().getAsset();
669: // String type = a.getClass().getName();
670: // type = type.substring(type.lastIndexOf('.')+1);
671: // return type;
672: InventoryPG invpg = (InventoryPG) inventory.getInventoryPG();
673: if (invpg == null)
674: return null;
675: Asset a = invpg.getResource();
676: if (a == null)
677: return null;
678: SupplyClassPG pg = (SupplyClassPG) a
679: .searchForPropertyGroup(SupplyClassPG.class);
680: return pg.getSupplyType();
681: }
682:
683: public Enumeration getInventoryBins(String assetType) {
684: InventoryTypeHashEntry entry = getInventoryTypeHashEntry(assetType);
685: return entry.invBins.elements();
686: }
687:
688: public void initializeInventoryFile(String type) {
689:
690: String invFile = getInventoryFile(type);
691: Enumeration initialInv = FileUtils.readConfigFile(invFile,
692: getConfigFinder());
693: if (initialInv != null) {
694: stashInventoryInformation(type, initialInv);
695: if (logger.isDebugEnabled()) {
696: logger
697: .debug("initializeInventory(), Inventory file is "
698: + invFile + " for " + type);
699: }
700: }
701: }
702:
703: private String getInventoryFile(String type) {
704: String result = null;
705: // if defined in plugin argument list
706: String inv_file = null;
707: if ((inv_file = (String) getParam(type + "_inv")) != null) {
708: result = inv_file;
709: } else {
710: result = getClusterSuffix(myOrganization_.getClusterPG()
711: .getMessageAddress().toString())
712: + "_" + type.toLowerCase() + ".inv";
713: }
714: return result;
715: }
716:
717: private String getClusterSuffix(String clusterId) {
718: String result = null;
719: int i = clusterId.lastIndexOf("-");
720: if (i == -1) {
721: result = clusterId;
722: } else {
723: result = clusterId.substring(i + 1);
724: }
725: return result;
726: }
727:
728: private static DateFormat dateTimeFormat = DateFormat
729: .getDateTimeInstance();
730:
731: static {
732: SimpleDateFormat sdf = (SimpleDateFormat) dateTimeFormat;
733: sdf.applyPattern("M/d/yyyy h:mm z");
734: }
735:
736: private GregorianCalendar parseDate(String s) {
737: try {
738: GregorianCalendar result = new GregorianCalendar();
739: result.setTime(dateTimeFormat.parse(s));
740: return result;
741: } catch (ParseException pe) {
742: pe.printStackTrace();
743: return null;
744: }
745: }
746:
747: private void stashInventoryInformation(String type,
748: Enumeration initInv) {
749: String line;
750: String item = null;
751: double capacity, level, erq, min_reorder;
752: GregorianCalendar reportBaseDate;
753: int reportStepKind;
754: int entries = 0;
755: if (logger.isDebugEnabled()) {
756: logger.debug("<" + type + "> Stashing inventories info...");
757: }
758:
759: while (initInv.hasMoreElements()) {
760: line = (String) initInv.nextElement();
761: // Find the fields in the line, values seperated by ','
762: Vector fields = FileUtils.findFields(line, ',');
763: if (fields.size() < 5)
764: continue;
765: item = (String) fields.elementAt(0);
766: capacity = Double.valueOf((String) fields.elementAt(1))
767: .doubleValue();
768: level = Double.valueOf((String) fields.elementAt(2))
769: .doubleValue();
770: erq = Double.valueOf((String) fields.elementAt(3))
771: .doubleValue();
772: min_reorder = Double.valueOf((String) fields.elementAt(4))
773: .doubleValue();
774: if (fields.size() < 7) {
775: reportBaseDate = null;
776: reportStepKind = 0;
777:
778: } else {
779: reportBaseDate = parseDate((String) fields.elementAt(5));
780: reportStepKind = Integer.parseInt((String) fields
781: .elementAt(6));
782: }
783: // GLMDebug.DEBUG("InventoryPlugin", clusterId_, "collected info for inventory item:"+
784: // item+" capacity:"+capacity+" level:"+level +" erq:"+erq+" min reorder:"+ min_reorder);
785: double[] levels = { capacity, level, erq, min_reorder };
786:
787: inventoryInitHash_.put(item, new InventoryItemInfo(levels,
788: reportBaseDate, reportStepKind));
789: entries++;
790: }
791: if (logger.isDebugEnabled()) {
792: logger.debug("stashInventory(), number of inventory bins: "
793: + entries + "for " + type);
794: }
795: }
796:
797: /**
798: Create a MaintainInventory task for an inventory. This task is
799: the parent of all refill tasks for the inventory and is itself
800: a subtask of the aggregated determine requirements tasks.
801: **/
802: private NewTask createMILTask(Task parent, Inventory inventory) {
803: NewTask subtask = theLDMF.newTask();
804: subtask.setDirectObject(inventory);
805: subtask.setParentTask(parent);
806: subtask.setVerb(Verb.get(Constants.Verb.MAINTAININVENTORY));
807: setStartTimePreference(subtask, TaskUtils.getStartTime(parent));
808: setEndTimePreference(subtask, TaskUtils.getEndTime(parent));
809: return subtask;
810: }
811:
812: /**
813: Create the aggregated determine requrements task. This task is
814: the parent of all the per-inventory MaintainInventory tasks.
815: It, too, uses the MaintainInventory verb but with no direct
816: object. It is an MPTask that combines all the
817: DetermineRequirements tasks of type MaintainInventory. The
818: Composition of this MPTask is non-propagating so it is
819: rescinded only if all the parent tasks are rescinded.
820: **/
821: private NewMPTask createAggTask(Enumeration parents) {
822: NewMPTask mpTask = theLDMF.newMPTask();
823: NewComposition composition = theLDMF.newComposition();
824: composition.setIsPropagating(false);
825: mpTask.setComposition(composition);
826: composition.setCombinedTask(mpTask);
827: mpTask.setVerb(Verb.get(Constants.Verb.MAINTAININVENTORY));
828: aggregateDetermineRequirementsTasks(mpTask, parents);
829: return mpTask;
830: }
831: }
|