001: /*--------------------------------------------------------------------------
002: * <copyright>
003: *
004: * Copyright 2000-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.IncrementalSubscription;
029: import org.cougaar.glm.ldm.Constants;
030: import org.cougaar.glm.ldm.asset.Inventory;
031: import org.cougaar.glm.ldm.asset.Organization;
032: import org.cougaar.glm.ldm.plan.AlpineAspectType;
033: import org.cougaar.glm.ldm.plan.GeolocLocation;
034: import org.cougaar.glm.plugins.AssetUtils;
035: import org.cougaar.glm.plugins.TaskUtils;
036: import org.cougaar.planning.ldm.asset.AggregateAsset;
037: import org.cougaar.planning.ldm.asset.Asset;
038: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
039: import org.cougaar.planning.ldm.plan.AllocationResult;
040: import org.cougaar.planning.ldm.plan.AllocationResultAggregator;
041: import org.cougaar.planning.ldm.plan.AspectRate;
042: import org.cougaar.planning.ldm.plan.AspectType;
043: import org.cougaar.planning.ldm.plan.AspectValue;
044: import org.cougaar.planning.ldm.plan.Constraint;
045: import org.cougaar.planning.ldm.plan.Expansion;
046: import org.cougaar.planning.ldm.plan.NewConstraint;
047: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
048: import org.cougaar.planning.ldm.plan.NewTask;
049: import org.cougaar.planning.ldm.plan.NewWorkflow;
050: import org.cougaar.planning.ldm.plan.PlanElement;
051: import org.cougaar.planning.ldm.plan.Preference;
052: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
053: import org.cougaar.planning.ldm.plan.Task;
054: import org.cougaar.planning.ldm.plan.TaskScoreTable;
055: import org.cougaar.planning.ldm.plan.Verb;
056: import org.cougaar.planning.ldm.plan.Workflow;
057: import org.cougaar.planning.plugin.util.AllocationResultHelper;
058: import org.cougaar.planning.plugin.util.PluginHelper;
059: import org.cougaar.util.UnaryPredicate;
060: import org.cougaar.util.log.Logger;
061: import org.cougaar.util.log.Logging;
062:
063: import java.util.ArrayList;
064: import java.util.Enumeration;
065: import java.util.List;
066: import java.util.Vector;
067:
068: /**
069: * SupplyExpander expands supply tasks into withdraw tasks and if needed
070: * Transport and Load Tasks. The SupplyExpander also updates the allocation
071: * result whenever one of the subtasks are changed.
072: * It runs for new(added) and changed Supply tasks.
073: * This processor should be included IFF inventory is being handled in this cluster.
074: */
075:
076: public class SupplyExpander extends InventoryProcessor {
077: private static Logger logger = Logging
078: .getLogger(SupplyExpander.class);
079:
080: /**
081: * Define an ARA that can deal with the expansion of a
082: * ProjectSupply task. Mostly, we just clone the result of the
083: * ProjectWithdraw task.
084: */
085: private static class ProjectionARA implements
086: AllocationResultAggregator {
087: public AllocationResult calculate(Workflow wf,
088: TaskScoreTable tst, AllocationResult currentar) {
089: if (tst.size() != 1)
090: throw new IllegalArgumentException(
091: "projectionARA: multiple subtasks");
092: AllocationResult ar = (AllocationResult) tst
093: .getAllocationResult(0);
094: if (ar == null)
095: return null;
096: if (ar.isEqual(currentar))
097: return currentar;
098: return (AllocationResult) ar.clone();
099: }
100: }
101:
102: private static class SupplyARA implements
103: AllocationResultAggregator {
104: public AllocationResult calculate(Workflow wf,
105: TaskScoreTable tst, AllocationResult currentar) {
106: AspectValue[] merged = new AspectValue[AlpineAspectType.LAST_ALPINE_ASPECT + 1];
107: long startTime = Long.MAX_VALUE;
108: long endTime = Long.MIN_VALUE;
109: boolean success = true;
110: float rating = 0.0f;
111: int tstSize = tst.size();
112: AllocationResult withdrawAR = null; // Remember this when we see it
113: long time;
114: Task parentTask = wf.getParentTask();
115: PlanElement pe = parentTask.getPlanElement();
116: AllocationResultHelper helper = new AllocationResultHelper(
117: parentTask, null);
118: AllocationResult bestAR = helper.getAllocationResult();
119: AspectValue[] curr = bestAR.getAspectValueResults();
120:
121: for (int i = 0; i < curr.length; i++) {
122: AspectValue av = curr[i];
123: int type = av.getAspectType();
124: merged[type] = av;
125: switch (type) {
126: case START_TIME:
127: startTime = (long) av.getValue();
128: break;
129: case END_TIME:
130: endTime = (long) av.getValue();
131: break;
132: }
133: }
134: for (int i = 0; i < tstSize; i++) {
135: AllocationResult ar = tst.getAllocationResult(i);
136: if (ar == null)
137: return null; // bail if undefined
138: Task t = tst.getTask(i);
139: Verb verb = t.getVerb();
140: boolean isWithdraw = verb
141: .equals(Constants.Verb.Withdraw)
142: || verb.equals(Constants.Verb.ProjectWithdraw);
143: if (isWithdraw) {
144: if (ar == null)
145: return null;
146: withdrawAR = ar;
147: }
148: AspectValue[] avs = ar.getAspectValueResults();
149: success = success && ar.isSuccess();
150: rating += ar.getConfidenceRating();
151: for (int j = 0; j < avs.length; j++) {
152: int type = avs[j].getAspectType();
153: switch (type) {
154: case AspectType.START_TIME:
155: break;
156: case AspectType.END_TIME:
157: break;
158: case AspectType.QUANTITY:
159: if (isWithdraw)
160: merged[AspectType.QUANTITY] = avs[j];
161: break;
162: default:
163: if (!isWithdraw)
164: merged[type] = avs[j];
165: }
166: }
167: }
168: List mergedPhasedResults = new ArrayList();
169: List withdrawPhasedResults = withdrawAR
170: .getPhasedAspectValueResults();
171: for (int i = 0, n = withdrawPhasedResults.size(); i < n; i++) {
172: AspectValue[] oneResult = (AspectValue[]) withdrawPhasedResults
173: .get(i);
174: mergedPhasedResults.add(merge(merged, oneResult));
175: }
176: return new AllocationResult(rating / tstSize, success,
177: merge(merged, null), mergedPhasedResults);
178: }
179:
180: /**
181: * Merges an array of AspectValue indexed by AspectType and an
182: * unindexed array of AspectValues into an unindexed array of
183: * AspectValues.
184: */
185: private AspectValue[] merge(AspectValue[] rollup,
186: AspectValue[] phased) {
187: if (phased != null) {
188: rollup = (AspectValue[]) rollup.clone(); // Don't clobber the original
189: for (int i = 0; i < phased.length; i++) {
190: AspectValue av = phased[i];
191: if (av != null)
192: rollup[av.getAspectType()] = av;
193: }
194: }
195: int nAspects = 0;
196: for (int i = 0; i < rollup.length; i++) {
197: if (rollup[i] != null)
198: nAspects++;
199: }
200: AspectValue[] result = new AspectValue[nAspects];
201: int aspect = 0;
202: for (int i = 0; i < rollup.length; i++) {
203: if (rollup[i] != null)
204: result[aspect++] = rollup[i];
205: }
206: return result;
207: }
208: }
209:
210: private IncrementalSubscription projectExpansions_;
211: private IncrementalSubscription supplyExpansions_;
212:
213: public static final long TRANSPORT_TIME = 24 * MSEC_PER_HOUR; // second day
214: public static final long LOAD_TIME = 4 * MSEC_PER_HOUR; // 4 hours
215: public static final Verb WITHDRAWVERB = Verb
216: .get(Constants.Verb.WITHDRAW);
217: public static final Verb PROJECTWITHDRAWVERB = Constants.Verb.ProjectWithdraw;
218: public static final Verb TRANSPORTVERB = Verb
219: .get(Constants.Verb.TRANSPORT);
220: public static final Verb LOADVERB = Verb.get(Constants.Verb.LOAD);
221: private static AllocationResultAggregator projectionARA = new ProjectionARA();
222: private static AllocationResultAggregator supplyARA = new SupplyARA();
223: protected boolean addTransport; // Add load tasks when expanding supply tasks
224: protected boolean addLoad; // Add transport tasks when expanding supply tasks
225:
226: /**
227: * Constructor takes this processor's plugin, organization and the type of
228: * supply tasks that shall be handled.
229: */
230: public SupplyExpander(InventoryPlugin plugin, Organization org,
231: String type) {
232: super (plugin, org, type);
233: supplyType_ = type;
234: // supplyExpansionElements_ = subscribe(new SupplyExpansionTaskPredicate(supplyType_));
235: // projectExpansionElements_ = subscribe(new ProjectionExpansionTaskPredicate(supplyType_));
236: projectExpansions_ = subscribe(new ProjectionExpansionPredicate(
237: supplyType_, myOrgName_));
238: supplyExpansions_ = subscribe(new SupplyExpansionPredicate(
239: supplyType_, myOrgName_));
240: addTransport = getBooleanParam(supplyType_ + "Transport");
241: addLoad = getBooleanParam(supplyType_ + "Load");
242:
243: }
244:
245: private boolean getBooleanParam(String paramName) {
246: Boolean bool = (Boolean) inventoryPlugin_.getParam(paramName);
247: return (bool != null && bool.booleanValue());
248: }
249:
250: // Subscribe to Single supplyType_ Supply Task
251: static class SupplyExpansionTaskPredicate implements UnaryPredicate {
252: String supplyType_;
253:
254: public SupplyExpansionTaskPredicate(String type) {
255: supplyType_ = type;
256: }
257:
258: public boolean execute(Object o) {
259: if (o instanceof Expansion) {
260: Task task = ((Expansion) o).getTask();
261: Verb task_verb = task.getVerb();
262: if (task_verb.equals(Constants.Verb.TRANSPORT)
263: || task_verb.equals(Constants.Verb.LOAD)
264: || task_verb.equals(Constants.Verb.WITHDRAW)) {
265: return TaskUtils.isDirectObjectOfType(task,
266: supplyType_);
267: }
268: }
269: return false;
270: }
271: }
272:
273: static class ProjectionExpansionTaskPredicate implements
274: UnaryPredicate {
275: String supplyType_;
276:
277: public ProjectionExpansionTaskPredicate(String type) {
278: supplyType_ = type;
279: }
280:
281: public boolean execute(Object o) {
282: if (o instanceof PlanElement) {
283: Task task = ((PlanElement) o).getTask();
284: Verb task_verb = task.getVerb();
285: if (task_verb.equals(Constants.Verb.PROJECTWITHDRAW)) {
286: return TaskUtils.isDirectObjectOfType(task,
287: supplyType_);
288: }
289: }
290: return false;
291: }
292: }
293:
294: static class ProjectionExpansionPredicate implements UnaryPredicate {
295: String supplyType_;
296: UnaryPredicate taskPredicate;
297:
298: public ProjectionExpansionPredicate(String type, String orgname) {
299: supplyType_ = type;
300: taskPredicate = new InventoryProcessor.ProjectionTaskPredicate(
301: type, orgname);
302: }
303:
304: public boolean execute(Object o) {
305: if (o instanceof PlanElement) {
306: Task task = ((PlanElement) o).getTask();
307: return taskPredicate.execute(task);
308: }
309: return false;
310: }
311: }
312:
313: static class SupplyExpansionPredicate implements UnaryPredicate {
314: String supplyType_;
315: UnaryPredicate taskPredicate;
316:
317: public SupplyExpansionPredicate(String type, String orgname) {
318: supplyType_ = type;
319: taskPredicate = new InventoryProcessor.SupplyTaskPredicate(
320: type, orgname);
321: }
322:
323: public boolean execute(Object o) {
324: if (o instanceof Expansion) {
325: Task task = ((Expansion) o).getTask();
326: return taskPredicate.execute(task);
327: }
328: return false;
329: }
330: }
331:
332: /**
333: * This method is called everytime a subscription has changed.
334: */
335: public void update() {
336: if ((inventoryPlugin_.getDetermineRequirementsTask() == null)
337: || !needUpdate()) {
338: return;
339: }
340: super .update(); // set up dates
341: handleExpandableTasks(supplyTasks_.getAddedList());
342: updateExpansion(supplyTasks_.getChangedList());
343: handleExpandableTasks(projectionTasks_.getAddedList());
344: updateExpansion(projectionTasks_.getChangedList());
345: PluginHelper.updateAllocationResult(projectExpansions_);
346: handleExpansionChanges(supplyExpansions_.getChangedList());
347: PluginHelper.updateAllocationResult(supplyExpansions_);
348: }
349:
350: private boolean needUpdate() {
351: if (supplyTasks_.hasChanged())
352: return true;
353: if (projectionTasks_.hasChanged())
354: return true;
355: if (supplyExpansions_.hasChanged())
356: return true;
357: if (projectExpansions_.hasChanged())
358: return true;
359: return false;
360: }
361:
362: /**
363: * Expands an enumeration of Supply tasks *
364: */
365: protected void handleExpandableTasks(Enumeration tasks) {
366: Task supplyTask;
367: Inventory inv = null;
368: Asset proto;
369: String id;
370: int tasksExpanded = 0;
371: while (tasks.hasMoreElements()) {
372: supplyTask = (Task) tasks.nextElement();
373: proto = (Asset) supplyTask.getDirectObject();
374: // If we cannot allocate the task to inventory then ignore it.
375: // The external allocator will forward it onto a re-supply cluster.
376: inv = inventoryPlugin_.findOrMakeInventory(supplyType_,
377: proto);
378: if (inv != null) {
379: tasksExpanded++;
380: // printDebug("handleExpandableTasks(), <"+supplyType_+">, Expanding "+TaskUtils.taskDesc(supplyTask));
381: expandSupplyTask(supplyTask);
382: } else {
383: id = proto.getTypeIdentificationPG()
384: .getTypeIdentification();
385: if (logger.isDebugEnabled()) {
386: logger.debug("handleExpandableTasks(), <"
387: + supplyType_ + ">, could not allocate "
388: + id);
389: }
390: }
391: }
392: // printDebug("handleExpandableTasks() <"+supplyType_+"> expanded "+
393: // tasksExpanded+" tasks.");
394: }
395:
396: protected void updateExpansion(Enumeration tasks) {
397: Task supplyTask;
398: Inventory inv = null;
399: Asset proto;
400: while (tasks.hasMoreElements()) {
401: supplyTask = (Task) tasks.nextElement();
402: proto = (Asset) supplyTask.getDirectObject();
403: inv = inventoryPlugin_.findOrMakeInventory(supplyType_,
404: proto);
405: if (inv != null) {
406: PlanElement pe = supplyTask.getPlanElement();
407: if (pe instanceof Expansion) {
408: if (logger.isDebugEnabled()) {
409: logger
410: .debug("updateExpansion(), Withdraw REPLAN, Supply task changed "
411: + TaskUtils
412: .taskDesc(supplyTask));
413: }
414: publishRemoveExpansion((Expansion) pe);
415: expandSupplyTask(supplyTask);
416: }
417: }
418: }
419: }
420:
421: /**
422: * Expands a Supply task into a withdraw task *
423: */
424: protected void expandSupplyTask(Task parentTask) {
425: if (parentTask.getVerb().equals(Constants.Verb.SUPPLY)) {
426: expandRealSupplyTask(parentTask);
427: } else if (parentTask.getVerb().equals(
428: Constants.Verb.PROJECTSUPPLY)) {
429: expandProjectionTask(parentTask);
430: }
431: }
432:
433: /**
434: * Expand a ProjectSupply into a ProjectWithdraw
435: * InventoryBG will sort out the details of dates and quantities
436: * later.
437: */
438: private void expandProjectionTask(Task parent_task) {
439: Vector expand_tasks = new Vector();
440: NewTask withdrawTask = createProjectSupplyWithdrawTask(parent_task);
441: expand_tasks.addElement(withdrawTask);
442: publishExpansion(parent_task, expand_tasks);
443: Expansion expansion = (Expansion) parent_task.getPlanElement();
444: NewWorkflow wf = (NewWorkflow) expansion.getWorkflow();
445: wf.setAllocationResultAggregator(projectionARA);
446: AllocationResult ar = new AllocationResultHelper(parent_task,
447: null).getAllocationResult(1.0);
448: expansion.setEstimatedResult(ar);
449: }
450:
451: private void expandRealSupplyTask(Task parentTask) {
452: Vector expand_tasks = new Vector();
453: NewTask withdrawTask = createSupplyWithdrawTask(parentTask);
454: expand_tasks.addElement(withdrawTask);
455: NewTask transportTask = null;
456: NewTask loadTask = null;
457: withdrawTask.addObservableAspect(AspectType.END_TIME);
458: withdrawTask.addObservableAspect(AspectType.QUANTITY);
459: if (addLoad) {
460: loadTask = createLoadTask(parentTask, withdrawTask);
461: loadTask.addObservableAspect(AspectType.START_TIME);
462: loadTask.addObservableAspect(AspectType.END_TIME);
463: loadTask.addObservableAspect(AspectType.QUANTITY);
464: expand_tasks.addElement(loadTask);
465: }
466: if (addTransport) {
467: transportTask = createTransportTask(parentTask,
468: withdrawTask);
469: transportTask.addObservableAspect(AspectType.START_TIME);
470: transportTask.addObservableAspect(AspectType.END_TIME);
471: transportTask.addObservableAspect(AspectType.QUANTITY);
472: expand_tasks.addElement(transportTask);
473: }
474: ((NewTask) parentTask).addObservableAspect(AspectType.END_TIME);
475: publishExpansion(parentTask, expand_tasks);
476: Expansion expansion = (Expansion) parentTask.getPlanElement();
477: AllocationResult ar = new AllocationResultHelper(parentTask,
478: null).getAllocationResult(1.0);
479: expansion.setEstimatedResult(ar);
480: NewWorkflow wf = (NewWorkflow) expansion.getWorkflow();
481: wf.setAllocationResultAggregator(supplyARA);
482: NewConstraint constraint;
483: if (transportTask != null) {
484: // Constraint start of transport
485: constraint = ldmFactory_.newConstraint();
486: constraint.setConstrainedTask(transportTask);
487: constraint.setConstrainedAspect(AspectType.START_TIME);
488: if (loadTask != null) {
489: // Constrain load before transport
490: constraint.setConstrainingTask(loadTask);
491: constraint.setConstrainingAspect(AspectType.END_TIME);
492: } else {
493: // Constrain withdraw before transport
494: constraint.setConstrainingTask(withdrawTask);
495: constraint.setConstrainingAspect(AspectType.END_TIME);
496: }
497: constraint.setConstraintOrder(Constraint.COINCIDENT); // Artificial
498: wf.addConstraint(constraint);
499: // Constraint QUANTITY of transport
500: constraint = ldmFactory_.newConstraint();
501: constraint.setConstrainedTask(transportTask);
502: constraint.setConstrainedAspect(AspectType.QUANTITY);
503: if (loadTask != null) {
504: // Constrain transport quantity equal to load quantity
505: constraint.setConstrainingTask(loadTask);
506: constraint.setConstrainingAspect(AspectType.QUANTITY);
507: } else {
508: // Constrain transport quantity equal to withdraw quantity
509: constraint.setConstrainingTask(withdrawTask);
510: constraint.setConstrainingAspect(AspectType.QUANTITY);
511: }
512: constraint.setConstraintOrder(Constraint.EQUALTO); // Artificial
513: wf.addConstraint(constraint);
514: }
515: if (loadTask != null) {
516: // Constraint start of load
517: constraint = ldmFactory_.newConstraint();
518: constraint.setConstrainedTask(loadTask);
519: constraint.setConstrainedAspect(AspectType.START_TIME);
520: constraint.setConstrainingTask(withdrawTask);
521: constraint.setConstrainingAspect(AspectType.END_TIME);
522: constraint.setConstraintOrder(Constraint.COINCIDENT); // Artificial
523: wf.addConstraint(constraint);
524: // Constraint quantity of load
525: constraint = ldmFactory_.newConstraint();
526: constraint.setConstrainedTask(loadTask);
527: constraint.setConstrainedAspect(AspectType.QUANTITY);
528: constraint.setConstrainingTask(withdrawTask);
529: constraint.setConstrainingAspect(AspectType.QUANTITY);
530: constraint.setConstraintOrder(Constraint.EQUALTO); // Artificial
531: wf.addConstraint(constraint);
532: }
533: // Constraint end of parentTask
534: constraint = ldmFactory_.newConstraint();
535: constraint.setConstrainedTask(parentTask);
536: constraint.setConstrainedAspect(AspectType.END_TIME);
537: if (transportTask != null) {
538: constraint.setConstrainingTask(transportTask);
539: } else if (loadTask != null) {
540: constraint.setConstrainingTask(loadTask);
541: } else {
542: constraint.setConstrainingTask(withdrawTask);
543: }
544: constraint.setConstrainingAspect(AspectType.END_TIME);
545: constraint.setConstraintOrder(Constraint.COINCIDENT); // Artificial
546: wf.addConstraint(constraint);
547: // Constraint quantity of parent task
548: constraint = ldmFactory_.newConstraint();
549: constraint.setConstrainedTask(parentTask);
550: constraint.setConstrainedAspect(AspectType.QUANTITY);
551: if (transportTask != null) {
552: constraint.setConstrainingTask(transportTask);
553: } else if (loadTask != null) {
554: constraint.setConstrainingTask(loadTask);
555: } else {
556: constraint.setConstrainingTask(withdrawTask);
557: }
558: constraint.setConstrainingAspect(AspectType.QUANTITY);
559: constraint.setConstraintOrder(Constraint.EQUALTO); // Artificial
560: wf.addConstraint(constraint);
561: }
562:
563: /**
564: * Handle changes to our expansions of Supply tasks. Basically, a
565: * failure causes all unfailed subtasks to be rescinded. The will
566: * get recreated if the incoming supply task ever gets revived.
567: */
568: protected void handleExpansionChanges(Enumeration expansions) {
569: AllocationResult ar;
570: while (expansions.hasMoreElements()) {
571: Expansion exp = (Expansion) expansions.nextElement();
572: ar = exp.getReportedResult();
573: if (ar != null && !ar.isSuccess()) {
574: NewWorkflow wf = (NewWorkflow) exp.getWorkflow();
575: for (Enumeration tasks = wf.getTasks(); tasks
576: .hasMoreElements();) {
577: Task subtask = (Task) tasks.nextElement();
578: PlanElement pe = subtask.getPlanElement();
579: if (pe != null) { // Null if being rescinded by customer
580: ar = pe.getEstimatedResult();
581: if (!ar.isSuccess())
582: continue;
583: }
584: wf.removeTask(subtask);
585: delegate_.publishRemove(subtask);
586: }
587: }
588: }
589: }
590:
591: /**
592: * creates a Withdraw task from a Supply task *
593: */
594: protected NewTask createWithdrawTask(Task parent_task) {
595:
596: // Create new task
597: Asset prototype = parent_task.getDirectObject();
598: NewTask subtask = ldmFactory_.newTask();
599: // attach withdraw task to parent and fill it in
600: subtask.setDirectObject(prototype);
601: subtask.setParentTask(parent_task);
602: subtask.setPlan(parent_task.getPlan());
603: subtask.setPrepositionalPhrases(parent_task
604: .getPrepositionalPhrases());
605: subtask.setPriority(parent_task.getPriority());
606: subtask.setSource(clusterId_);
607: if (parent_task.getVerb().equals(Constants.Verb.PROJECTSUPPLY)) {
608: subtask.setVerb(PROJECTWITHDRAWVERB);
609: } else {
610: subtask.setVerb(WITHDRAWVERB);
611: }
612: // Copy all preferences that aren't used for repetitive tasks
613: Vector prefs = new Vector();
614: int aspect_type;
615: Preference pref;
616: Enumeration preferences = parent_task.getPreferences();
617: while (preferences.hasMoreElements()) {
618: pref = (Preference) preferences.nextElement();
619: aspect_type = pref.getAspectType();
620: // Quanity added to withdraw by task specific method.
621: // Inerval and DemandRate are not added to withdraw task.
622: if ((aspect_type != AspectType.QUANTITY)
623: && (aspect_type != AspectType.INTERVAL)
624: && (aspect_type != AlpineAspectType.DEMANDRATE)) {
625: prefs.addElement(pref);
626: }
627: }
628: subtask.setPreferences(prefs.elements());
629: return subtask;
630: }
631:
632: protected NewTask createSupplyWithdrawTask(Task parent_task) {
633:
634: NewTask subtask = createWithdrawTask(parent_task);
635: long anticipation = 0L;
636: if (addTransport)
637: anticipation += TRANSPORT_TIME;
638: if (addLoad)
639: anticipation += LOAD_TIME;
640: // Add preferences for QUANTITY
641: double quantity = TaskUtils.getPreference(parent_task,
642: AspectType.QUANTITY);
643: Preference p_qty = createQuantityPreference(
644: AspectType.QUANTITY, quantity);
645: subtask.addPreference(p_qty);
646: addEndTimePref(subtask, TaskUtils.getEndTime(parent_task)
647: - anticipation);
648: // printDebug(1, "CreateSupplyWithdrawTask() "+
649: // TaskUtils.taskDesc(subtask)+" with end date:"+
650: // TimeUtils.dateString(TaskUtils.getEndTime(subtask)));
651: return subtask;
652: }
653:
654: protected NewTask createProjectSupplyWithdrawTask(Task parent_task) {
655: NewTask subtask = createWithdrawTask(parent_task);
656: Preference pref = parent_task
657: .getPreference(AlpineAspectType.DEMANDRATE);
658: if (pref.getScoringFunction().getBest().getAspectValue() instanceof AspectRate) {
659: } else {
660: if (logger.isErrorEnabled()) {
661: logger
662: .error("SupplyExpander DEMANDRATE preference not AspectRate:"
663: + pref);
664: }
665: }
666: subtask.addPreference(pref);
667: // printDebug(1, "CreateProjectSupplyWithdrawTask() with start date:"+
668: // TimeUtils.dateString(TaskUtils.getStartTime(subtask))+", with end dat:"+
669: // TimeUtils.dateString(TaskUtils.getEndTime(subtask))+", quantity is "+quantity);
670:
671: return subtask;
672: }
673:
674: private static final String THEATER_TRANSPORT = "TheaterTransportation";
675:
676: // task coming in is the parent task
677: private NewTask createTransportTask(Task parent_task,
678: Task wdraw_task) {
679:
680: // This is the part to transport
681: Asset part = parent_task.getDirectObject();
682: // This is the number of parts to transport
683: int quantity = (int) TaskUtils.getPreference(wdraw_task,
684: AspectType.QUANTITY);
685:
686: NewTask subtask = ldmFactory_.newTask();
687:
688: AggregateAsset aggAsset = (AggregateAsset) ldmFactory_
689: .createAggregate(part, quantity);
690:
691: subtask.setParentTask(parent_task);
692:
693: // START TIME & END TIME
694: long parent_end = TaskUtils.getEndTime(parent_task);
695: long start = parent_end - TRANSPORT_TIME;
696: long end = parent_end;
697:
698: Preference startPref = createTransportStartPref(start);
699: subtask.addPreference(startPref);
700:
701: Preference endPref = createTransportEndPref(end);
702: subtask.addPreference(endPref);
703:
704: // Fill in preposition phrases.
705: Vector pps = new Vector();
706:
707: // From
708:
709: NewPrepositionalPhrase prep_phrase = ldmFactory_
710: .newPrepositionalPhrase();
711: prep_phrase.setPreposition(Constants.Preposition.FROM);
712: Enumeration geolocs = AssetUtils.getGeolocLocationAtTime(
713: myOrganization_, start);
714: GeolocLocation geoloc = null;
715: if (geolocs.hasMoreElements()) {
716: geoloc = (GeolocLocation) geolocs.nextElement();
717: } else {
718: try {
719: // printDebug("SupplyExpander, Using HomeLocation for transport");
720: geoloc = (GeolocLocation) myOrganization_
721: .getMilitaryOrgPG().getHomeLocation();
722: } catch (NullPointerException npe) {
723: if (logger.isErrorEnabled()) {
724: logger
725: .error("SupplyExpander, Unable to find Location for Transport");
726: }
727: }
728: }
729: // printDebug("SupplyExpander, At "+TimeUtils.dateString(start)+ " the geoloc is "+geoloc);
730: prep_phrase.setIndirectObject(geoloc);
731: pps.addElement(prep_phrase);
732:
733: // To
734: PrepositionalPhrase pp_to = parent_task
735: .getPrepositionalPhrase(Constants.Preposition.TO);
736: if (pp_to != null) {
737: prep_phrase = ldmFactory_.newPrepositionalPhrase();
738: prep_phrase.setPreposition(Constants.Preposition.TO);
739: prep_phrase.setIndirectObject((GeolocLocation) pp_to
740: .getIndirectObject());
741: pps.addElement(prep_phrase);
742: } else {
743: // ???????????????????
744: // What to do in this case? Transport to nowhere? just return at this point?
745: if (logger.isErrorEnabled()) {
746: logger.error("Missing TO Preposition on input task "
747: + parent_task);
748: }
749: return null;
750: }
751:
752: // Ready at
753: // prep_phrase = ldmFactory_.newPrepositionalPhrase();
754: // prep_phrase.setPreposition( Preposition.READYAT );
755: // CHECK SCHEDULES -- RJB
756: // Schedule s = ldmFactory_.newSimpleSchedule(allocated_date, allocated_date);
757: // Schedule s = ldmFactory_.newSimpleSchedule(allocated_date, addNDays(allocated_date,1));
758: // prep_phrase.setIndirectObject(s);
759: // pps.addElement(prep_phrase);
760:
761: // For
762: prep_phrase = ldmFactory_.newPrepositionalPhrase();
763: prep_phrase.setPreposition(Constants.Preposition.FOR);
764: String orgName = myOrganization_.getItemIdentificationPG()
765: .getItemIdentification();
766: prep_phrase.setIndirectObject(orgName);
767: // prep_phrase.setIndirectObject(myOrganization_);
768: pps.addElement(prep_phrase);
769:
770: String ofTypeString = THEATER_TRANSPORT;
771: // if parent task has an ofType <commodity> copy it into the Transport task
772: // this allows users of the transport task to do commodity based routing
773: PrepositionalPhrase pp_commodityType = parent_task
774: .getPrepositionalPhrase(Constants.Preposition.OFTYPE);
775: if (pp_commodityType != null) {
776: String ind_obj = (String) pp_commodityType
777: .getIndirectObject();
778: ofTypeString = ind_obj + "_" + ofTypeString;
779: }
780:
781: // OfType
782: prep_phrase = ldmFactory_.newPrepositionalPhrase();
783: prep_phrase.setPreposition(Constants.Preposition.OFTYPE);
784: Asset transport_asset = ldmFactory_.createPrototype(
785: "AbstractAsset", ofTypeString);
786: NewTypeIdentificationPG tipg = (NewTypeIdentificationPG) transport_asset
787: .getTypeIdentificationPG();
788: tipg.setTypeIdentification(ofTypeString);
789: prep_phrase.setIndirectObject(transport_asset);
790: pps.addElement(prep_phrase);
791:
792: // Fill in verb.
793: subtask.setDirectObject(aggAsset);
794: subtask.setPrepositionalPhrases(pps.elements());
795: subtask.setVerb(TRANSPORTVERB);
796: subtask.setPlan(parent_task.getPlan());
797:
798: // Quantity Preference
799: Preference quantity_pf = createQuantityPreference(
800: AspectType.QUANTITY, quantity);
801: subtask.addPreference(quantity_pf);
802:
803: subtask.setSource(clusterId_);
804: // printDebug("Created transport task:" + taskDesc(subtask));
805: return subtask;
806: }
807:
808: // LOAD Task
809: private NewTask createLoadTask(Task parent_task, Task wdraw_task) {
810:
811: NewTask subtask = ldmFactory_.newTask();
812: Asset asset = parent_task.getDirectObject();
813:
814: // Quantity Preference
815: int quantity = (int) TaskUtils.getPreference(wdraw_task,
816: AspectType.QUANTITY);
817: Preference quantity_pf = createQuantityPreference(
818: AspectType.QUANTITY, quantity);
819: subtask.addPreference(quantity_pf);
820:
821: // // START TIME & END TIME
822: addStartTimePref(subtask, TaskUtils.getEndTime(wdraw_task));
823: addEndTimePref(subtask, TaskUtils.getEndTime(wdraw_task)
824: + LOAD_TIME);
825:
826: // For
827: Vector pps = new Vector();
828: NewPrepositionalPhrase prep_phrase = ldmFactory_
829: .newPrepositionalPhrase();
830: prep_phrase.setPreposition(Constants.Preposition.FOR);
831: String orgName = myOrganization_.getItemIdentificationPG()
832: .getItemIdentification();
833: prep_phrase.setIndirectObject(orgName);
834: // prep_phrase.setIndirectObject(myOrganization_);
835: pps.addElement(prep_phrase);
836:
837: subtask.setParentTask(parent_task);
838: subtask.setDirectObject(asset);
839:
840: // Fill in verb.
841: subtask.setPrepositionalPhrases(pps.elements());
842: subtask.setVerb(LOADVERB);
843: subtask.setPlan(parent_task.getPlan());
844:
845: subtask.setSource(clusterId_);
846: // printDebug("Created transport task:" + taskDesc(subtask));
847: return subtask;
848: }
849:
850: /**
851: * Creates a start and end preference and attaches them to a task *
852: */
853: protected void addEndTimePref(NewTask task, long end) {
854: Preference p_end = createDateBeforePreference(
855: AspectType.END_TIME, end);
856: task.addPreference(p_end);
857: }
858:
859: protected void addStartTimePref(NewTask task, long start) {
860: Preference p_start = createDateAfterPreference(
861: AspectType.START_TIME, start);
862: task.addPreference(p_start);
863: }
864:
865: }
|