001: /*--------------------------------------------------------------------------
002: * <copyright>
003: *
004: * Copyright 1999-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;
027:
028: import org.cougaar.glm.ldm.Constants;
029: import org.cougaar.glm.ldm.asset.SupplyClassPG;
030: import org.cougaar.glm.ldm.plan.AlpineAspectType;
031: import org.cougaar.planning.ldm.PlanningFactory;
032: import org.cougaar.planning.ldm.asset.AggregateAsset;
033: import org.cougaar.planning.ldm.asset.Asset;
034: import org.cougaar.planning.ldm.asset.TypeIdentificationPG;
035: import org.cougaar.planning.ldm.measure.CountRate;
036: import org.cougaar.planning.ldm.measure.FlowRate;
037: import org.cougaar.planning.ldm.measure.MassTransferRate;
038: import org.cougaar.planning.ldm.measure.Rate;
039: import org.cougaar.planning.ldm.plan.AllocationResult;
040: import org.cougaar.planning.ldm.plan.AspectRate;
041: import org.cougaar.planning.ldm.plan.AspectScorePoint;
042: import org.cougaar.planning.ldm.plan.AspectType;
043: import org.cougaar.planning.ldm.plan.AspectValue;
044: import org.cougaar.planning.ldm.plan.NewTask;
045: import org.cougaar.planning.ldm.plan.PlanElement;
046: import org.cougaar.planning.ldm.plan.Preference;
047: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
048: import org.cougaar.planning.ldm.plan.Priority;
049: import org.cougaar.planning.ldm.plan.ScoringFunction;
050: import org.cougaar.planning.ldm.plan.Task;
051: import org.cougaar.planning.plugin.util.PluginHelper;
052: import org.cougaar.util.MoreMath;
053: import org.cougaar.util.log.Logger;
054: import org.cougaar.util.log.Logging;
055:
056: import java.text.NumberFormat;
057: import java.util.Date;
058: import java.util.Enumeration;
059: import java.util.Vector;
060:
061: /**
062: * Provides convenience methods.
063: */
064: public class TaskUtils extends PluginHelper {
065: /**
066: * number of msec per day
067: */
068: // 86400000 msec/day = 1000msec/sec * 60sec/min *60min/hr * 24 hr/day
069: public static final long MSEC_PER_DAY = 86400000;
070: public static final NumberFormat demandFormat_ = getDemandFormat();
071: private static Logger logger = Logging.getLogger(TaskUtils.class);
072:
073: // TASK utils
074:
075: public static NumberFormat getDemandFormat() {
076: NumberFormat demandFormat = NumberFormat.getInstance();
077: demandFormat.setMaximumIntegerDigits(10);
078: demandFormat.setMinimumIntegerDigits(2);
079: demandFormat.setMinimumFractionDigits(2);
080: demandFormat.setMaximumFractionDigits(2);
081: demandFormat.setGroupingUsed(false);
082: return demandFormat;
083: }
084:
085: /**
086: * @param t the task
087: * @param type type identification string
088: * @return true if the task's OFTYPE preposition's indirect object is
089: * an asset with nomeclature equal to 'type'.
090: */
091: public static boolean isTaskOfType(Task t, String type) {
092: PrepositionalPhrase pp = t
093: .getPrepositionalPhrase(Constants.Preposition.OFTYPE);
094: if (pp != null) {
095: Object obj = pp.getIndirectObject();
096: if (obj instanceof Asset) {
097: Asset a = (Asset) obj;
098: return a.getTypeIdentificationPG()
099: .getTypeIdentification().equals(type);
100: }
101: }
102: return false;
103: }
104:
105: public static String getNameOfConsumedItem(Task task) {
106: Asset asset = task.getDirectObject();
107: // Check for aggregate assets and grab the prototype
108: if (asset instanceof Asset) {
109: return asset.getTypeIdentificationPG()
110: .getTypeIdentification();
111: } else {
112: return "Unknown";
113: }
114: }
115:
116: public static boolean isTaskPrepOfType(Task t, String type) {
117: PrepositionalPhrase pp = t
118: .getPrepositionalPhrase(Constants.Preposition.OFTYPE);
119: if (pp != null) {
120: Object obj = pp.getIndirectObject();
121: if (obj instanceof String) {
122: String s = (String) obj;
123: return s.equals(type);
124: }
125: }
126: return false;
127: }
128:
129: public static boolean isDirectObjectOfType(Task t, String type) {
130: boolean result = false;
131: Asset asset = t.getDirectObject();
132: // Check for aggregate assets and grab the prototype
133: if (asset instanceof AggregateAsset) {
134: asset = ((AggregateAsset) asset).getAsset();
135: }
136: try {
137: SupplyClassPG pg = (SupplyClassPG) asset
138: .searchForPropertyGroup(SupplyClassPG.class);
139: if (pg != null) {
140: result = type.equals(pg.getSupplyType());
141: } else {
142: if (logger.isDebugEnabled()) {
143: logger.debug("No SupplyClassPG found on asset "
144: + TaskUtils.taskDesc(t));
145: }
146: }
147: } catch (Exception e) {
148: if (logger.isErrorEnabled()) {
149: logger.error("Tasks DO is null "
150: + TaskUtils.taskDesc(t) + "\n" + e);
151: }
152: }
153: return result;
154: }
155:
156: public static boolean isMyRefillTask(Task task, String myOrgName) {
157: PrepositionalPhrase pp = task
158: .getPrepositionalPhrase(Constants.Preposition.REFILL);
159: if (pp == null) {
160: return false;
161: }
162: pp = task.getPrepositionalPhrase(Constants.Preposition.FOR);
163: if (pp == null) {
164: return false;
165: }
166: Object io = pp.getIndirectObject();
167: if (io instanceof String) {
168: String orgName = (String) io;
169: if (orgName.equals(myOrgName)) {
170: return true;
171: }
172: }
173: return false;
174: }
175:
176: public static boolean isMyInventoryProjection(Task task,
177: String myOrgName) {
178: PrepositionalPhrase pp = task
179: .getPrepositionalPhrase(Constants.Preposition.FOR);
180: if (pp == null) {
181: return false;
182: }
183: Object io = pp.getIndirectObject();
184: if (io instanceof String) {
185: String orgName = (String) io;
186: if (orgName.equals(myOrgName)) {
187: pp = task
188: .getPrepositionalPhrase(Constants.Preposition.MAINTAINING);
189: if (pp != null) {
190: try {
191: if (((MaintainedItem) pp.getIndirectObject())
192: .getMaintainedItemType().equals(
193: "Inventory")) {
194: return true;
195: }
196: } catch (ClassCastException exc) {
197: return false;
198: }
199: }
200: }
201: }
202: return false;
203: }
204:
205: public static String taskDesc(Task task) {
206: return "[ " + task.getUID() + " "
207: + PublicationKey.getTotalTaskKey(task)
208: // +" "+
209: // task.getVerb()+"("+
210: // demandFormat_.format(TaskUtils.getQuantity(task))+" "+
211: // getTaskItemName(task)+") "+
212: // TimeUtils.dateString(TaskUtils.getEndTime(task))+"]"
213: ;
214: }
215:
216: public static String shortTaskDesc(Task task) {
217: String typeID = null;
218: Object o = task.getDirectObject();
219: if (o instanceof Asset) {
220: TypeIdentificationPG typePG = ((Asset) o)
221: .getTypeIdentificationPG();
222: if (typePG != null) {
223: typeID = typePG.getTypeIdentification();
224: }
225: }
226: return task.getUID() + "[" + task.getVerb() + "; " + typeID
227: + "; "
228: + demandFormat_.format(TaskUtils.getQuantity(task))
229: + "; "
230: + TimeUtils.dateString(TaskUtils.getEndTime(task))
231: + "]";
232: }
233:
234: public static String projectionDesc(Task task) {
235: return task.getUID() + "[ Start:"
236: + TimeUtils.dateString(TaskUtils.getStartTime(task))
237: + " End:"
238: + TimeUtils.dateString(TaskUtils.getEndTime(task))
239: + " Rate:" + TaskUtils.getRate(task) + " ]";
240: }
241:
242: public static String getTaskItemName(Task task) {
243: Asset prototype = (Asset) task.getDirectObject();
244: if (prototype == null)
245: return "null";
246: return AssetUtils.assetDesc(prototype);
247: }
248:
249: public static String getDirectObjectID(Task task) {
250: return task.getDirectObject().getTypeIdentificationPG()
251: .getTypeIdentification();
252: }
253:
254: /**
255: * Compare the preferences of two tasks return true if the tasks
256: * have preferences for the same aspect types and if all
257: * corresponding AspectValues are nearly equal.
258: * This needs to be fixed to be more efficient.
259: */
260: public static boolean comparePreferences(Task a, Task b) {
261: return comparePreferencesInner(a, b)
262: && comparePreferencesInner(b, a);
263: }
264:
265: private static boolean comparePreferencesInner(Task a, Task b) {
266: Enumeration ae = a.getPreferences();
267: while (ae.hasMoreElements()) {
268: Preference p = (Preference) ae.nextElement();
269: int at = p.getAspectType();
270: double av = p.getScoringFunction().getBest().getValue();
271: double bv = getPreferenceBestValue(b, at);
272: if (!MoreMath.nearlyEquals(av, bv, 0.0001))
273: return false;
274: }
275: return true;
276: }
277:
278: public static String getPriority(Task task) {
279: byte priority = task.getPriority();
280: switch (priority) {
281: case Priority.VERY_HIGH:
282: return "1";
283: case Priority.HIGH:
284: return "3";
285: case Priority.MEDIUM:
286: return "5";
287: case Priority.LOW:
288: return "7";
289: case Priority.VERY_LOW:
290: return "9";
291: }
292: return "1"; // default to high priority
293: }
294:
295: public static int getNumericPriority(Task task) {
296: byte priority = task.getPriority();
297: switch (priority) {
298: case Priority.VERY_HIGH:
299: return 1;
300: case Priority.HIGH:
301: return 3;
302: case Priority.MEDIUM:
303: return 5;
304: case Priority.LOW:
305: return 7;
306: case Priority.VERY_LOW:
307: return 9;
308: }
309: return 1; // default to high priority
310: }
311:
312: // TASK PREFERENCE UTILS
313:
314: public static double getQuantity(Task task) {
315: return getPreferenceBestValue(task, AspectType.QUANTITY);
316: }
317:
318: public static Rate getRate(Task task) {
319: AspectValue best = getPreferenceBest(task,
320: AlpineAspectType.DEMANDRATE);
321: if (best == null)
322: if (logger.isErrorEnabled()) {
323: logger.error("getRate(), Task is not Projection :"
324: + taskDesc(task));
325: }
326: return ((AspectRate) best).getRateValue();
327: }
328:
329: public static double getDailyQuantity(Task task) {
330: if (isProjection(task)) {
331: return getDailyQuantity(getRate(task));
332: } else {
333: return getQuantity(task);
334: }
335: }
336:
337: public static double getDailyQuantity(Rate r) {
338: if (r instanceof FlowRate) {
339: return ((FlowRate) r).getGallonsPerDay();
340: } else if (r instanceof CountRate) {
341: return ((CountRate) r).getEachesPerDay();
342: } else if (r instanceof MassTransferRate) {
343: return ((MassTransferRate) r).getShortTonsPerDay();
344: } else {
345: return Double.NaN;
346: }
347: }
348:
349: public static double getMultiplier(Task task) {
350: AspectValue best = getPreferenceBest(task,
351: AlpineAspectType.DEMANDMULTIPLIER);
352: if (best == null)
353: if (logger.isErrorEnabled()) {
354: logger.error("getRate(), Task is not Projection :"
355: + taskDesc(task));
356: }
357: return best.getValue();
358: }
359:
360: public static double getRefillQuantity(Task refillTask) {
361: AllocationResult ar = getValidResult(refillTask);
362: if (ar != null) {
363: // if Estimated Result was successful then return AR Quantity, else return 0.0
364: if (ar.isSuccess())
365: return getQuantity(ar);
366: else
367: return 0.0;
368: }
369: // get requested results until actual results are available
370: return TaskUtils.getPreference(refillTask, AspectType.QUANTITY);
371: }
372:
373: public static double getWithdrawQuantity(Task withdrawTask) {
374: AllocationResult ar = getValidResult(withdrawTask);
375: if (ar != null) {
376: return getQuantity(ar);
377: }
378: // get requested results until actual results are available
379: return TaskUtils.getPreference(withdrawTask,
380: AspectType.QUANTITY);
381: }
382:
383: public static long getRefillTime(Task refillTask) {
384: AllocationResult ar = getValidResult(refillTask);
385: if (ar != null) {
386: return (long) getEndTime(ar);
387: } else {
388: // use requested results until actual results are valid
389: return TaskUtils.getEndTime(refillTask);
390: }
391: }
392:
393: public static Date getRefillDate(Task refillTask) {
394: return new Date(getRefillTime(refillTask));
395: }
396:
397: private static AllocationResult getValidResult(Task task) {
398: PlanElement pe = task.getPlanElement();
399: if (pe != null) {
400: AllocationResult ar = pe.getEstimatedResult();
401: if (ar != null) {
402: if (ar.getConfidenceRating() > 0.5) {
403: return ar;
404: }
405: }
406: }
407: return null;
408: }
409:
410: /**
411: * return the preference of the given aspect type. Returns null if
412: * the task does not have the given aspect.
413: */
414: public static double getPreference(Task t, int aspect_type) {
415: Preference p = t.getPreference(aspect_type);
416: if (p == null)
417: return Double.NaN;
418:
419: AspectScorePoint asp = p.getScoringFunction().getBest();
420: return asp.getValue();
421: }
422:
423: public static NewTask addPrepositionalPhrase(NewTask task,
424: PrepositionalPhrase pp) {
425: Enumeration en = task.getPrepositionalPhrases();
426: if (!en.hasMoreElements())
427: task.setPrepositionalPhrases(pp);
428: else {
429: Vector phrases = new Vector();
430: while (en.hasMoreElements()) {
431: phrases.addElement(en.nextElement());
432: }
433: phrases.addElement(pp);
434: task.setPrepositionalPhrases(phrases.elements());
435: }
436: return task;
437: }
438:
439: public static void replacePrepositionalPhrase(NewTask task,
440: PrepositionalPhrase pp) {
441: String prep = pp.getPreposition();
442: if (task.getPrepositionalPhrase(prep) == null) {
443: // its new, just add to the list
444: addPrepositionalPhrase(task, pp);
445: return;
446: }
447:
448: PrepositionalPhrase phrase;
449: Enumeration en = task.getPrepositionalPhrases();
450: Vector phrases = new Vector();
451: while (en.hasMoreElements()) {
452: phrase = (PrepositionalPhrase) en.nextElement();
453: if (!phrase.getPreposition().equals(prep)) {
454: phrases.addElement(phrase);
455: }
456: }
457: phrases.addElement(pp);
458: task.setPrepositionalPhrases(phrases.elements());
459: }
460:
461: public static double getQuantity(AllocationResult ar) {
462: return getARAspectValue(ar, AspectType.QUANTITY);
463: }
464:
465: public static String arDesc(AllocationResult ar) {
466: return "(AR: "
467: + (long) ar.getValue(AspectType.QUANTITY)
468: + "; "
469: + TimeUtils.dateString((long) ar
470: .getValue(AspectType.START_TIME))
471: + ","
472: + TimeUtils.dateString((long) ar
473: .getValue(AspectType.END_TIME)) + ")";
474: }
475:
476: public static boolean isProjection(Task t) {
477: return t.getPreference(AlpineAspectType.DEMANDRATE) != null;
478: }
479:
480: public static boolean isSupply(Task t) {
481: return !isProjection(t);
482: }
483:
484: public static Preference createDemandRatePreference(
485: PlanningFactory rf, Rate rate) {
486: ScoringFunction sf = ScoringFunction
487: .createStrictlyAtValue(AspectValue.newAspectValue(
488: AlpineAspectType.DEMANDRATE, rate));
489: return rf.newPreference(AlpineAspectType.DEMANDRATE, sf);
490: }
491:
492: public static Preference createDemandMultiplierPreference(
493: PlanningFactory rf, double mult) {
494: ScoringFunction sf = ScoringFunction
495: .createStrictlyAtValue(AspectValue.newAspectValue(
496: AlpineAspectType.DEMANDMULTIPLIER, mult));
497: return rf.newPreference(AlpineAspectType.DEMANDMULTIPLIER, sf);
498: }
499: }
|