001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.mlm.plugin.ldm;
028:
029: import java.io.Serializable;
030:
031: import java.util.Collection;
032: import java.util.Date;
033: import java.util.Enumeration;
034: import java.util.HashMap;
035: import java.util.Iterator;
036: import java.util.Map;
037: import java.util.SortedSet;
038: import java.util.TreeSet;
039:
040: import org.cougaar.core.blackboard.IncrementalSubscription;
041: import org.cougaar.core.logging.LoggingServiceWithPrefix;
042: import org.cougaar.core.plugin.ComponentPlugin;
043: import org.cougaar.core.service.DomainService;
044: import org.cougaar.core.service.LoggingService;
045: import org.cougaar.core.service.UIDService;
046: import org.cougaar.core.util.UID;
047: import org.cougaar.core.util.UniqueObject;
048: import org.cougaar.glm.ldm.Constants;
049: import org.cougaar.glm.ldm.asset.Organization;
050: import org.cougaar.glm.ldm.oplan.Oplan;
051: import org.cougaar.glm.ldm.oplan.OplanFactory;
052: import org.cougaar.glm.ldm.oplan.OplanStage;
053: import org.cougaar.glm.ldm.oplan.OrgActivity;
054: import org.cougaar.glm.ldm.oplan.OrgActivityImpl;
055: import org.cougaar.glm.ldm.oplan.TimeSpan;
056: import org.cougaar.glm.ldm.plan.GeolocLocation;
057: import org.cougaar.mlm.plugin.organization.GLSConstants;
058: import org.cougaar.planning.ldm.PlanningFactory;
059: import org.cougaar.planning.ldm.plan.ContextOfOplanIds;
060: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
061: import org.cougaar.planning.ldm.plan.Task;
062: import org.cougaar.planning.ldm.plan.Verb;
063: import org.cougaar.planning.ldm.plan.Relationship;
064: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
065: import org.cougaar.planning.ldm.plan.Role;
066: import org.cougaar.planning.ldm.asset.Asset;
067: import org.cougaar.util.CSVUtility;
068: import org.cougaar.util.DBProperties;
069: import org.cougaar.util.TimeSpanSet;
070: import org.cougaar.util.UnaryPredicate;
071:
072: public class OplanReaderPlugin extends ComponentPlugin implements
073: GLSConstants {
074: public static final String QUERY_FILE = "oplan.q";
075: public static final String OPLAN_ID_PARAMETER = ":oplanid:";
076: public static final String OPLAN_STAGE_PARAMETER = ":oplanStage:";
077: public static final String AGENT_PARAMETER = ":agent:";
078:
079: private static final String OPLAN_QUERY_HANDLER = "oplanInfoQuery.handler";
080: private static final String ACTIVE_STAGES_HANDLER = "activeStagesQuery.handler";
081: private static final String ORG_ACTIVITY_QUERY_HANDLER = "orgActivityQuery.handler";
082: private static final String LOCATION_QUERY_HANDLERS = "locationQuery.handlers";
083:
084: protected LoggingService logger;
085:
086: private Collection oplans;
087:
088: private Oplan myOplan;
089:
090: private Date cDay;
091:
092: private Map locations = new HashMap();
093:
094: private NewQueryHandler oplanQueryHandler;
095: private NewQueryHandler activeStagesQueryHandler;
096: private NewQueryHandler orgActivityQueryHandler;
097: private DBProperties dbp;
098: private String myPackage;
099: private UIDService uidService;
100: private PlanningFactory theFactory;
101:
102: private static class MyStages implements Serializable {
103: private TreeSet myStages;
104:
105: public MyStages() {
106: myStages = new TreeSet();
107: }
108:
109: public TreeSet getStages() {
110: return myStages;
111: }
112:
113: public void setStages(TreeSet stages) {
114: myStages = stages;
115: }
116: }
117:
118: private MyStages currentStages;
119:
120: private NewOplanPlugin myOplanPlugin = new NewOplanPlugin() {
121: public LoggingService getLoggingService() {
122: return logger;
123: }
124:
125: public GeolocLocation getLocation(String code) {
126: return (GeolocLocation) locations.get(code);
127: }
128:
129: public Date getCDay() {
130: return cDay;
131: }
132:
133: public String getOrgCode() {
134: return orgCode;
135: }
136:
137: public OrgActivity makeOrgActivity(TimeSpan timeSpan,
138: String activity, String geoCode, String opTempo,
139: String opCon) {
140:
141: return OplanReaderPlugin.this .makeOrgActivity(timeSpan,
142: activity, geoCode, opTempo, opCon);
143: }
144: };
145:
146: private static UnaryPredicate myStagesPredicate = new UnaryPredicate() {
147: public boolean execute(Object o) {
148: return o instanceof MyStages;
149: }
150: };
151:
152: // Temporaries used during org activity reading
153: private TimeSpanSet currentActivities = new TimeSpanSet();
154: private TimeSpanSet addedActivities = new TimeSpanSet();
155: private TimeSpanSet changedActivities = new TimeSpanSet();
156: private TimeSpanSet removedActivities = new TimeSpanSet();
157:
158: private IncrementalSubscription glsSubscription;
159: private IncrementalSubscription mySelfOrgs;
160:
161: /** for knowing when we get our self org asset **/
162: private Organization selfOrgAsset = null;
163: private String orgId;
164: private String orgCode;
165: private String adSuperior = null;
166:
167: /**
168: * The predicate for the Socrates subscription
169: **/
170: private static UnaryPredicate selfOrgAssetPred = new UnaryPredicate() {
171: public boolean execute(Object o) {
172: if (o instanceof Organization) {
173: Organization org = (Organization) o;
174: return org.isSelf();
175: }
176: return false;
177: }
178: };
179:
180: private UnaryPredicate glsTaskPredicate = new UnaryPredicate() {
181: public boolean execute(Object o) {
182: if (o instanceof Task) {
183: Task task = (Task) o;
184: Verb verb = task.getVerb();
185: if (verb.equals(Constants.Verb.GetLogSupport)) {
186: PrepositionalPhrase pp = task
187: .getPrepositionalPhrase(FOR_ORGANIZATION);
188: if (pp != null) {
189: return pp.getIndirectObject().equals(
190: selfOrgAsset);
191: }
192: }
193: }
194: return false;
195: }
196: };
197:
198: private static UnaryPredicate oplanPredicate = new UnaryPredicate() {
199: public boolean execute(Object o) {
200: return (o instanceof Oplan);
201: }
202: };
203:
204: private class OrgActivityPredicate implements UnaryPredicate {
205: private UID oplanUID = null;
206:
207: public void setOplan(Oplan oplan) {
208: if (oplan != null)
209: oplanUID = oplan.getUID();
210: }
211:
212: public boolean execute(Object o) {
213: if (oplanUID == null)
214: return false;
215: if (o instanceof OrgActivity) {
216: OrgActivity oa = (OrgActivity) o;
217: return oa.getOplanUID().equals(oplanUID);
218: }
219: return false;
220: }
221: }
222:
223: private OrgActivityPredicate orgActivityPredicate = new OrgActivityPredicate();
224:
225: public void setLoggingService(LoggingService ls) {
226: logger = ls;
227: }
228:
229: public void setDomainService(DomainService ds) {
230: if (ds == null) {
231: theFactory = null;
232: } else {
233: theFactory = (PlanningFactory) ds.getFactory("planning");
234: }
235: }
236:
237: public void setUIDService(UIDService uidService) {
238: this .uidService = uidService;
239: }
240:
241: protected void setupSubscriptions() {
242: String myClassName = getClass().getName();
243: int dot = myClassName.lastIndexOf('.');
244: myPackage = myClassName.substring(0, dot);
245: logger = LoggingServiceWithPrefix.add(logger,
246: getAgentIdentifier() + ": ");
247: mySelfOrgs = (IncrementalSubscription) blackboard
248: .subscribe(selfOrgAssetPred);
249:
250: // refill oplan Collection on rehydrate
251: oplans = blackboard.query(oplanPredicate);
252:
253: Collection c = blackboard.query(myStagesPredicate);
254: if (c.size() > 0) {
255: currentStages = (MyStages) c.iterator().next();
256: } else {
257: currentStages = new MyStages();
258: blackboard.publishAdd(currentStages);
259: }
260:
261: try {
262: Collection fParams = getParameters();
263: if ((fParams == null) || (fParams.size() == 0)) {
264: dbp = DBProperties.readQueryFile(QUERY_FILE).unlock();
265: } else {
266: // Get the query file from the args.
267: String qFile = (String) fParams.iterator().next();
268: dbp = DBProperties.readQueryFile(qFile).unlock();
269: }
270: readLocations();
271: oplanQueryHandler = createQueryHandler(OPLAN_QUERY_HANDLER);
272: activeStagesQueryHandler = createQueryHandler(ACTIVE_STAGES_HANDLER);
273: orgActivityQueryHandler = createQueryHandler(ORG_ACTIVITY_QUERY_HANDLER);
274: } catch (Exception se) {
275: logger.error(this .toString() + ": Initialization failed: ",
276: se);
277: }
278:
279: // test the mySelfOrgs sub to see if it has anything. If so, call processSelfOrgs
280: if (!mySelfOrgs.isEmpty()) {
281: if (logger.isInfoEnabled())
282: logger.info(getAgentIdentifier()
283: + " had selfOrg on sub in setupSubscriptions");
284: processOrgAssets(mySelfOrgs.elements());
285: }
286:
287: // If the above created the glsSub and there are gls tasks there already,
288: // then perhaps we rehydrated, and we need to go get the OrgActivities
289: if (glsSubscription != null && !glsSubscription.isEmpty()) {
290: if (logger.isInfoEnabled())
291: logger
292: .info(getAgentIdentifier()
293: + " in setupSubs and now have a non empty GLS sub -- will get oplans");
294: // It is very hard to process gls tasks incrementally because of
295: // possible oplan removes, etc. In addition, there are
296: // relatively few (e.g. one) such tasks, so we simply process the most
297: // recent gls task.
298:
299: requestOplans(lastGLSTask());
300: }
301: }
302:
303: // Find the most recent gls task, (i.e. one with the highest number of
304: // oplan stages.
305: private Task lastGLSTask() {
306: int maxStageNumber = -1;
307: Task lastGLSTask = null;
308:
309: for (Iterator iterator = glsSubscription.iterator(); iterator
310: .hasNext();) {
311: Task task = (Task) iterator.next();
312: PrepositionalPhrase stagespp = task
313: .getPrepositionalPhrase(FOR_OPLAN_STAGES);
314: SortedSet oplanStages = (SortedSet) stagespp
315: .getIndirectObject();
316: OplanStage lastStage = (OplanStage) oplanStages.last();
317: if (lastStage.getNumber() > maxStageNumber) {
318: maxStageNumber = lastStage.getNumber();
319: lastGLSTask = task;
320: }
321: }
322: return lastGLSTask;
323: }
324:
325: private void readLocations() {
326: NewQueryHandler[] qhs = createQueryHandlers(LOCATION_QUERY_HANDLERS);
327: for (int i = 0; i < qhs.length; i++) {
328: NewQueryHandler qh = qhs[i];
329: if (logger.isDebugEnabled()) {
330: logger.debug("readLocations with " + qh);
331: }
332: try {
333: updateLocations(qh.readCollection());
334: } catch (Exception e) {
335: logger.error("Exception reading locations", e);
336: }
337: }
338: }
339:
340: private NewQueryHandler createQueryHandler(String propName) {
341: NewQueryHandler[] handlers = createQueryHandlers(propName);
342: if (handlers.length < 1) {
343: throw new IllegalArgumentException("No handlers found for "
344: + propName);
345: }
346: if (handlers.length > 1) {
347: throw new IllegalArgumentException(
348: "Multipler handlers found for " + propName);
349: }
350: return handlers[0];
351: }
352:
353: private static Class[] queryHandlerConstructorTypes = {
354: DBProperties.class, NewOplanPlugin.class };
355:
356: private NewQueryHandler[] createQueryHandlers(String propName) {
357: String classNames = dbp.getProperty(propName);
358: String[] handlerClassNames = CSVUtility.parse(classNames);
359: NewQueryHandler[] result = new NewQueryHandler[handlerClassNames.length];
360: Object[] args = { dbp, myOplanPlugin };
361: for (int i = 0; i < result.length; i++) {
362: String className = handlerClassNames[i];
363: if (className.indexOf('.') < 0) {
364: if (myPackage != null) {
365: className = myPackage + "." + className;
366: }
367: }
368: try {
369: result[i] = (NewQueryHandler) Class.forName(className)
370: .getConstructor(queryHandlerConstructorTypes)
371: .newInstance(args);
372: } catch (Exception e) {
373: throw new RuntimeException(
374: "Could not instantiate QueryHandler: "
375: + className, e);
376: }
377: }
378: return result;
379: }
380:
381: private void setupSubscriptions2() {
382: glsSubscription = (IncrementalSubscription) blackboard
383: .subscribe(glsTaskPredicate);
384: blackboard.unsubscribe(mySelfOrgs);
385: mySelfOrgs = null;
386: }
387:
388: private void processOrgAssets(Enumeration e) {
389: if (e.hasMoreElements()) {
390: selfOrgAsset = (Organization) e.nextElement();
391: orgId = selfOrgAsset.getItemIdentificationPG()
392: .getItemIdentification();
393: orgCode = selfOrgAsset.getMilitaryOrgPG().getUIC();
394: adSuperior = getMySuperior();
395: // Setup our other subscriptions now that we know ourself
396: if (glsSubscription == null) {
397: setupSubscriptions2();
398: }
399: }
400: }
401:
402: private String getMySuperior() {
403: String super ior = null;
404: RelationshipSchedule relationshipSchedule = selfOrgAsset
405: .getRelationshipSchedule();
406: Collection adSuperiors = relationshipSchedule
407: .getMatchingRelationships(Constants.Role.ADMINISTRATIVESUPERIOR);
408:
409: if (adSuperiors.size() > 1) {
410: logger.warn(getAgentIdentifier()
411: + " has multiple administrative superiors "
412: + adSuperiors + ". Using the first one.");
413: }
414:
415: for (Iterator it = adSuperiors.iterator(); it.hasNext();) {
416: Relationship rel = (Relationship) it.next();
417: super ior = ((Asset) relationshipSchedule.getOther(rel))
418: .getItemIdentificationPG().getItemIdentification();
419: if (logger.isInfoEnabled()) {
420: logger.info(getAgentIdentifier()
421: + "'s admininistrative superior is: "
422: + super ior);
423: }
424: break;
425: }
426: return super ior;
427: }
428:
429: public synchronized void execute() {
430: if (mySelfOrgs != null && mySelfOrgs.hasChanged()) {
431: if (logger.isDebugEnabled())
432: logger.debug(getAgentIdentifier()
433: + ".execute: selfOrgs sub has changed");
434: processOrgAssets(mySelfOrgs.getAddedList());
435: } else {
436: if (logger.isDebugEnabled())
437: logger
438: .debug(getAgentIdentifier()
439: + ".execute: selfOrgs sub is "
440: + mySelfOrgs
441: + ((mySelfOrgs != null) ? (" and not changed. It has "
442: + mySelfOrgs.size() + " elements.")
443: : " so must have done processOrgAssets."));
444: if (adSuperior == null) {
445: adSuperior = getMySuperior();
446: }
447: }
448:
449: if ((glsSubscription != null) && (!glsSubscription.isEmpty())
450: && (glsSubscription.hasChanged())) {
451: if (logger.isDebugEnabled())
452: logger
453: .debug(getAgentIdentifier()
454: + ".execute: have a changed glsSub - will do requestOplans");
455: // It is very hard to process gls tasks incrementally because of
456: // possible oplan removes, etc. In addition, there are
457: // relatively few (e.g. one) such tasks, so we simply reprocess
458: // all gls tasks whenever there are any changes
459:
460: requestOplans(lastGLSTask());
461: } else if (logger.isInfoEnabled()) {
462: logger
463: .info(getAgentIdentifier()
464: + ".execute not requesting oplans. "
465: + ((glsSubscription != null) ? ("Have a glsSub. Not apparently changed. It has "
466: + glsSubscription.size() + " GLS Tasks.")
467: : "No glsSub. Have not yet apparently done processOrgAssets"));
468: }
469: }
470:
471: private void requestOplans(Task glsTask) {
472: dbp.put(AGENT_PARAMETER, orgId);
473:
474: ContextOfOplanIds cIds = (ContextOfOplanIds) glsTask
475: .getContext();
476: // There should always be exactly one oplan
477: String oplanId = (String) cIds.iterator().next();
478: PrepositionalPhrase c0pp = glsTask
479: .getPrepositionalPhrase(WITH_C0);
480: long c0_date = ((Long) (c0pp.getIndirectObject())).longValue();
481: cDay = new Date(c0_date);
482: myOplan = findOplan(oplanId);
483: dbp.put(OPLAN_ID_PARAMETER, oplanId);
484: if (myOplan == null) {
485: if (logger.isInfoEnabled())
486: logger.info(getAgentIdentifier()
487: + ".requestOplans: no Oplan on BBoard yet.");
488: try {
489: myOplan = (Oplan) oplanQueryHandler.readObject();
490: if (myOplan == null) {
491: logger.error(getAgentIdentifier()
492: + " still has null Oplan for id " + oplanId
493: + "! This agent wont have anything to do!");
494: return;
495: }
496: Number num = (Number) activeStagesQueryHandler
497: .readObject();
498: int minRequiredStage;
499: if (num == null) {
500: minRequiredStage = 0;
501: } else {
502: minRequiredStage = num.intValue();
503: }
504: myOplan.setMinRequiredStage(minRequiredStage);
505: myOplan.setCday(cDay);
506: uidService.registerUniqueObject(myOplan);
507: myOplan.setOwner(getAgentIdentifier());
508: myOplan.setOplanId(oplanId);
509: oplans.add(myOplan);
510: if (logger.isInfoEnabled())
511: logger.info(getAgentIdentifier()
512: + " publishing Oplan");
513: blackboard.publishAdd(myOplan);
514: } catch (Exception e) {
515: logger.error("Exception reading oplan" + oplanId, e);
516: return;
517: }
518: }
519:
520: currentActivities.clear();
521: addedActivities.clear();
522: changedActivities.clear();
523: removedActivities.clear();
524:
525: orgActivityPredicate.setOplan(myOplan);
526: currentActivities
527: .addAll(blackboard.query(orgActivityPredicate));
528:
529: PrepositionalPhrase stagespp = glsTask
530: .getPrepositionalPhrase(FOR_OPLAN_STAGES);
531: SortedSet newStages = (SortedSet) stagespp.getIndirectObject();
532: if (logger.isInfoEnabled())
533: logger
534: .info(getAgentIdentifier()
535: + ".requestOplans: GLS task lists OplanStages size: "
536: + newStages.size()
537: + ". My currentStages has : "
538: + currentStages.getStages().size());
539: boolean currentStagesChanged = false;
540: if (!newStages.containsAll(currentStages.getStages())) {
541: // Some stages have been removed, we start all over
542: // this shouldn't ever happen
543: for (Iterator j = currentActivities.iterator(); j.hasNext();) {
544: OrgActivity oa = (OrgActivity) j.next();
545: removedActivities.add(oa);
546: j.remove();
547: }
548: currentStages.getStages().clear();
549: currentStagesChanged = true;
550: }
551:
552: if (logger.isInfoEnabled())
553: logger.info(getAgentIdentifier()
554: + ".requestOplans: OrgActivities to remove: "
555: + removedActivities.size());
556:
557: SortedSet addedStages = new TreeSet(newStages);
558: addedStages.removeAll(currentStages.getStages()); // Leaves only the added stages
559: for (Iterator j = addedStages.iterator(); j.hasNext();) {
560: OplanStage stage = (OplanStage) j.next();
561: dbp.put(OPLAN_STAGE_PARAMETER, String.valueOf(stage
562: .getNumber()));
563: try {
564: Collection orgActivities = orgActivityQueryHandler
565: .readCollection();
566: updateOrgActivities(myOplan, orgActivities);
567: } catch (Exception e) {
568: logger.error("Error running org activity query", e);
569: }
570: currentStagesChanged = ((currentStages.getStages()
571: .add(stage)) || currentStagesChanged);
572: }
573:
574: if (currentStagesChanged) {
575: blackboard.publishChange(currentStages);
576: if (currentStages.getStages().isEmpty()) {
577: myOplan.setMaxActiveStage(-1); // No stages are active
578: } else {
579: OplanStage maxActiveStage = (OplanStage) newStages
580: .last();
581: myOplan.setMaxActiveStage(maxActiveStage.getNumber());
582: }
583: blackboard.publishChange(myOplan);
584: }
585:
586: for (Iterator j = removedActivities.iterator(); j.hasNext();) {
587: OrgActivity oa = (OrgActivity) j.next();
588: blackboard.publishRemove(oa);
589: }
590:
591: if (logger.isInfoEnabled())
592: logger.info(getAgentIdentifier()
593: + ".requestOplans: OrgActivities to add: "
594: + addedActivities.size());
595:
596: for (Iterator j = addedActivities.iterator(); j.hasNext();) {
597: OrgActivity oa = (OrgActivity) j.next();
598: blackboard.publishAdd(oa);
599: if (logger.isDebugEnabled())
600: logger.debug("Adding OrgActivity: "
601: + oa.getActivityType());
602: }
603:
604: if (logger.isInfoEnabled())
605: logger.info(getAgentIdentifier()
606: + ".requestOplans: OrgActivities to change: "
607: + changedActivities.size());
608:
609: for (Iterator j = changedActivities.iterator(); j.hasNext();) {
610: OrgActivity oa = (OrgActivity) j.next();
611: blackboard.publishChange(oa);
612: }
613: }
614:
615: // Update org activities. The supplied orgActivities override
616: // currentActivities.
617: private void updateOrgActivities(Oplan update,
618: Collection orgActivities) {
619: if (logger.isDebugEnabled()) {
620: logger.debug("updateOrgActivities with "
621: + orgActivities.size() + " activities");
622: }
623: synchronized (oplans) {
624: String oplanID = update.getOplanId();
625: Oplan oplan = findOplan(oplanID);
626: if (oplan == null) {
627: logger
628: .error("GLSInitServlet.updateOrgActivities(): can't find"
629: + " referenced Oplan " + oplanID);
630: return;
631: }
632: // We scan all activities for overlap with each of the new
633: // activities. Were there is overlap, the existing activity is
634: // trimmed to not exist for the timespan of the new activity.
635: // The existing activity is copied, then the time span is
636: // changed. The existing is removed and the copied version
637: // is added.
638:
639: TimeSpanSet[] tsSets = { currentActivities,
640: addedActivities, changedActivities };
641: // For each new org activity, see if it overlaps a current activity
642: for (Iterator i = orgActivities.iterator(); i.hasNext();) {
643: OrgActivity orgActivity = (OrgActivity) i.next();
644: if (logger.isDebugEnabled()) {
645: logger.debug("New OrgActivity is: "
646: + orgActivity.getActivityType() + " "
647: + orgActivity.getTimeSpan());
648: }
649: long newStartTime = orgActivity.getStartTime();
650: long newEndTime = orgActivity.getEndTime();
651: //go thru current activities first then added, then changed
652: // to check for any overlapping timespans
653: for (int k = 0; k < tsSets.length; k++) {
654: TimeSpanSet tsSet = tsSets[k];
655: Collection affectedActivities = tsSet
656: .intersectingSet(orgActivity);
657: for (Iterator j = affectedActivities.iterator(); j
658: .hasNext();) {
659: //found an overlapping activity
660: OrgActivity existingActivity = (OrgActivity) j
661: .next();
662: if (logger.isDebugEnabled()) {
663: logger
664: .debug("Fixing existing org activity "
665: + existingActivity
666: .getActivityType()
667: + " "
668: + existingActivity
669: .getTimeSpan());
670: }
671: tsSet.remove(existingActivity); // Don't know where it will end up,
672: // but it can't be here anymore
673: // See if any part is still viable
674: long existingStartTime = existingActivity
675: .getStartTime();
676: long existingEndTime = existingActivity
677: .getEndTime();
678: //if the existingActivity came from the set of currentActivities
679: // it should be removed from blackboard ultimately because
680: // we will copy the info and make a new one for part and
681: // the newly read OA will cover the other part.
682: boolean existingActivityNeedsRemove = (tsSet == currentActivities);
683: if (existingStartTime < newStartTime) {
684: //the new orgactivity starts later than the existing one so
685: // there is a slice of the existing OA at the start
686: // that is still valid.
687: TimeSpan newTimeSpan = new TimeSpan(
688: existingStartTime, newStartTime);
689: // Need new activity like the existingActivity
690: OrgActivity newActivity = makeOrgActivity(
691: newTimeSpan, existingActivity);
692: if (logger.isDebugEnabled()) {
693: logger
694: .debug("New/Copied org activity is: "
695: + newActivity
696: .getActivityType()
697: + " "
698: + newActivity
699: .getTimeSpan());
700: }
701: addedActivities.add(newActivity);
702: }
703: //Now need to check if the new OA goes longer than the existing
704: if (existingEndTime > newEndTime) {
705: //the new orgactivity ends earlier than the existing one so
706: // there is a slice of the existing OA at the end
707: // that is still valid.
708: //if (existingEndTime < newEndTime) {
709: TimeSpan aNewTimeSpan = new TimeSpan(
710: newEndTime, existingEndTime);
711: // Need new activity like the existingActivity
712: OrgActivity aNewActivity = makeOrgActivity(
713: aNewTimeSpan, existingActivity);
714: if (logger.isDebugEnabled()) {
715: logger
716: .debug("New/Copied org activity is: "
717: + aNewActivity
718: .getActivityType()
719: + " "
720: + aNewActivity
721: .getTimeSpan());
722: }
723: addedActivities.add(aNewActivity);
724: }
725: if (existingActivityNeedsRemove) {
726: blackboard.publishRemove(existingActivity);
727: if (logger.isDebugEnabled()) {
728: logger
729: .debug("Removing activity from blackboard: "
730: + existingActivity
731: .getActivityType()
732: + " "
733: + existingActivity
734: .getTimeSpan());
735: }
736: }
737: }
738: }
739: addedActivities.add(orgActivity);
740: }
741: }
742: }
743:
744: private void updateLocations(Collection locs) {
745: for (Iterator i = locs.iterator(); i.hasNext();) {
746: GeolocLocation location = (GeolocLocation) i.next();
747: String locName = location.getGeolocCode();
748: locations.put(locName, location);
749: }
750: }
751:
752: private Oplan findOplan(String oplanId) {
753: synchronized (oplans) {
754: for (Iterator i = oplans.iterator(); i.hasNext();) {
755: Oplan oplan = (Oplan) i.next();
756: if (oplan.getOplanId().equals(oplanId))
757: return oplan;
758: }
759: return null;
760: }
761: }
762:
763: private OrgActivity makeOrgActivity(TimeSpan timeSpan,
764: String activity, String geoCode, String opTempo,
765: String opCon) {
766:
767: OrgActivityImpl orgActivity = OplanFactory.newOrgActivity(
768: orgId, myOplan.getUID());
769:
770: uidService.registerUniqueObject(orgActivity);
771: orgActivity.setOwner(getAgentIdentifier());
772: orgActivity.setTimeSpan(timeSpan);
773: orgActivity.setActivityType(activity);
774: orgActivity.setGeoLoc((GeolocLocation) locations.get(geoCode));
775: orgActivity.setOpTempo(opTempo);
776: //At the moment - always get adCon from the org_relation table query
777: // which means we can get it from the self org
778:
779: if (adSuperior == null) {
780: if (logger.isWarnEnabled()) {
781: logger
782: .warn(getAgentIdentifier()
783: + ": Missing the AdministrativeSuperior value needed for the OrgActivity!");
784: }
785: } else {
786: orgActivity.setAdCon(adSuperior);
787: }
788:
789: //If no opCon value was read from the database,
790: // set opCon to be same as adCon
791: // This should mean that this is either the Initial Stage
792: // or this agent is a UA agent - either way opCon will
793: // be the same as adCon for the moement.
794:
795: if (opCon == null) {
796: if (adSuperior != null) {
797: orgActivity.setOpCon(adSuperior);
798: if (logger.isDebugEnabled()) {
799: logger
800: .debug("Setting opCon value to adCon value because opCon from DB is null");
801: }
802: } else if (logger.isErrorEnabled()) {
803: logger.error(getAgentIdentifier()
804: + ": No AdSuperior OR OpCon available!");
805: }
806: } else {
807: orgActivity.setOpCon(opCon);
808: }
809: return orgActivity;
810: }
811:
812: private OrgActivity makeOrgActivity(TimeSpan timeSpan,
813: OrgActivity oldActivity) {
814: OrgActivityImpl orgActivity = OplanFactory.newOrgActivity(
815: oldActivity.getOrgID(), oldActivity.getOplanUID());
816: //orgActivity.setAll(oldActivity);
817: orgActivity.setActivityName(oldActivity.getActivityName());
818: orgActivity.setActivityType(oldActivity.getActivityType());
819: orgActivity.setOpTempo(oldActivity.getOpTempo());
820: orgActivity.setGeoLoc(oldActivity.getGeoLoc());
821: orgActivity.setAdCon(oldActivity.getAdCon());
822: orgActivity.setOpCon(oldActivity.getOpCon());
823: orgActivity.setOwner(getAgentIdentifier());
824: uidService.registerUniqueObject(orgActivity);
825: orgActivity.setTimeSpan(timeSpan);
826: return orgActivity;
827: }
828:
829: private Oplan makeOplan() {
830: return new Oplan();
831: }
832: }
|