001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.mlm.plugin.organization;
027:
028: import java.util.ArrayList;
029: import java.util.Calendar;
030: import java.util.Collection;
031: import java.util.Date;
032: import java.util.HashMap;
033: import java.util.Iterator;
034:
035: import org.cougaar.core.blackboard.IncrementalSubscription;
036: import org.cougaar.core.mts.MessageAddress;
037: import org.cougaar.core.util.UID;
038:
039: import org.cougaar.glm.ldm.Constants;
040: import org.cougaar.glm.ldm.asset.Organization;
041: import org.cougaar.glm.ldm.oplan.OrgActivity;
042: import org.cougaar.glm.ldm.oplan.OrgActivityImpl;
043: import org.cougaar.glm.ldm.oplan.Oplan;
044: import org.cougaar.glm.plugins.TaskUtils;
045:
046: import org.cougaar.planning.ldm.plan.AspectType;
047: import org.cougaar.planning.ldm.plan.HasRelationships;
048: import org.cougaar.planning.ldm.plan.NewTask;
049: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
050: import org.cougaar.planning.ldm.plan.Preference;
051: import org.cougaar.planning.ldm.plan.Relationship;
052: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
053: import org.cougaar.planning.ldm.plan.Role;
054: import org.cougaar.planning.ldm.plan.Task;
055: import org.cougaar.planning.ldm.plan.Verb;
056:
057: import org.cougaar.planning.ldm.asset.Asset;
058: import org.cougaar.planning.plugin.asset.AssetDataPlugin;
059:
060: import org.cougaar.util.MutableTimeSpan;
061: import org.cougaar.util.NonOverlappingTimeSpanSet;
062: import org.cougaar.util.TimeSpan;
063: import org.cougaar.util.TimeSpanSet;
064: import org.cougaar.util.UnaryPredicate;
065:
066: public class OrgDataPlugin extends AssetDataPlugin {
067:
068: private static Calendar myCalendar = Calendar.getInstance();
069:
070: private static long DEFAULT_START_TIME = -1;
071: private static long DEFAULT_END_TIME = -1;
072:
073: static {
074: myCalendar.set(1990, 0, 1, 0, 0, 0);
075: DEFAULT_START_TIME = myCalendar.getTime().getTime();
076:
077: myCalendar.set(2010, 0, 1, 0, 0, 0);
078: DEFAULT_END_TIME = myCalendar.getTime().getTime();
079:
080: packages.add("org.cougaar.glm.ldm.asset");
081: packages.add("org.cougaar.glm.ldm.plan");
082: packages.add("org.cougaar.glm.ldm.oplan");
083: packages.add("org.cougaar.glm.ldm.policy");
084: }
085:
086: IncrementalSubscription myOplanSubscription;
087: IncrementalSubscription myOrgActivitySubscription;
088: IncrementalSubscription myOpConInfoRelaySubscription;
089: IncrementalSubscription myRFDSubscription;
090: IncrementalSubscription myOrganizationSubscription;
091:
092: MessageAddress myAgentAddr;
093:
094: // report for duty tasks
095: protected UnaryPredicate myRFDPredicate = new UnaryPredicate() {
096: public boolean execute(Object o) {
097: if (o instanceof Task) {
098: Task task = (Task) o;
099: Verb verb = task.getVerb();
100:
101: // Get the ReportForDuty task where this Agent is reporting to
102: // its OperationalSuperior
103: // -- not its SupportSuperior or AdministrativeSuperior
104: if (Constants.Verb.ReportForDuty.equals(verb)) {
105: PrepositionalPhrase pp = task
106: .getPrepositionalPhrase(org.cougaar.planning.Constants.Preposition.AS);
107: if (pp == null) {
108: return false;
109: }
110:
111: Collection roles = (Collection) pp
112: .getIndirectObject();
113:
114: if (roles == null) {
115: return false;
116: } else {
117: // This collection should contain "Subordinate"
118: return roles
119: .contains(org.cougaar.glm.ldm.Constants.Role.OPERATIONALSUBORDINATE);
120: }
121: }
122: }
123: return false;
124: }
125: };
126:
127: // oplan
128: protected static class OplanPredicate implements UnaryPredicate {
129: public boolean execute(Object o) {
130: return (o instanceof Oplan);
131: }
132: }
133:
134: // org activities
135: protected class OrgActivitiesPredicate implements UnaryPredicate {
136: UID oplanUID_;
137: String orgId_;
138:
139: public OrgActivitiesPredicate(UID uid, String orgId) {
140: oplanUID_ = uid;
141: orgId_ = orgId;
142: }
143:
144: public boolean execute(Object o) {
145: if (o instanceof OrgActivity) {
146: if (oplanUID_.equals(((OrgActivity) o).getOplanUID())
147: && orgId_.equals(((OrgActivity) o).getOrgID())) {
148: return true;
149: }
150: }
151: return false;
152: }
153: }
154:
155: private UnaryPredicate myOpConInfoRelayPredicate = new UnaryPredicate() {
156: public boolean execute(Object o) {
157: if (o instanceof OpConInfoRelay) {
158: OpConInfoRelay relay = (OpConInfoRelay) o;
159: return (myAgentAddr.equals(relay.getSource()));
160: } else {
161: return false;
162: }
163: //return o instanceof OpConInfoRelay;
164: }
165: };
166:
167: private static class OrganizationPredicate implements
168: UnaryPredicate {
169: public boolean execute(Object o) {
170: return o instanceof Organization;
171: }
172: }
173:
174: protected Verb getReportVerb(Collection roles) {
175: // Assuming that collection of roles never mixes subordinate with
176: // provider roles.
177: for (Iterator iterator = roles.iterator(); iterator.hasNext();) {
178: Role role = (Role) iterator.next();
179:
180: // Does this Role match SUPERIOR/SUBORDINATE RelationshipType
181: if ((role.getName()
182: .endsWith(Constants.RelationshipType.SUBORDINATE_SUFFIX))
183: && (role.getConverse().getName()
184: .endsWith(Constants.RelationshipType.SUPERIOR_SUFFIX))) {
185: return Constants.Verb.ReportForDuty;
186: }
187: }
188:
189: // Didn't get a superior/subordinate match
190: return Constants.Verb.ReportForService;
191: }
192:
193: protected void setupSubscriptions() {
194: super .setupSubscriptions();
195: // Set up before the subscriptions so predicates can reference.
196: myAgentAddr = getMessageAddress();
197:
198: myOplanSubscription = (IncrementalSubscription) getBlackboardService()
199: .subscribe(new OplanPredicate());
200: myRFDSubscription = (IncrementalSubscription) getBlackboardService()
201: .subscribe(myRFDPredicate);
202: myOpConInfoRelaySubscription = (IncrementalSubscription) getBlackboardService()
203: .subscribe(myOpConInfoRelayPredicate);
204:
205: myOrganizationSubscription = (IncrementalSubscription) getBlackboardService()
206: .subscribe(new OrganizationPredicate());
207: }
208:
209: public void execute() {
210: if (myOplanSubscription.hasChanged()) {
211:
212: for (Iterator iterator = myOplanSubscription
213: .getAddedCollection().iterator(); iterator
214: .hasNext();) {
215: Oplan oplan = (Oplan) iterator.next();
216: UID oplanUID = oplan.getUID();
217: if (myOrgActivitySubscription == null) {
218: myOrgActivitySubscription = (IncrementalSubscription) getBlackboardService()
219: .subscribe(
220: new OrgActivitiesPredicate(
221: oplanUID,
222: getSelfOrg()
223: .getMessageAddress()
224: .toString()));
225: }
226: }
227: }
228:
229: if ((myOrgActivitySubscription != null)
230: && (myOrgActivitySubscription.hasChanged())) {
231: processPotentialChangedOpCons();
232: }
233:
234: if (myOpConInfoRelaySubscription.hasChanged()) {
235: if (myLogger.isInfoEnabled()) {
236: myLogger
237: .info("myOpConInfoRelaySubscription has changed!");
238: }
239: Collection changedOpConInfoRelays = myOpConInfoRelaySubscription
240: .getChangedCollection();
241:
242: createOperationalRFDs(changedOpConInfoRelays);
243: }
244: }
245:
246: public long getDefaultStartTime() {
247: return DEFAULT_START_TIME;
248: }
249:
250: public long getDefaultEndTime() {
251: return DEFAULT_END_TIME;
252: }
253:
254: protected void processPotentialChangedOpCons() {
255: NonOverlappingTimeSpanSet currentRFDInfos = buildRFDInfos(myRFDSubscription);
256: TimeSpanSet addedRFDInfos = new TimeSpanSet();
257: TimeSpanSet removedRFDInfos = new TimeSpanSet();
258:
259: Collection opConInfoRelays = new ArrayList();
260:
261: NonOverlappingTimeSpanSet orgActivities = new NonOverlappingTimeSpanSet(
262: myOrgActivitySubscription);
263: NonOverlappingTimeSpanSet opconInfos = buildOpConInfos(orgActivities);
264:
265: for (Iterator iterator = opconInfos.iterator(); iterator
266: .hasNext();) {
267: OpConInfo opconInfo = (OpConInfo) iterator.next();
268:
269: Collection affectedRFDInfos = currentRFDInfos
270: .intersectingSet(opconInfo);
271:
272: TimeSpanSet rfdSchedule = new TimeSpanSet(affectedRFDInfos);
273:
274: boolean covered = false;
275: for (Iterator rfdIterator = rfdSchedule.iterator(); rfdIterator
276: .hasNext();) {
277: RFDInfo existingRFDInfo = (RFDInfo) rfdIterator.next();
278:
279: // Check that RFDs map to opCon/Start/End of org activity.
280: // If different, remove and generate new.
281: // DON'T TRY TO BE CLEVER
282: if (covered) {
283: removedRFDInfos.add(existingRFDInfo);
284: } else if ((existingRFDInfo.getOpSuperior()
285: .equals(opconInfo.getOpCon()))
286: && (existingRFDInfo.getStartTime() == opconInfo
287: .getStartTime())
288: && (existingRFDInfo.getEndTime() == opconInfo
289: .getEndTime())) {
290: covered = true;
291: } else {
292: if (myLogger.isInfoEnabled()) {
293: myLogger.info("opconInfo - " + opconInfo
294: + " does not match overlapping RFD - "
295: + existingRFDInfo.getTask());
296: }
297:
298: // Need to make a new rfd for this timespan
299: // Don't know where it will end up,
300: // but it can't be here anymore
301: removedRFDInfos.add(existingRFDInfo);
302:
303: // May not be able to make the new RFD task but no point in
304: // generating additional work
305: covered = true;
306:
307: // Look for local version of OpCon asset
308: Organization localOpCon = findLocalOrganization(opconInfo
309: .getOpCon());
310:
311: // If no local version, send an OpConInfoRelay to agent. Will be
312: // able to build a local version of the asset with the relay
313: // response
314: if (localOpCon == null) {
315: boolean relayExists = false;
316:
317: // Check whether I've already created a relay to this OpCon in
318: // the current execute cycle
319: for (Iterator relayIterator = opConInfoRelays
320: .iterator(); relayIterator.hasNext();) {
321: OpConInfoRelay addedRelay = (OpConInfoRelay) relayIterator
322: .next();
323: if (addedRelay
324: .getTarget()
325: .equals(
326: MessageAddress
327: .getMessageAddress(opconInfo
328: .getOpCon()))) {
329: relayExists = true;
330: break;
331: }
332: }
333:
334: // Have not created a relay so create/publish one
335: if (!relayExists) {
336: OpConInfoRelay opConRelay = createOpConInfoRelay(opconInfo
337: .getOpCon());
338: getBlackboardService().publishAdd(
339: opConRelay);
340: opConInfoRelays.add(opConRelay);
341: }
342: } else {
343: // Have a local copy of the OpCon asset so I can go ahead and
344: // make the corresponding RFDs
345:
346: Task rfdTask = createOpConRFD(localOpCon,
347: opconInfo.getStartTime(), opconInfo
348: .getEndTime());
349: addedRFDInfos.add(new RFDInfo(rfdTask));
350: if (myLogger.isInfoEnabled()) {
351: myLogger.info("New is:" + rfdTask);
352: }
353: }
354: }
355: } // loop over rfds
356: } // loop over opconinfos
357:
358: if (myLogger.isInfoEnabled())
359: myLogger.info("processPotentialChangedOpCons: adding "
360: + addedRFDInfos.size() + " RFDs , removing "
361: + removedRFDInfos.size() + " RFDs.");
362:
363: for (Iterator j = removedRFDInfos.iterator(); j.hasNext();) {
364: Task rfd = ((RFDInfo) j.next()).getTask();
365: getBlackboardService().publishRemove(rfd);
366:
367: if (myLogger.isInfoEnabled())
368: myLogger.info("Removing RFD: " + rfd);
369: }
370:
371: for (Iterator j = addedRFDInfos.iterator(); j.hasNext();) {
372: Task rfd = ((RFDInfo) j.next()).getTask();
373: getBlackboardService().publishAdd(rfd);
374:
375: if (myLogger.isInfoEnabled())
376: myLogger.info("Adding RFD: " + rfd);
377: }
378: }
379:
380: protected void addRelationship(String typeId, String itemId,
381: String otherAgentId, String roleName, long start, long end) {
382: super .addRelationship(typeId, itemId, otherAgentId, roleName,
383: start, end);
384:
385: if (myLogger.isInfoEnabled()) {
386: myLogger.info("added relationship "
387: + " other asset typeid = " + typeId + ", itemId = "
388: + itemId + ", agentId = " + otherAgentId
389: + ", role = " + roleName + ", start = " + start
390: + ", end = " + end);
391: }
392:
393: if (roleName.equals(Constants.Role.ADMINISTRATIVESUBORDINATE
394: .toString())) {
395: if (myLogger.isInfoEnabled()) {
396: myLogger.info("adding OPCON relationship ");
397: }
398:
399: super .addRelationship(typeId, itemId, otherAgentId,
400: Constants.Role.OPERATIONALSUBORDINATE.toString(),
401: start, end);
402: }
403: }
404:
405: private Task createOpConRFD(Asset opCon, long startTime,
406: long endTime) {
407: if (myLogger.isInfoEnabled()) {
408: myLogger.info("creating an RFD from " + myAgentAddr
409: + " to " + opCon);
410: }
411:
412: Asset localClone = myPlanningFactory
413: .cloneInstance(myLocalAsset);
414: Asset sendTo = myPlanningFactory.cloneInstance(opCon);
415:
416: Collection roles = new ArrayList();
417: roles
418: .add(org.cougaar.glm.ldm.Constants.Role.OPERATIONALSUBORDINATE);
419:
420: Task rfdTask = createReportTask(localClone, sendTo, roles,
421: startTime, endTime);
422: return rfdTask;
423: }
424:
425: private OpConInfoRelay createOpConInfoRelay(String opCon) {
426: //sending a relay to the opcon from the orgActivity
427: MessageAddress targetAddr = MessageAddress
428: .getMessageAddress(opCon);
429: OpConInfoRelay opconRelay = new OpConInfoRelay(getUIDService()
430: .nextUID(), myAgentAddr, targetAddr, null, null);
431: if (myLogger.isInfoEnabled()) {
432: myLogger.info("just created an OpConInfoRelay: "
433: + opconRelay.toString() + " from " + myAgentAddr
434: + " to " + targetAddr);
435: }
436:
437: return opconRelay;
438: }
439:
440: private void createOperationalRFDs(Collection changedOpConInfoRelays) {
441: HashMap relayMap = new HashMap();
442:
443: NonOverlappingTimeSpanSet rfdInfos = buildRFDInfos(myRFDSubscription);
444:
445: NonOverlappingTimeSpanSet orgActivities = new NonOverlappingTimeSpanSet(
446: myOrgActivitySubscription);
447: NonOverlappingTimeSpanSet opconInfos = buildOpConInfos(orgActivities);
448:
449: for (Iterator changes = changedOpConInfoRelays.iterator(); changes
450: .hasNext();) {
451: OpConInfoRelay relay = (OpConInfoRelay) changes.next();
452:
453: TimeSpan content = (TimeSpan) relay.getContent();
454: ArrayList response = (ArrayList) relay.getResponse();
455:
456: if (myLogger.isInfoEnabled()) {
457: myLogger.info("OpConInfoRelay content = " + content
458: + " response = " + response);
459: }
460:
461: if ((response == null) || (response.size() < 2)) {
462: if (myLogger.isDebugEnabled()) {
463: myLogger.debug("ignoring invalid response.");
464: }
465: } else {
466: String opConItemId = (String) response.get(0);
467: String opConTypeId = (String) response.get(1);
468:
469: if (relayMap.containsKey(opConItemId)) {
470: if (myLogger.isInfoEnabled()) {
471: myLogger.info("ignoring OpConInfoRelay "
472: + relay
473: + " already added required RFDs.");
474: }
475: } else {
476: relayMap.put(opConItemId, relay);
477: boolean usedRelay = false;
478:
479: // Iterate over OrgActivities to see whether there are RFDs for
480: // OpCons specified by the OrgActivities.
481: for (Iterator iterator = opconInfos.iterator(); iterator
482: .hasNext();) {
483: OpConInfo opconInfo = (OpConInfo) iterator
484: .next();
485:
486: // Only interested if OpCon is the same. Trust that OpConInfoRelays
487: // have been sent out for other missing OpCons.
488: if (opconInfo.getOpCon().equals(opConItemId)) {
489: // Is time span already covered?
490: Collection affectedRFDInfos = rfdInfos
491: .intersectingSet(opconInfo);
492:
493: if (!(affectedRFDInfos.isEmpty())) {
494: // Existence of any RFDs means that we had the info to make
495: // all RFDs to this OpCon. Let processPotentialChangedOpCons()
496: // ensure that entire time period is covered.
497: continue;
498: }
499:
500: // Make RFD
501: MessageAddress maTarget = relay.getTarget();
502: String relTargetAddr = (String) maTarget
503: .getAddress();
504:
505: Asset otherAsset = getAsset(
506: myAssetClassName, opConItemId,
507: opConTypeId, maTarget.getAddress());
508: Relationship relationship = myPlanningFactory
509: .newRelationship(
510: (Constants.Role.OPERATIONALSUBORDINATE),
511: (HasRelationships) myLocalAsset,
512: (HasRelationships) otherAsset,
513: opconInfo.getStartTime(),
514: opconInfo.getEndTime());
515: report(relationship);
516:
517: if (myLogger.isInfoEnabled()) {
518: myLogger.info(" published RFD to "
519: + maTarget
520: + " for "
521: + new Date(opconInfo
522: .getStartTime())
523: + " to "
524: + new Date(opconInfo
525: .getEndTime()));
526: }
527:
528: usedRelay = true;
529: }
530: }
531:
532: if ((!usedRelay) && (myLogger.isInfoEnabled())) {
533: myLogger.info("ignoring OpConInfoRelay "
534: + relay
535: + " required RFDs already exist.");
536: }
537: }
538: }
539: // General clean up
540: publishRemove(relay);
541: } // loop over changed opconinfo relays
542: }
543:
544: private Organization findLocalOrganization(String itemID) {
545: // Find matching Organization
546: for (Iterator iterator = myOrganizationSubscription.iterator(); iterator
547: .hasNext();) {
548: Organization organization = (Organization) iterator.next();
549: if (organization.getItemIdentificationPG()
550: .getItemIdentification().equals(itemID)) {
551: return organization;
552: }
553: }
554:
555: return null;
556: }
557:
558: private Organization getSelfOrg() {
559: // Find matching Organization
560: for (Iterator iterator = myOrganizationSubscription.iterator(); iterator
561: .hasNext();) {
562: Organization organization = (Organization) iterator.next();
563: if (organization.isSelf()) {
564: return organization;
565: }
566: }
567:
568: return null;
569: }
570:
571: private NonOverlappingTimeSpanSet buildRFDInfos(Collection rfdTasks) {
572:
573: NonOverlappingTimeSpanSet rfdInfos = new NonOverlappingTimeSpanSet();
574:
575: // Go thru current set of RFD tasks and extract the start
576: // and end times as well as the operational superior
577: // Make RFDInfo objects to be compared against
578: for (Iterator it = rfdTasks.iterator(); it.hasNext();) {
579: Task rfdTask = (Task) it.next();
580:
581: RFDInfo rfdInfo = new RFDInfo(rfdTask);
582: rfdInfos.add(rfdInfo);
583: }
584:
585: return rfdInfos;
586: }
587:
588: private Relationship getAdConRelationship() {
589: // Depends on the assumption that an Organization ALWAYS has an
590: // AdCon and that AdCon does not change.
591: Organization selfOrg = getSelfOrg();
592: if (selfOrg == null) {
593: // ERROR - should never have OrgActivities w/o a self org.
594: myLogger.error(
595: "getAdConRelationship ran but selfOrg is null!",
596: new Throwable());
597: return null;
598: } else {
599: RelationshipSchedule relationshipSchedule = selfOrg
600: .getRelationshipSchedule();
601: Collection relationships = relationshipSchedule
602: .getMatchingRelationships(Constants.Role.ADMINISTRATIVESUPERIOR);
603: if (relationships.isEmpty()) {
604: // OrgDataPlugin is intended for only complex users - with Oplans and
605: // OpCons and AdCons. Try using SimpleOrgDataPlugin, or, even better
606: // org.cougaar.planning.plugin.asset.AssetDataPlugin
607: myLogger
608: .error(
609: "getAdConRelationship found no AdministrativeSuperior! Should you be using SimpleOrgDataPlugin?",
610: new Throwable(
611: "No AdministrativeSuperior for "
612: + selfOrg
613: .getMessageAddress()));
614: } else if (relationships.size() != 1) {
615: myLogger.error("getAdConRelationship - "
616: + " found multiple administrative superiors "
617: + relationships + " choice is random.");
618: }
619:
620: for (Iterator relationshipIterator = relationships
621: .iterator(); relationshipIterator.hasNext();) {
622: return (Relationship) relationshipIterator.next();
623: }
624: }
625: return null;
626: }
627:
628: private void handlePreOrgActivityOpCon(
629: Relationship adConRelationship, TimeSpanSet orgActivities,
630: TimeSpanSet currentRFDInfos, TimeSpanSet addedRFDInfos,
631: TimeSpanSet removedRFDInfos) {
632:
633: Organization adCon = null;
634:
635: if (adConRelationship != null) {
636: adCon = (Organization) getSelfOrg()
637: .getRelationshipSchedule().getOther(
638: adConRelationship);
639: }
640: boolean covered = false;
641:
642: TimeSpan firstOrgActivity = (TimeSpan) orgActivities.first();
643:
644: // Before OrgActivities
645: for (Iterator iterator = currentRFDInfos.iterator(); iterator
646: .hasNext();) {
647: RFDInfo rfdInfo = (RFDInfo) iterator.next();
648:
649: if (rfdInfo.getEndTime() <= firstOrgActivity.getStartTime()) {
650: // Verify that OpCon == AdCon
651: // Want a single default OpCon which starts with the AdCon and ends
652: // when the OrgActivities start
653: if (adCon == null) {
654: removedRFDInfos.add(rfdInfo);
655: } else if ((adCon.getItemIdentificationPG()
656: .getItemIdentification().equals(rfdInfo
657: .getOpSuperior()))
658: && (rfdInfo.getStartTime() == adConRelationship
659: .getStartTime())
660: || (rfdInfo.getEndTime() == firstOrgActivity
661: .getStartTime())) {
662: covered = true;
663: } else {
664: removedRFDInfos.add(rfdInfo);
665: }
666: } else {
667: // moved into time period covered by org activities
668: break;
669: }
670: }
671:
672: if (!covered) {
673: Task rfdTask = createOpConRFD(adCon, adConRelationship
674: .getStartTime(), firstOrgActivity.getStartTime());
675: addedRFDInfos.add(new RFDInfo(rfdTask));
676: }
677: }
678:
679: private void handlePostOrgActivityOpCon(
680: Relationship adConRelationship, TimeSpanSet orgActivities,
681: TimeSpanSet currentRFDInfos, TimeSpanSet addedRFDInfos,
682: TimeSpanSet removedRFDInfos) {
683:
684: Organization adCon = null;
685:
686: if (adConRelationship != null) {
687: adCon = (Organization) getSelfOrg()
688: .getRelationshipSchedule().getOther(
689: adConRelationship);
690: }
691: boolean covered = false;
692:
693: TimeSpan lastOrgActivity = (TimeSpan) orgActivities.last();
694:
695: for (Iterator iterator = currentRFDInfos.iterator(); iterator
696: .hasNext();) {
697: RFDInfo rfdInfo = (RFDInfo) iterator.next();
698:
699: if (rfdInfo.getStartTime() >= lastOrgActivity.getEndTime()) {
700: // Verify that OpCon == AdCon
701: // Want a single default opCon which starts when Org Activities end and
702: // continues to the same end date as the AdCon
703: if (adCon == null) {
704: removedRFDInfos.add(rfdInfo);
705: } else if ((adCon.getItemIdentificationPG()
706: .getItemIdentification().equals(rfdInfo
707: .getOpSuperior()))
708: || (rfdInfo.getStartTime() == lastOrgActivity
709: .getEndTime())
710: || (rfdInfo.getEndTime() == adConRelationship
711: .getEndTime())) {
712: covered = true;
713: } else {
714: removedRFDInfos.add(rfdInfo);
715: }
716: }
717: }
718:
719: if (!covered) {
720: Task rfdTask = createOpConRFD(adCon, lastOrgActivity
721: .getEndTime(), adConRelationship.getEndTime());
722: addedRFDInfos.add(new RFDInfo(rfdTask));
723: }
724: }
725:
726: private NonOverlappingTimeSpanSet buildOpConInfos(
727: NonOverlappingTimeSpanSet orgActivities) {
728: NonOverlappingTimeSpanSet opconInfos = new NonOverlappingTimeSpanSet();
729: String currentOpCon = null;
730:
731: Relationship adConRelationship = getAdConRelationship();
732: Organization adCon = null;
733:
734: if (adConRelationship == null) {
735: // FIXME: Not an error for the older style oplan.xml societies
736: myLogger.error("buildOpConInfos - no AdConRelationship.");
737: return opconInfos;
738: } else {
739: adCon = (Organization) getSelfOrg()
740: .getRelationshipSchedule().getOther(
741: adConRelationship);
742:
743: if (myLogger.isDebugEnabled()) {
744: myLogger.debug("adConRelationship = "
745: + adConRelationship);
746: }
747: }
748: String adconName = adCon.getItemIdentificationPG()
749: .getItemIdentification();
750:
751: String opconName;
752: long startTime;
753: long endTime;
754:
755: if (orgActivities.isEmpty()) {
756: if (adCon != null) {
757: OpConInfo adconInfo = new OpConInfo(adconName,
758: adConRelationship.getStartTime(),
759: adConRelationship.getEndTime());
760: opconInfos.add(adconInfo);
761: }
762: return opconInfos;
763: }
764:
765: OrgActivity firstOrgActivity = (OrgActivity) orgActivities
766: .first();
767:
768: if ((adCon != null)
769: && (firstOrgActivity.getStartTime() > adConRelationship
770: .getStartTime())) {
771: // Start with adcon Info
772: opconName = adconName;
773: startTime = adConRelationship.getStartTime();
774: endTime = adConRelationship.getEndTime();
775: } else {
776: opconName = firstOrgActivity.getOpCon();
777: startTime = firstOrgActivity.getStartTime();
778: endTime = firstOrgActivity.getEndTime();
779: }
780:
781: for (Iterator iterator = orgActivities.iterator(); iterator
782: .hasNext();) {
783: OrgActivity orgActivity = (OrgActivity) iterator.next();
784:
785: if (!orgActivity.getOpCon().equals(opconName)) {
786: OpConInfo opConInfo = new OpConInfo(opconName,
787: startTime, endTime);
788: opconInfos.add(opConInfo);
789:
790: opconName = orgActivity.getOpCon();
791: startTime = orgActivity.getStartTime();
792: }
793:
794: endTime = orgActivity.getEndTime();
795: }
796:
797: if ((adCon == null)
798: || (adConRelationship.getEndTime() < endTime)) {
799: OpConInfo opConInfo = new OpConInfo(opconName, startTime,
800: endTime);
801: opconInfos.add(opConInfo);
802: } else {
803: if (!opconName.equals(adconName)) {
804: OpConInfo opConInfo = new OpConInfo(opconName,
805: startTime, endTime);
806: opconInfos.add(opConInfo);
807: startTime = endTime;
808: }
809:
810: OpConInfo opConInfo = new OpConInfo(adconName, startTime,
811: adConRelationship.getEndTime());
812: opconInfos.add(opConInfo);
813: }
814:
815: if (myLogger.isDebugEnabled()) {
816: myLogger.debug("buildOpConInfos returning " + opconInfos);
817: }
818:
819: return opconInfos;
820: }
821:
822: private static class OpConInfo extends MutableTimeSpan {
823: String myOpConName = null;
824:
825: public OpConInfo(String opConName, TimeSpan timeSpan) {
826: this (opConName, timeSpan.getStartTime(), timeSpan
827: .getEndTime());
828: }
829:
830: public OpConInfo(String opConName, long startTime, long endTime) {
831: super ();
832:
833: setTimeSpan(startTime, endTime);
834: myOpConName = opConName;
835: }
836:
837: public String getOpCon() {
838: return myOpConName;
839: }
840:
841: public boolean equals(Object o) {
842: if (o instanceof OpConInfo) {
843: OpConInfo opConInfo = (OpConInfo) o;
844: return ((opConInfo.getStartTime() == getStartTime())
845: && (opConInfo.getEndTime() == getEndTime()) && (opConInfo
846: .getOpCon().equals(getOpCon())));
847: } else {
848: return false;
849: }
850: }
851:
852: public String toString() {
853: StringBuffer buf = new StringBuffer();
854: buf.append("start=" + new Date(getStartTime()) + ", end="
855: + new Date(getEndTime()));
856:
857: buf.append(", opCon=" + myOpConName);
858: buf.append("]");
859:
860: return buf.toString();
861: }
862: }
863:
864: private static class RFDInfo implements org.cougaar.util.TimeSpan {
865: Task myTask;
866: long myStart;
867: long myEnd;
868: String myOpSuperior;
869:
870: RFDInfo(Task t) {
871: myTask = t;
872: myStart = TaskUtils.getStartTime(t);
873: myEnd = TaskUtils.getEndTime(t);
874: setOpSuperior(t);
875: }
876:
877: private void setOpSuperior(Task t) {
878: PrepositionalPhrase pp = t
879: .getPrepositionalPhrase(org.cougaar.planning.Constants.Preposition.FOR);
880: myOpSuperior = ((Asset) pp.getIndirectObject())
881: .getItemIdentificationPG().getItemIdentification();
882: }
883:
884: public String getOpSuperior() {
885: return myOpSuperior;
886: }
887:
888: public long getStartTime() {
889: return myStart;
890: }
891:
892: public long getEndTime() {
893: return myEnd;
894: }
895:
896: public Task getTask() {
897: return myTask;
898: }
899: }
900: }
|