001: /*
002: * <copyright>
003: *
004: * Copyright 2003-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.plugin.strattrans;
028:
029: import java.util.Collection;
030: import java.util.Enumeration;
031: import java.util.Vector;
032:
033: import org.cougaar.glm.ldm.Constants;
034:
035: import org.cougaar.planning.ldm.plan.NewTask;
036: import org.cougaar.planning.ldm.plan.PlanElement;
037: import org.cougaar.planning.ldm.plan.Task;
038:
039: import org.cougaar.glm.ldm.asset.Organization;
040: import org.cougaar.glm.ldm.asset.Person;
041: import org.cougaar.glm.ldm.asset.ClassVIIMajorEndItem;
042: import org.cougaar.glm.ldm.asset.MovabilityPG;
043:
044: import org.cougaar.planning.plugin.util.ExpanderHelper;
045:
046: import org.cougaar.glm.ldm.plan.GeolocLocation;
047:
048: import org.cougaar.lib.callback.UTILFilterCallback;
049: import org.cougaar.lib.callback.UTILGenericListener;
050:
051: import org.cougaar.lib.filter.UTILExpanderPluginAdapter;
052:
053: import org.cougaar.planning.ldm.asset.AbstractAsset;
054: import org.cougaar.planning.ldm.asset.Asset;
055: import org.cougaar.planning.ldm.asset.AssetGroup;
056:
057: import org.cougaar.glm.ldm.oplan.OrgActivity;
058: import org.cougaar.glm.ldm.oplan.TimeSpan;
059:
060: import org.cougaar.util.ShortDateFormat;
061:
062: import java.util.Date;
063:
064: /**
065: * Class <code>org.cougaar.logistics.plugin.strattrans.StrategicTransportProjectorPlugin</code> is a replacement
066: * for <code>org.cougaar.mlm.plugin.sample.StrategicTranportProjectorPlugin</code>.
067: * <p>
068: * (updated based upon ComponentPlugin and Toolkit)
069: * <p>
070: * This class subscribes to the single "Deploy" "DetermineRequirements"
071: * Task and expands it to "Transport" Tasks for all applicable assets.
072: * <p>
073: * Currently expects only one oplan, one "self" org activity, and one
074: * "Deploy" "DetermineRequirements" task.
075: * <p>
076: * Debug information is now off by default. See method <code>setDebug()</code>
077: */
078:
079: public class StrategicTransportProjectorPlugin extends
080: UTILExpanderPluginAdapter implements UTILOrgActivityListener,
081: UTILOrganizationListener, UTILParameterizedAssetListener {
082:
083: /**
084: * Provide the callback that is paired with the buffering thread, which is a
085: * listener. The buffering thread is the listener to the callback
086: *
087: * overridden to use UTILExpandableChildTaskCallback to allow
088: * tasks that are child of another task (specifically required for
089: * Strat-Trans Deter-Req tasks, which are child of GLS)
090: *
091: * @return an UTILExpandableChildTaskCallback with the buffering thread as its listener
092: * @see org.cougaar.lib.callback.UTILWorkflowCallback
093: */
094: protected UTILFilterCallback createThreadCallback(
095: UTILGenericListener bufferingThread) {
096: if (isInfoEnabled())
097: info(getAgentIdentifier()
098: + " : Filtering for Expandable Tasks...");
099: myInputTaskCallback = new UTILExpandableChildTaskCallback(
100: bufferingThread, logger);
101: return myInputTaskCallback;
102: }
103:
104: /**
105: * Replan tasks when one of the inputs has changed, typically the Org Activity.
106: */
107: public void redoTasks() {
108: SubscriptionResults subscriptionResults = checkSubscriptions();
109: if (subscriptionResults != null) {
110: Enumeration en = myInputTaskCallback.getSubscription()
111: .elements();
112: boolean alreadyFound = false;
113:
114: if (isInfoEnabled()) {
115: if (!en.hasMoreElements()) {
116: info("no tasks to replan on redo?");
117: }
118: }
119:
120: while (en.hasMoreElements()) {
121: if (alreadyFound) {
122: warn(getAgentIdentifier()
123: + " - more than one determine requirements task!");
124: }
125: Task t = (Task) en.nextElement();
126: alreadyFound = true;
127: if (t.getPlanElement() == null) {
128: if (isInfoEnabled()) {
129: info(getAgentIdentifier()
130: + " - redoTasks: Null Plan Element to be filled for task "
131: + t.getUID());
132: }
133: handleTask(t, subscriptionResults);
134: } else {
135: PlanElement prevPE = t.getPlanElement();
136:
137: // check to see if org activity in the past before we go tearing up the log plan
138: if (orgActivityInThePast(subscriptionResults)) {
139: if (isInfoEnabled()) {
140: info(getAgentIdentifier()
141: + " - redoTasks: not replanning "
142: + t.getUID()
143: + " because it's in the past.");
144: }
145: } else {
146: if (isInfoEnabled()) {
147: info(getAgentIdentifier()
148: + " - redoTasks: Plan Element removed from "
149: + t.getUID() + " and replanned.");
150: }
151:
152: publishRemove(prevPE); // only remove old results if activity is in the future
153: handleTask(t, subscriptionResults);
154:
155: // postcondition test
156: if ((t.getPlanElement() == null)
157: || (t.getPlanElement() == prevPE)) {
158: warn(getAgentIdentifier()
159: + " - redoTasks: didn't replan "
160: + t.getUID()
161: + " properly, PE not updated.");
162: }
163: }
164: }
165: }
166: } else {
167: if (isInfoEnabled()) {
168: info("Not acting on change since not all required elements on blackboard.");
169: }
170: }
171: }
172:
173: public void handleNewOrganizations(Enumeration e) {
174: if (isInfoEnabled())
175: info("Got new organization - " + e.nextElement());
176: redoTasks();
177: }
178:
179: public void handleNewParameterizedAssets(Enumeration e, String key) {
180: if (isInfoEnabled())
181: info("Got new assets - " + e.nextElement() + " key " + key);
182: redoTasks();
183: }
184:
185: public void handleNewOrgActivities(Enumeration e) {
186: if (isInfoEnabled())
187: info("Got new org activity - " + e.nextElement());
188: redoTasks();
189: }
190:
191: /**
192: * Does NOT replan on changed org.
193: *
194: * If we replan on changed org - will always replan on rehydrate,
195: * when the org changes when the agent is reconstituted.
196: * Why the org changes, I'm not sure. I just know it does on rehydrate.
197: */
198: public void handleChangedOrganizations(Enumeration e) {
199: if (isInfoEnabled())
200: info("Got changed organization - " + e.nextElement()
201: + " but not replanning.");
202: }
203:
204: public void handleChangedParameterizedAssets(Enumeration e,
205: String key) {
206: if (isInfoEnabled())
207: info("Got changed assets - " + e.nextElement() + " key "
208: + key);
209: redoTasks();
210: }
211:
212: public void handleChangedOrgActivities(Enumeration e) {
213: if (isInfoEnabled()) {
214: while (e.hasMoreElements()) {
215: OrgActivity orgAct = (OrgActivity) e.nextElement();
216: info("Got changed org activity - " + orgAct
217: + "'s end time "
218: + orgAct.getTimeSpan().getEndDate());
219: }
220: }
221: redoTasks();
222: }
223:
224: // extending UTILExpanderPluginAdapter gets me a callback that listens to the types of tasks specified in "interestingTask" (see the method UTILExpanderPluginAdapter.createThreadCallback, which is called by setupFilters of its parent class UTILBufferingPluginAdapter)
225: // extending UTILExpanderPluginAdapter gets me a callback that listens to the types of tasks specified in "interestingExpandedTask" (see the method UTILExpanderPluginAdapter.setupFilters)
226: // by default, from UTILExpanderPluginAdapter.interestingExpandedTask, the interestingExpandedTask is also the interestingTask
227:
228: protected UTILOrgActivityCallback myDeploymentOrgActivityCallback;
229: protected UTILOrganizationCallback mySelfOrganizationCallback;
230: protected UTILParameterizedAggregateAssetCallback myPersonAssetCallback;
231: protected UTILParameterizedAggregateAssetCallback myMEIAssetCallback;
232:
233: /*
234: * <pre>
235: * The idea is to add subscriptions (via the filterCallback), and when
236: * they change, to have the callback react to the change, and tell
237: * the listener (many times the plugin) what to do.
238: *
239: * </pre>
240: * @see #createOrgActivityCallback
241: * @see #createOrganizationCallback
242: * @see #createParameterizedAggregateAssetCallback
243: */
244: public void setupFilters() {
245: super .setupFilters();
246:
247: addFilter(myDeploymentOrgActivityCallback = createOrgActivityCallback());
248: addFilter(mySelfOrganizationCallback = createOrganizationCallback());
249: addFilter(myPersonAssetCallback = createParameterizedAggregateAssetCallback(
250: "Person", false));
251: addFilter(myMEIAssetCallback = createParameterizedAggregateAssetCallback(
252: "ClassVIIMajorEndItem", true));
253: }
254:
255: /*-----------------------------------------------------------------
256: *
257: * Task methods
258: *
259: *-----------------------------------------------------------------
260: */
261:
262: /**
263: * State that we are interested in all DETERMINEREQUIREMENT tasks of type Asset
264: * where the asset type is StrategicTransportation.
265: * @param task the task to test.
266: * @return true if the tasks verb is DetermineRequirements with the preposition "StrategicTransportation", false otherwise
267: */
268: public boolean interestingTask(Task task) {
269: if (task.getVerb().equals(Constants.Verb.DetermineRequirements)) {
270: return (ExpanderHelper.isOfType(task,
271: Constants.Preposition.OFTYPE,
272: "StrategicTransportation"));
273: }
274: return false;
275: }
276:
277: /*-----------------------------------------------------------------
278: *
279: * Expanded task methods
280: *
281: *-----------------------------------------------------------------
282: */
283:
284: // by default the same DETERMINEREQUIREMENT tasks of type StrategicTransportation
285: /*-----------------------------------------------------------------
286: *
287: * Organization methods
288: *
289: *-----------------------------------------------------------------
290: */
291:
292: /**
293: * create the organization callback
294: */
295: protected UTILOrganizationCallback createOrganizationCallback() {
296: if (isInfoEnabled())
297: info(getName() + " : Filtering for Organizations...");
298:
299: UTILOrganizationCallback cb = new UTILOrganizationCallback(
300: this , logger);
301: return cb;
302: }
303:
304: /** Interested in listening to self-organization (from interface UTILOrganizationListener,
305: * and linked to UTILOrganizationCallback)
306: */
307: public boolean interestingOrganization(Organization org) {
308: return (org.isSelf());
309: }
310:
311: /*-----------------------------------------------------------------
312: *
313: * Org Activity methods
314: *
315: *-----------------------------------------------------------------
316: */
317:
318: /**
319: * create the org activity callback
320: */
321: protected UTILOrgActivityCallback createOrgActivityCallback() {
322: if (isInfoEnabled())
323: info(getName() + " : Filtering for Org Activities...");
324:
325: UTILOrgActivityCallback cb = new UTILOrgActivityCallback(this ,
326: logger);
327: return cb;
328: }
329:
330: /** Interested in listening to deployment org-activities (from interface
331: * UTILOrgActivityListener, and linked to UTILOrgActivityCallback)
332: */
333: public boolean interestingOrgActivity(OrgActivity orgAct) {
334: return (orgAct.getActivityType().equals("Deployment"));
335: }
336:
337: /*-----------------------------------------------------------------
338: *
339: * Asset (Person/ClassVIIMajorEndItem) methods
340: *
341: *-----------------------------------------------------------------
342: */
343:
344: /**
345: * create the parameterized aggregate asset callback
346: */
347: protected UTILParameterizedAggregateAssetCallback createParameterizedAggregateAssetCallback(
348: String key, boolean isDynamic) {
349: if (isInfoEnabled()) {
350: if (isDynamic)
351: info(getName()
352: + " : Filtering for Asset/Aggregate Assets (that are dynamic) based on key: "
353: + key + "...");
354: else
355: info(getName()
356: + " : Filtering for Asset/Aggregate Assets (that are static) based on key: "
357: + key + "...");
358: }
359:
360: UTILParameterizedAggregateAssetCallback cb = new UTILParameterizedAggregateAssetCallback(
361: this , logger, key, isDynamic);
362: return cb;
363: }
364:
365: /** Interested in listening to Person/ClassVIIMajorEndItem assets
366: *
367: * See bug 2998 in bugzilla.
368: *
369: * In order to not strat trans move Level2MEIs we filter out equipment with the
370: * cargo cat code of "000" which means phantom equipment. The
371: * phantom equipment corresponds to Level2MEIs. The cargo cat code is put
372: * onto the Level2MEIs retroactively after they have been made that is the
373: * reason for the DynamicUnaryPredicate (i.e., callback created with isDynamic true)
374: */
375: public boolean interestingParameterizedAsset(Asset o, String key) {
376: if (key.equals("Person")) {
377: return (o instanceof Person);
378: } else if (key.equals("ClassVIIMajorEndItem")) {
379: if (o instanceof ClassVIIMajorEndItem) {
380: ClassVIIMajorEndItem asset = (ClassVIIMajorEndItem) o;
381: MovabilityPG moveProp = asset.getMovabilityPG();
382: if ((moveProp != null)
383: && (moveProp.getCargoCategoryCode() != null)
384: && (moveProp.getCargoCategoryCode()
385: .equals("000"))) {
386: return false;
387: }
388: return true;
389: }
390: }
391: return false;
392: }
393:
394: /** helper function
395: */
396: protected String getOrgID(Organization org) {
397: try {
398: return org.getClusterPG().getMessageAddress().toString();
399: } catch (Exception e) {
400: return null;
401: }
402: }
403:
404: /** return "self" organization in mySelfOrganizationCallback bucket
405: */
406: protected Organization getSelfOrg() {
407: Enumeration selfOrgsElements = mySelfOrganizationCallback
408: .getSubscription().elements();
409: Organization selfOrg = null;
410:
411: while (selfOrgsElements.hasMoreElements()) {
412: Organization org = (Organization) selfOrgsElements
413: .nextElement();
414: if (selfOrg != null) {
415: error(getAgentIdentifier()
416: + " - Expecting only one \"SELF\" Organization! Already have "
417: + selfOrg + " with self-id: "
418: + getOrgID(selfOrg)
419: + " >> ignoring org with id: " + getOrgID(org));
420: continue;
421: }
422: selfOrg = org;
423: }
424: if (selfOrg == null) {
425: if (isInfoEnabled()) {
426: info(getAgentIdentifier()
427: + " - Expecting a \"SELF\" Organization! Expansion will fail");
428: }
429: }
430:
431: return selfOrg;
432: }
433:
434: /** return orgActivity with matching id (in myDeploymentOrgActivityCallback bucket)
435: */
436: protected OrgActivity getOrgActivity(String id) {
437: Enumeration orgActivitiesElements = myDeploymentOrgActivityCallback
438: .getSubscription().elements();
439: OrgActivity matchingOrgActivity = null;
440:
441: while (orgActivitiesElements.hasMoreElements()) {
442: OrgActivity orgAct = (OrgActivity) orgActivitiesElements
443: .nextElement();
444: if (id.equals(orgAct.getOrgID())) {
445: matchingOrgActivity = orgAct; // found matching org activity
446: break;
447: }
448: }
449: if (matchingOrgActivity == null) {
450: if (isInfoEnabled()) {
451: info(getAgentIdentifier()
452: + " - Expecting an org Activity with id " + id
453: + "! Expansion will fail");
454: }
455: }
456:
457: return matchingOrgActivity;
458: }
459:
460: /** return Vector of Person assets from (in myPersonAssetCallback bucket)
461: */
462: protected Vector getPersonAssets() {
463: return new Vector(myPersonAssetCallback.getSubscription()
464: .getCollection());
465: }
466:
467: /** return Vector of ClassVIIMajorEndItem assets from (in myMEIAssetCallback bucket)
468: */
469: protected Vector getMEIAssets() {
470: return new Vector(myMEIAssetCallback.getSubscription()
471: .getCollection());
472: }
473:
474: class SubscriptionResults {
475: Organization selfOrg = null;
476: String selfOrgID = null;
477: OrgActivity selfDeployOrgActivity = null;
478: Vector personAssets = null;
479: Vector MEIAssets = null;
480:
481: public String toString() {
482: return "Subscription Results : \n" + "\tself " + selfOrg
483: + "\n" + "\tself id " + selfOrgID + "\n"
484: + "\torg act " + selfDeployOrgActivity + "\n"
485: + "\tnum people " + personAssets.size() + "\n"
486: + "\tnum mei " + MEIAssets.size();
487: }
488: }
489:
490: /** Returns a structure containing all the information extracted from the blackboard.
491: * Returns null if any key information is missing.
492: */
493: public SubscriptionResults checkSubscriptions() {
494: SubscriptionResults results = new SubscriptionResults();
495: results.selfOrg = getSelfOrg();
496: if (results.selfOrg == null) {
497: if (isInfoEnabled()) {
498: info(getAgentIdentifier() + " - No self org yet.");
499: }
500: return null; // if no self org, not valid
501: }
502:
503: results.selfOrgID = getOrgID(results.selfOrg);
504: if (isInfoEnabled()) {
505: info(getAgentIdentifier() + " - Found Self: "
506: + results.selfOrgID);
507: }
508:
509: results.selfDeployOrgActivity = getOrgActivity(results.selfOrgID);
510: if (results.selfDeployOrgActivity == null) {
511: if (isInfoEnabled()) {
512: info(getAgentIdentifier()
513: + " - no self deploy org act yet.");
514: }
515: return null; // if no deployment activity, not valid
516: }
517:
518: results.personAssets = getPersonAssets();
519: results.MEIAssets = getMEIAssets();
520: if ((results.personAssets == null || results.personAssets
521: .size() == 0)
522: && (results.MEIAssets == null || results.MEIAssets
523: .size() == 0)) {
524: if (isInfoEnabled()) {
525: info(getAgentIdentifier()
526: + " - no people or MEI assets yet.");
527: }
528: return null; // if nothing to transport, not valid
529: }
530:
531: return results;
532: }
533:
534: /**
535: * <pre>
536: * Implemented for UTILGenericListener interface
537: *
538: * This method Expands the given Task and publishes the PlanElement,
539: * but only if subtasks have been created.
540: *
541: * The method expandTask should be implemented by child classes.
542: * </pre>
543: * @param t the task to be expanded.
544: */
545: public void handleTask(Task t) {
546: if (t.getPlanElement() != null) {
547: if (isInfoEnabled()) {
548: info(getName()
549: + ".handleTask : task "
550: + t.getUID()
551: + " already has a PE (from redoTasks step.). Skipping.");
552: }
553: return;
554: }
555: if (isDebugEnabled())
556: debug(getName() + ".handleTask : called on task "
557: + t.getUID());
558:
559: // Need special handling here in case the getSubtasks returns no subtasks
560: // This is possible if not all subscriptions have been "filled"
561: Vector subtasks = getSubtasks(t);
562:
563: if (subtasks.size() > 0)
564: expand.handleTask(ldmf, getBlackboardService(), getName(),
565: wantConfidence, t, subtasks);
566: }
567:
568: /** overloaded for efficient checking of subscriptions */
569: public void handleTask(Task t,
570: SubscriptionResults subscriptionResults) {
571:
572: if (isDebugEnabled())
573: debug(getName() + ".handleTask : called on task "
574: + t.getUID() + " with " + subscriptionResults);
575:
576: // Need special handling here in case the getSubtasks returns no subtasks
577: // This is possible if not all subscriptions have been "filled"
578: Vector subtasks = getSubtasks(t, subscriptionResults);
579:
580: if (subtasks.size() > 0) {
581: if (isInfoEnabled()) {
582: info(getAgentIdentifier() + " - handleTask: Expanding "
583: + t.getUID() + " with " + subtasks.size()
584: + " subtasks.");
585: }
586:
587: expand.handleTask(ldmf, getBlackboardService(), getName(),
588: wantConfidence, t, subtasks);
589: } else {
590: // postcondition test
591: warn(getAgentIdentifier()
592: + " - publishing no subtasks for " + t.getUID()
593: + " despite having subscription results = "
594: + subscriptionResults);
595: }
596: }
597:
598: /**
599: * Expands the task using information from several different subscriptions
600: * If the key subscriptions have not been filled, as determined by checkSubscriptions(),
601: * then returns an empty Vector, which must be handled appropriately by higher levels.
602: *
603: * @param task the task to expand
604: * @return a vector with the expanded subtask
605: */
606: public Vector getSubtasks(Task task) {
607: Vector subtasks = new Vector();
608:
609: // ==== check buckets to make sure have information required from subcriptions to blackboard
610:
611: SubscriptionResults subscriptionResults = checkSubscriptions();
612:
613: if (subscriptionResults == null) {
614: return subtasks;
615: }
616:
617: return getSubtasks(task, subscriptionResults);
618: }
619:
620: /**
621: * Overloaded for efficient checking of subscriptions.
622: * Returns empty vector if the task is in the past.
623: * (note: still processes task if the deploy time span is null. May need to change this?)
624: *
625: * @return empty vector if org activity is in the past,
626: * or if both person and MEI assets are missing
627: */
628: public Vector getSubtasks(Task task,
629: SubscriptionResults subscriptionResults) {
630: Vector subtasks = new Vector();
631:
632: // TIME-CHECK
633: // First, check time preference on self org to see if the task is in the past.
634: // Compare endDate with the cougaar currentTimeMillis(),
635: // return empty vector if too early so that task is effectively ignored.
636:
637: // get start/end time
638: TimeSpan actTS = subscriptionResults.selfDeployOrgActivity
639: .getTimeSpan();
640: Date thruTime = null, startTime = null;
641: if (actTS != null) {
642: // do we want to fix dates to be after System time?
643: // startDate will be null if OffsetDays days wasn't an command line parameter
644: thruTime = actTS.getEndDate();
645: startTime = actTS.getStartDate();
646: }
647:
648: if (orgActivityInThePast(subscriptionResults)) {
649: long curr = currentTimeMillis();
650: warn(getName()
651: + ": orgActivity for agent "
652: + getAgentIdentifier()
653: + " is in the past, will be ignored: activity thru time: "
654: + thruTime.toString() + " vs. cougaar-time: "
655: + (new Date(curr)).toString());
656: return (new Vector()); // return empty vector
657: }
658:
659: // PREPOSITIONS ====== extract information from buckets and create prepositions
660:
661: Vector prepositions = new Vector();
662:
663: // 1. --------- get FROM geographic location from selfOrg
664:
665: // this is taken from the MilitaryOrgPG
666: GeolocLocation fromLoc = null;
667: org.cougaar.glm.ldm.asset.MilitaryOrgPG milPG = subscriptionResults.selfOrg
668: .getMilitaryOrgPG();
669: if (milPG != null)
670: fromLoc = (GeolocLocation) milPG.getHomeLocation();
671:
672: prepositions.add(prepHelper.makePrepositionalPhrase(ldmf,
673: Constants.Preposition.FROM, fromLoc));
674:
675: // 2. --------- get TO geographic location from selfDeployOrgActivity
676: GeolocLocation toLoc = subscriptionResults.selfDeployOrgActivity
677: .getGeoLoc();
678:
679: prepositions.add(prepHelper.makePrepositionalPhrase(ldmf,
680: Constants.Preposition.TO, toLoc));
681:
682: // 3. ---------- FOR (me) preposition based on selfOrg
683: prepositions.add(prepHelper.makePrepositionalPhrase(ldmf,
684: Constants.Preposition.FOR, subscriptionResults.selfOrg
685: .getItemIdentificationPG()
686: .getItemIdentification()));
687:
688: // 4. ---------- OFTYPE (StrategicTransport)
689: AbstractAsset strans = null;
690: /* May be inefficient due to repeated use of Class.forName() */
691: try {
692: Asset strans_proto = ldmf
693: .createPrototype(
694: Class
695: .forName("org.cougaar.planning.ldm.asset.AbstractAsset"),
696: "StrategicTransportation");
697: strans = (AbstractAsset) ldmf.createInstance(strans_proto);
698: } catch (Exception exc) {
699: error(getAgentIdentifier()
700: + " - Unable to create abstract strategictransport\n"
701: + exc);
702: }
703:
704: prepositions.add(prepHelper.makePrepositionalPhrase(ldmf,
705: Constants.Preposition.OFTYPE, strans));
706:
707: // PREFERENCES ====== extract information from buckets and create preferences
708:
709: Vector preferences = new Vector();
710:
711: // 5. ---------- get start and end time
712:
713: preferences.add(prefHelper.makeStartDatePreference(ldmf,
714: startTime));
715: //preferences.add(prefHelper.makeEndDatePreference(ldmf, thruTime));
716:
717: // Slight hack based upon logic approved by Jeff Berliner
718: // - best time to arrive is 1 day earlier than end time,
719: // and no earlier than 5 days earlier than end time (or actual starttime, whichever is greater)
720: //
721: // This should be changed to use parameter for greater flexibility
722: // END DATE (RDD - 5) <= RDD - 1 <= RDD
723:
724: Date lateEndDate = thruTime;
725: Date bestEndDate = ShortDateFormat.adjustDate(lateEndDate, 0,
726: -1);
727: if (bestEndDate.getTime() < startTime.getTime()) // boundary correction
728: bestEndDate = startTime;
729: Date earlyEndDate = ShortDateFormat.adjustDate(lateEndDate, 0,
730: -5);
731: if (earlyEndDate.getTime() < startTime.getTime()) // boundary correction
732: earlyEndDate = startTime;
733:
734: preferences.add(prefHelper.makeEndDatePreference(ldmf,
735: earlyEndDate, bestEndDate, lateEndDate));
736:
737: // CREATE SUBTASKS
738: // To reach here, must be at least one person or one MEI.
739: //
740: // if only one in a given collection, then that is the directobject
741: // if more than one in given collection, create an assetgroup and add all to that group.
742:
743: Asset personDirectObject = null;
744:
745: // if size 0, then don't create subtask
746: if (subscriptionResults.personAssets.size() > 0) {
747:
748: if (subscriptionResults.personAssets.size() > 1)
749: personDirectObject = assetHelper.makeAssetGroup(ldmf,
750: subscriptionResults.personAssets); // put everything into a single asset group
751: else
752: personDirectObject = (Asset) subscriptionResults.personAssets
753: .get(0);
754:
755: NewTask newPersonSubtask = expandHelper.makeSubTask(ldmf,
756: task, personDirectObject, getAgentIdentifier());
757:
758: newPersonSubtask.setVerb(Constants.Verb.Transport);
759:
760: // ATTACH PREPS and PREFS to SUBTASK
761:
762: newPersonSubtask.setPrepositionalPhrases(prepositions
763: .elements());
764: newPersonSubtask.setPreferences(preferences.elements());
765:
766: // add new subtask to vector
767: subtasks.add(newPersonSubtask);
768: }
769:
770: Asset MEIDirectObject = null;
771:
772: // if size 0, then don't create subtask
773: if (subscriptionResults.MEIAssets.size() > 0) {
774:
775: if (subscriptionResults.MEIAssets.size() > 1)
776: MEIDirectObject = assetHelper.makeAssetGroup(ldmf,
777: subscriptionResults.MEIAssets);
778: else
779: MEIDirectObject = (Asset) subscriptionResults.MEIAssets
780: .get(0);
781:
782: NewTask newMEISubtask = expandHelper.makeSubTask(ldmf,
783: task, MEIDirectObject, getAgentIdentifier());
784:
785: // ATTACH PREPS and PREFS to SUBTASK
786:
787: newMEISubtask.setVerb(Constants.Verb.Transport);
788:
789: newMEISubtask.setPrepositionalPhrases(prepositions
790: .elements());
791: newMEISubtask.setPreferences(preferences.elements());
792:
793: // add new subtask to vector
794: subtasks.add(newMEISubtask);
795: }
796:
797: // postcondition test
798: if (subtasks.isEmpty()) {
799: warn(getAgentIdentifier()
800: + " - producing no subtasks, expecting at least one of people or assets,\n"
801: + "num people "
802: + subscriptionResults.personAssets.size()
803: + " num assets "
804: + subscriptionResults.MEIAssets.size());
805: }
806:
807: return subtasks;
808: }
809:
810: /**
811: * Is the org activity for something in the past?
812: * SubscriptionResults refers to org activity, which has a time span for when it's active.
813: * Compares with current cougaar time (not wall clock time).
814: */
815: public boolean orgActivityInThePast(
816: SubscriptionResults subscriptionResults) {
817: TimeSpan actTS = subscriptionResults.selfDeployOrgActivity
818: .getTimeSpan();
819: Date thruTime = null;
820: if (actTS != null) {
821: // do we want to fix dates to be after System time? (what does this mean?)
822: thruTime = actTS.getEndDate();
823: }
824:
825: if (thruTime != null) {
826: long curr = currentTimeMillis();
827: long thru = thruTime.getTime();
828: return (thru < curr);
829: }
830:
831: if (isWarnEnabled()) {
832: warn(getAgentIdentifier()
833: + " - taskInThePast : thruTime is null in deploy org activity???");
834: }
835:
836: return false;
837: }
838:
839: }
|