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:
027: package org.cougaar.logistics.ldm.asset;
028:
029: import org.cougaar.core.service.LoggingService;
030: import org.cougaar.glm.ldm.asset.PackagePG;
031: import org.cougaar.glm.ldm.oplan.OrgActivity;
032: import org.cougaar.glm.ldm.plan.ObjectScheduleElement;
033: import org.cougaar.logistics.ldm.ClassIConsumerPrototypeProvider;
034: import org.cougaar.logistics.ldm.policy.FeedingPolicy;
035: import org.cougaar.logistics.plugin.inventory.LogisticsOPlan;
036: import org.cougaar.logistics.plugin.utils.FeedingPolicyPred;
037: import org.cougaar.logistics.plugin.utils.LogisticsOPlanPredicate;
038: import org.cougaar.logistics.plugin.utils.MilitaryPersonPred;
039: import org.cougaar.logistics.plugin.utils.OrgActivityPred;
040: import org.cougaar.planning.ldm.asset.AggregateAsset;
041: import org.cougaar.planning.ldm.asset.Asset;
042: import org.cougaar.planning.ldm.asset.PGDelegate;
043: import org.cougaar.planning.ldm.asset.PropertyGroup;
044: import org.cougaar.planning.ldm.measure.CountRate;
045: import org.cougaar.planning.ldm.measure.Rate;
046: import org.cougaar.planning.ldm.plan.Schedule;
047: import org.cougaar.planning.ldm.policy.KeyRuleParameterEntry;
048: import org.cougaar.planning.ldm.policy.RangeRuleParameter;
049: import org.cougaar.planning.ldm.policy.RangeRuleParameterEntry;
050: import org.cougaar.util.TimeSpan;
051: import org.cougaar.util.UnaryPredicate;
052:
053: import java.math.BigDecimal;
054: import java.util.ArrayList;
055: import java.util.Collection;
056: import java.util.Enumeration;
057: import java.util.HashMap;
058: import java.util.Iterator;
059: import java.util.List;
060: import java.util.Vector;
061:
062: public class SubsistenceConsumerBG extends ConsumerBG {
063:
064: public static HashMap cachedDBValues = new HashMap();
065: protected SubsistenceConsumerPG myPG;
066: transient ClassIConsumerPrototypeProvider parentPlugin;
067: String supplyType = "Subsistence";
068: private transient LoggingService logger;
069: private LogisticsOPlan logOPlan = null;
070: private Collection consumedItems = null;
071: private FeedingPolicy feedingPolicy = null;
072: private final static String BOTTLED_WATER = "NSN/8960013687383";
073: private final static String FRESH_FRUITS = "NSN/891501F768439";
074: private final static String FRESH_VEGETABLES = "NSN/891500V264926";
075:
076: public SubsistenceConsumerBG(SubsistenceConsumerPG pg) {
077: myPG = pg;
078: }
079:
080: public void initialize(ClassIConsumerPrototypeProvider plugin) {
081: parentPlugin = plugin;
082: logger = parentPlugin.getLoggingService(this );
083: }
084:
085: public List getPredicates() {
086: ArrayList predList = new ArrayList();
087: predList.add(new OrgActivityPred());
088: predList.add(new LogisticsOPlanPredicate());
089: predList.add(new FeedingPolicyPred(myPG.getService()));
090: return predList;
091: }
092:
093: public Schedule getParameterSchedule(Collection col, TimeSpan span) {
094: Schedule paramSchedule = null;
095: Vector params = new Vector();
096: Iterator predList = col.iterator();
097: UnaryPredicate predicate;
098: // DEBUG
099: // String myOrgName = parentPlugin.getMyOrg().getItemIdentificationPG().getItemIdentification();
100: // if (myOrgName.indexOf("35-ARBN") >= 0) {
101: // System.out.println("getParamSched() Asset is "+
102: // myPG.getMei().getTypeIdentificationPG().getTypeIdentification());
103: // }
104: ArrayList consumerlist = new ArrayList();
105: consumerlist.add(myPG.getMei());
106: Schedule consumerSched = parentPlugin.getScheduleUtils()
107: .createConsumerSchedule(consumerlist);
108: consumerSched = parentPlugin.getScheduleUtils()
109: .convertQuantitySchedule(consumerSched);
110: params.add(parentPlugin.getScheduleUtils().trimObjectSchedule(
111: consumerSched, span));
112: while (predList.hasNext()) {
113: Iterator list = ((Collection) predList.next()).iterator();
114: predicate = (UnaryPredicate) list.next();
115: if (predicate instanceof OrgActivityPred) {
116: Collection orgColl = (Collection) list.next();
117: if ((orgColl == null) || (orgColl.isEmpty())) {
118: return null;
119: }
120: Schedule orgActSched = parentPlugin.getScheduleUtils()
121: .createOrgActivitySchedule(orgColl);
122: params.add(parentPlugin.getScheduleUtils()
123: .trimObjectSchedule(orgActSched, span));
124: // if (myOrgName.indexOf("35-ARBN") >= 0) {
125: // System.out.println("getParamSched() OrgActSched "+orgActSched);
126: // }
127: } else if (predicate instanceof LogisticsOPlanPredicate) {
128: Collection oplanColl = (Collection) list.next();
129: if ((oplanColl == null) || (oplanColl.isEmpty())) {
130: return null;
131: }
132: Iterator it = oplanColl.iterator();
133: if (it.hasNext()) {
134: logOPlan = (LogisticsOPlan) it.next();
135: }
136: } else if (predicate instanceof FeedingPolicyPred) {
137: Collection fpColl = (Collection) list.next();
138: if ((fpColl == null) || (fpColl.isEmpty())) {
139: return null;
140: }
141: Iterator it = fpColl.iterator();
142: Schedule sched;
143: if (it.hasNext()) {
144: feedingPolicy = (FeedingPolicy) it.next();
145: sched = getFeedingPolicySchedule(feedingPolicy);
146: params.add(parentPlugin.getScheduleUtils()
147: .trimObjectSchedule(sched, span));
148: sched = getEnhancementPolicySchedule(feedingPolicy);
149: params.add(parentPlugin.getScheduleUtils()
150: .trimObjectSchedule(sched, span));
151: sched = getWaterPolicySchedule(feedingPolicy);
152: params.add(parentPlugin.getScheduleUtils()
153: .trimObjectSchedule(sched, span));
154: }
155: } else {
156: if (logger.isErrorEnabled()) {
157: logger
158: .error("getParameterSchedule: unknown predicate "
159: + predicate);
160: }
161: }
162: }
163: paramSchedule = parentPlugin.getScheduleUtils()
164: .getMergedSchedule(params);
165: return paramSchedule;
166: }
167:
168: private HashMap addWater(HashMap water, String key, Double value) {
169: water.put(key, value);
170: return water;
171: }
172:
173: private HashMap addEnhancements(HashMap enhance, String[] nsn_keys,
174: int j, FeedingPolicy fp) {
175: KeyRuleParameterEntry[] keys = fp.getEnhancementsKeys(j);
176: for (int i = 0; i < keys.length; i++) {
177: enhance.put(nsn_keys[i], new Double(keys[i].getValue()));
178: }
179: return enhance;
180: }
181:
182: protected Schedule getFeedingPolicySchedule(FeedingPolicy fp) {
183: Vector sched_els = new Vector();
184: ObjectScheduleElement ose;
185: long start, end;
186: ObjectScheduleElement element;
187: Vector mealsSched = createMealAndSupplementSchedule(fp);
188: for (int i = 0; i < mealsSched.size(); i++) {
189: ose = (ObjectScheduleElement) mealsSched.elementAt(i);
190: // e.g., min = 0 then start is C + 0 or C - Day of the operation
191: // e.g., min = 1 then start is C + 1 or 2nd day of the operation
192: start = parentPlugin.getTimeUtils().addNDays(
193: logOPlan.getStartTime(), (int) ose.getStartTime());
194: end = parentPlugin.getTimeUtils()
195: .addNDays(
196: start,
197: ((int) ose.getEndTime()
198: - (int) ose.getStartTime() + 1));
199: element = new ObjectScheduleElement(start, end, ose
200: .getObject());
201: sched_els.addElement(element);
202: start = end;
203: }
204: return parentPlugin.getScheduleUtils().newObjectSchedule(
205: sched_els.elements());
206: }
207:
208: protected Schedule getWaterPolicySchedule(FeedingPolicy fp) {
209: Vector sched_els = new Vector(0);
210: if (fp != null) {
211: RangeRuleParameterEntry[] waterRanges = fp
212: .getWaterPolicyRanges();
213: ObjectScheduleElement element;
214: long start, end;
215: // e.g., min = 0 then start is C + 0 or C - Day of the operation
216: // e.g., min = 1 then start is C + 1 or 2nd day of the operation
217: if (waterRanges.length > 0) {
218: start = parentPlugin.getTimeUtils().addNDays(
219: logOPlan.getStartTime(),
220: waterRanges[0].getRangeMin());
221: for (int i = 0; i < waterRanges.length; i++) {
222: end = parentPlugin
223: .getTimeUtils()
224: .addNDays(
225: start,
226: (waterRanges[i].getRangeMax()
227: - waterRanges[i]
228: .getRangeMin() + 1));
229: KeyRuleParameterEntry[] keys = fp
230: .getRangeKeys(waterRanges[i]);
231: element = new ObjectScheduleElement(start, end,
232: addWater(new HashMap(), BOTTLED_WATER,
233: new Double(keys[0].getValue())));
234: sched_els.addElement(element);
235: start = end;
236: }
237: }
238: }// else feeding policy is null return empty schedule
239: return parentPlugin.getScheduleUtils().newObjectSchedule(
240: sched_els.elements());
241: }
242:
243: protected Schedule getEnhancementPolicySchedule(FeedingPolicy fp) {
244: Vector sched_els = new Vector(0);
245: String[] nsns = { FRESH_FRUITS, FRESH_VEGETABLES };
246: if (fp != null) {
247: RangeRuleParameterEntry[] eRanges = fp
248: .getEnhancementsPolicyRanges();
249: ObjectScheduleElement element;
250: long start, end;
251: // e.g., min = 0 then start is C + 0 or C - Day of the operation
252: // e.g., min = 1 then start is C + 1 or 2nd day of the operation
253: if (eRanges.length > 0) {
254: start = parentPlugin.getTimeUtils().addNDays(
255: logOPlan.getStartTime(),
256: eRanges[0].getRangeMin());
257: for (int i = 0; i < eRanges.length; i++) {
258: end = parentPlugin.getTimeUtils().addNDays(
259: start,
260: (eRanges[i].getRangeMax()
261: - eRanges[i].getRangeMin() + 1));
262: element = new ObjectScheduleElement(start, end,
263: addEnhancements(new HashMap(), nsns, i, fp));
264: sched_els.addElement(element);
265: start = end;
266: }
267: }
268: }// else feeding policy is null return empty schedule
269: return parentPlugin.getScheduleUtils().newObjectSchedule(
270: sched_els.elements());
271: }
272:
273: public Rate getRate(Asset asset, List params) {
274:
275: double quantity = 0; // people
276: // CDW
277: if (params.size() < 1) {
278: return null;
279: } // if
280: Object obj = params.get(0);
281: if (obj instanceof Double) {
282: quantity = ((Double) obj).doubleValue();
283: } else {
284: if (obj != null) {
285: if (logger.isDebugEnabled()) {
286: logger.debug("Bad param - expected quantity got "
287: + obj);
288: }
289: } // if
290: return null;
291: } // if
292: OrgActivity act = null;
293: obj = params.get(1);
294: if (obj instanceof OrgActivity) {
295: act = (OrgActivity) obj;
296: } else {
297: if (obj != null) {
298: if (logger.isDebugEnabled()) {
299: logger
300: .debug("Bad param - expected OrgActivity got "
301: + obj);
302: }
303: } // if
304: return null;
305: } // if
306:
307: KeyRuleParameterEntry[] keys = getActionPolicy(act
308: .getActivityType(), act.getOpTempo());
309: if ((keys != null) && (keys.length == 0)) {
310: return null;
311: } // if
312:
313: Rate result = null;
314: String identifier = parentPlugin.getAssetUtils()
315: .getAssetIdentifier(asset);
316:
317: PackagePG ppg = (PackagePG) asset
318: .searchForPropertyGroup(PackagePG.class);
319: if (ppg == null) {
320: if (logger.isErrorEnabled()) {
321: logger.error("No PackagePG on " + identifier);
322: }
323: }
324: //String type = null;
325: double resource_count = 0;
326:
327: if (keys != null) {
328: for (int j = 0; j < keys.length; j++) {
329: if ((keys[j].getKey().equalsIgnoreCase("Breakfast") && (keys[j]
330: .getValue().equals(identifier)))
331: || (keys[j].getKey().equalsIgnoreCase("Lunch") && (keys[j]
332: .getValue().equals(identifier)))
333: || (keys[j].getKey().equalsIgnoreCase("Dinner") && (keys[j]
334: .getValue().equals(identifier)))) {
335: resource_count += 1.0;
336: }
337: }
338: } else {
339: // keys from getActionPolicy was null
340:
341: // Optempo does not over rule
342: if (params.size() < 3) {
343: if (logger.isErrorEnabled()) {
344: logger
345: .error("Class I ose array in getRate() is missing element "
346: + 2 + " (meal)");
347: }
348: } else {
349: if (params.get(2) != null) {
350: if (logger.isDebugEnabled()) {
351: logger.debug(" meal params is " + params.get(2)
352: + " resource is " + identifier);
353: }
354: if (((HashMap) params.get(2))
355: .containsKey(identifier)) {
356: // Meals
357: resource_count += ((Double) ((HashMap) params
358: .get(2)).get(identifier)).doubleValue();
359: if (logger.isDebugEnabled()) {
360: logger.debug(identifier + " rate is "
361: + resource_count);
362: }
363: } // if
364: // DEBUG
365: else {
366: if (logger.isDebugEnabled()) {
367: logger.debug("No meal rates for "
368: + identifier);
369: }
370: }
371: } // if non null params(2)
372:
373: // Enhancements policy
374: if (params.size() >= 4 && params.get(3) != null) {
375: if (((HashMap) params.get(3))
376: .containsKey(identifier)) {
377: // Meals
378: resource_count += ((Double) ((HashMap) params
379: .get(3)).get(identifier)).doubleValue();
380: if (logger.isDebugEnabled()) {
381: logger.debug(" enhance params is "
382: + ((Double) ((HashMap) params
383: .get(3)).get(identifier))
384: .doubleValue());
385: }
386: }
387: }
388: } // if have at least thru params(3)
389: } // end of case for null keys
390:
391: // Water
392: if (params.size() < 5) {
393: if (logger.isErrorEnabled()) {
394: logger
395: .error("Class I ose array in getRate() is missing element "
396: + 5 + " water");
397: }
398: } else {
399: if (params.get(4) != null) {
400: if (((HashMap) params.get(4)).containsKey(identifier)) {
401: // water public static HashMap cachedDBValues = new HashMap();
402:
403: resource_count += ((Double) ((HashMap) params
404: .get(4)).get(identifier)).doubleValue();
405: if (logger.isDebugEnabled()) {
406: logger
407: .debug(" water params is "
408: + ((Double) ((HashMap) params
409: .get(4))
410: .get(identifier))
411: .doubleValue());
412: }
413: } // if
414: } // if
415: } // if
416:
417: if (resource_count > 0) {
418: double total = Math.ceil(resource_count
419: * (1.0 / ppg.getCountPerPack()) * quantity);
420: result = CountRate.newEachesPerDay(total);
421: RationPG rpg = (RationPG) asset
422: .searchForPropertyGroup(RationPG.class);
423: if (logger.isDebugEnabled()) {
424: logger.debug("\n THE rate is "
425: + CountRate.newEachesPerDay(total)
426: + " for asset " + identifier
427: + " the ration type is " + rpg.getRationType());
428: }
429: if (logger.isDebugEnabled()) {
430: logger.debug(" Unit of Issue is "
431: + ppg.getUnitOfIssue() + " count per pack"
432: + ppg.getCountPerPack());
433: }
434: } // if
435: return result;
436: } // getRate
437:
438: public Collection getConsumed() {
439: if (consumedItems == null) {
440: synchronized (cachedDBValues) {
441: Asset asset = myPG.getMei();
442: if (asset instanceof AggregateAsset) {
443: asset = ((AggregateAsset) asset).getAsset();
444: }
445: String typeId = asset.getTypeIdentificationPG()
446: .getTypeIdentification();
447: consumedItems = (Collection) cachedDBValues.get(typeId);
448: if (consumedItems == null) {
449: consumedItems = parentPlugin.generateRationList();
450: if (consumedItems.isEmpty()) {
451: if (logger.isDebugEnabled()) {
452: logger
453: .debug("getConsumed(): Database query returned EMPTY result set for "
454: + myPG.getMei()
455: + ", "
456: + supplyType);
457: }
458: } else {
459: cachedDBValues.put(typeId, consumedItems);
460: }
461: }
462: }
463: }
464: return consumedItems;
465: }
466:
467: public Collection getConsumed(int x) {
468: return getConsumed();
469: }
470:
471: public Collection getConsumed(int x, int y) {
472: return getConsumed();
473: }
474:
475: public PGDelegate copy(PropertyGroup pg) {
476: return null;
477: }
478:
479: private KeyRuleParameterEntry[] getActionPolicy(String activity,
480: String optempo) {
481: // This appears to happen sporadically.
482: if (feedingPolicy == null) {
483: if (logger.isErrorEnabled()) {
484: String myOrgName = null;
485: if (parentPlugin != null
486: && parentPlugin.getMyOrg() != null
487: && parentPlugin.getMyOrg()
488: .getItemIdentificationPG() != null)
489: myOrgName = parentPlugin.getMyOrg()
490: .getItemIdentificationPG()
491: .getItemIdentification();
492:
493: logger.error("Bug 2982: SubsistenceConsumerBG at Org "
494: + myOrgName + " got null feedingPolicy!",
495: new Throwable());
496: }
497: return null;
498: }
499:
500: RangeRuleParameterEntry[] rules = feedingPolicy.getRules();
501: RangeRuleParameter theRule = new RangeRuleParameter();
502: KeyRuleParameterEntry[] keys;
503: boolean found = false;
504: boolean flag = true;
505: int j = 0;
506: int i = 0;
507: while ((!found) && (i < rules.length)) {
508: theRule = (RangeRuleParameter) rules[i].getValue();
509: keys = feedingPolicy.getConditionKeys(theRule);
510: j = 0;
511: flag = true;
512: while (flag && (j < keys.length)) {
513: if ((!keys[j].getKey().equalsIgnoreCase("OrgActivity"))
514: && (!keys[j].getKey().equalsIgnoreCase(
515: "Optempo"))) {
516: flag = false;
517: } else {
518: if ((!keys[j].getValue().equalsIgnoreCase(activity))
519: && (!keys[j].getValue().equalsIgnoreCase(
520: optempo))) {
521: flag = false;
522: }
523: }
524: j++;
525: }
526: if (flag) {
527: found = true;
528: } else {
529: i++;
530: }
531: }
532: if (found) {
533: return feedingPolicy.getActionKeys(theRule);
534: }
535: return null;
536: }
537:
538: /**
539: * Get the mandatory supplements from the property group and create a map
540: * that contains the daily consumption rate for both the supplements
541: * and the meals for a given range.
542: * @param policy the feeding policy
543: * @return Vector of ObjectScheduleElements
544: */
545: private Vector createMealAndSupplementSchedule(FeedingPolicy policy) {
546: Vector sched_els = new Vector();
547: if (policy != null) {
548: RangeRuleParameterEntry[] mealRanges = policy
549: .getMealPolicyRanges();
550: ObjectScheduleElement element;
551: for (int i = 0; i < mealRanges.length; i++) {
552: element = new ObjectScheduleElement(mealRanges[i]
553: .getRangeMin(), mealRanges[i].getRangeMax(),
554: addMeals(new HashMap(), i, policy));
555: sched_els.addElement(element);
556: } // for
557: } // if
558: return sched_els;
559: } // createMealAndSupplementSchedule
560:
561: private HashMap addMeals(HashMap map, int j, FeedingPolicy p) {
562: RangeRuleParameterEntry[] meals; // bRanges, lRanges, dRanges;
563: meals = p.getMealPolicyRanges();
564: if (meals == null) {
565: return map;
566: } // if
567: KeyRuleParameterEntry[] keys = p.getRangeKeys(meals[j]);
568: String nsn;
569: for (int i = 0; i < keys.length; i++) {
570: nsn = keys[i].getValue().toString();
571: if (nsn != null && nsn.length() > 0) {
572: calculateConsumptionRate(map, nsn);
573: map = addSupplementRate(map, nsn);
574: } // if
575: } // for
576: return map;
577: } // addMeals
578:
579: private HashMap calculateConsumptionRate(HashMap m, String key) {
580: double rate = 0;
581: if (m.containsKey(key)) {
582: rate = ((Double) m.get(key)).doubleValue();
583: ++rate;
584: m.put(key, new Double(rate));
585: } else { // else first time in
586: m.put(key, new Double(++rate));
587: } // if
588: return m;
589: } // calculateConsumptionRate
590:
591: private HashMap addSupplementRate(HashMap m, String n) {
592: Asset item = parentPlugin.getPrototype(n);
593: if (item != null) {
594: RationPG rpg = (RationPG) item
595: .searchForPropertyGroup(RationPG.class);
596: HashMap supplements = rpg.getMandatorySupplement();
597: // System.JTEST.out.println (" the supplements list is " + supplements);
598: for (Iterator i = supplements.keySet().iterator(); i
599: .hasNext();) {
600: String nsn = (String) i.next();
601: m = calculateSupplementRate(m, nsn,
602: ((BigDecimal) supplements.get(nsn))
603: .doubleValue());
604: } // for
605: } // if
606: return m;
607: } // addSupplementRate
608:
609: private HashMap calculateSupplementRate(HashMap m, String key,
610: double value) {
611: if (m.containsKey(key)) {
612: value = value + ((Double) m.get(key)).doubleValue();
613: m.put(key, new Double(value));
614: } else {
615: m.put(key, new Double(value));
616: }
617: return m;
618: }
619: }
|