0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 1997-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026:
0027: package org.cougaar.mlm.plugin.sample;
0028:
0029: import java.util.Collection;
0030: import java.util.Date;
0031: import java.util.Enumeration;
0032: import java.util.Iterator;
0033: import java.util.Vector;
0034:
0035: import org.cougaar.core.blackboard.IncrementalSubscription;
0036: import org.cougaar.core.service.LoggingService;
0037: import org.cougaar.core.util.UID;
0038: import org.cougaar.glm.ldm.Constants;
0039: import org.cougaar.glm.ldm.asset.ClassVIIMajorEndItem;
0040: import org.cougaar.glm.ldm.asset.MovabilityPG;
0041: import org.cougaar.glm.ldm.asset.Organization;
0042: import org.cougaar.glm.ldm.asset.Person;
0043: import org.cougaar.glm.ldm.oplan.Oplan;
0044: import org.cougaar.glm.ldm.oplan.OrgActivity;
0045: import org.cougaar.glm.ldm.oplan.TimeSpan;
0046: import org.cougaar.glm.ldm.plan.GeolocLocation;
0047: import org.cougaar.glm.xml.parser.LocationParser;
0048: import org.cougaar.planning.ldm.PlanningFactory;
0049: import org.cougaar.planning.ldm.asset.AbstractAsset;
0050: import org.cougaar.planning.ldm.asset.AggregateAsset;
0051: import org.cougaar.planning.ldm.asset.Asset;
0052: import org.cougaar.planning.ldm.asset.AssetGroup;
0053: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
0054: import org.cougaar.planning.ldm.asset.TypeIdentificationPGImpl;
0055: import org.cougaar.planning.ldm.plan.Allocation;
0056: import org.cougaar.planning.ldm.plan.AllocationResult;
0057: import org.cougaar.planning.ldm.plan.AspectType;
0058: import org.cougaar.planning.ldm.plan.AspectValue;
0059: import org.cougaar.planning.ldm.plan.Expansion;
0060: import org.cougaar.planning.ldm.plan.MPTask;
0061: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
0062: import org.cougaar.planning.ldm.plan.NewTask;
0063: import org.cougaar.planning.ldm.plan.NewWorkflow;
0064: import org.cougaar.planning.ldm.plan.PlanElement;
0065: import org.cougaar.planning.ldm.plan.Preference;
0066: import org.cougaar.planning.ldm.plan.ScoringFunction;
0067: import org.cougaar.planning.ldm.plan.Task;
0068: import org.cougaar.planning.ldm.plan.Workflow;
0069: import org.cougaar.planning.plugin.legacy.SimplePlugin;
0070: import org.cougaar.planning.plugin.util.ExpanderHelper;
0071: import org.cougaar.planning.plugin.util.PluginHelper;
0072: import org.cougaar.util.DynamicUnaryPredicate;
0073: import org.cougaar.util.ShortDateFormat;
0074: import org.cougaar.util.UnaryPredicate;
0075: import org.w3c.dom.Document;
0076: import org.w3c.dom.Node;
0077:
0078: /**
0079: * Class <code>StrategicTransportProjectorPlugin</code> is a replacement
0080: * for <code>StrategicTranportProjectionExpanderPlugin</code>.
0081: * <p>
0082: * This class subscribes to the single "Deploy" "DetermineRequirements"
0083: * Task and expands it to "Transport" Tasks for all applicable assets.
0084: * <p>
0085: * Currently expects only one oplan, one "self" org activity, and one
0086: * "Deploy" "DetermineRequirements" task.
0087: * <p>
0088: * Debug information is now off by default. See method <code>setDebug()</code>
0089: */
0090: public class StrategicTransportProjectorPlugin extends SimplePlugin {
0091:
0092: public final static long MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
0093:
0094: /** Self Organization Info **/
0095: protected IncrementalSubscription selfOrgsSub;
0096: // On rejydration filled in from selfOrgsSub;
0097: protected Organization selfOrg;
0098: protected String selfOrgId = "XXXSelfOrgNotSetYet";
0099:
0100: /** Subscription to orgActivities for Deployment **/
0101: protected IncrementalSubscription orgDeployActsSub;
0102:
0103: /** Subscription to DetermineRequirement Tasks **/
0104: protected IncrementalSubscription drTasksSub;
0105:
0106: /** Subscription to Transportable Person Assets **/
0107: protected IncrementalSubscription transAssetsPersonSub;
0108:
0109: /** Subscription to Transportable Equipment Assets **/
0110: protected IncrementalSubscription transAssetsEquipmentSub;
0111:
0112: /** Subscription to Failed Allocations **/
0113: protected IncrementalSubscription failedDRAllocsSub;
0114:
0115: /** Subscription to Expansions **/
0116: protected IncrementalSubscription expansionsSub;
0117:
0118: // Following set from invocation parameters
0119: /** Expand into an AssetGroup if true, else separate Tasks if false **/
0120: protected boolean createAssetGroups = true;
0121:
0122: // /** delay re-processing DetermineRequirement Tasks by specified millis **/
0123: // protected long delayReprocessMillis;
0124:
0125: /** Defaults optionally set by parameters. **/
0126: protected int defaultAdjustDurationDays;
0127:
0128: /** XML file containing description of GeolocLocation used for Task fromLocation **/
0129: protected String originFile = null;
0130:
0131: /** Number of days added to the Oplan C Day used for Task startDate **/
0132: protected int offsetDays = 0;
0133:
0134: /** GeolocLocation specified in XML file used for Task fromLocation **/
0135: protected GeolocLocation overrideFromLocation = null;
0136:
0137: /** Holder for info required to handle the determine requirements task. **/
0138: protected DeployPlan singleDeployPlan = null;
0139:
0140: /**
0141: * Subscribe.
0142: */
0143: protected void setupSubscriptions() {
0144: if (logger.isInfoEnabled()) {
0145: printInfo(getClass() + " setting up subscriptions");
0146: }
0147:
0148: setDefaults(getParameters().elements());
0149:
0150: selfOrgsSub = (IncrementalSubscription) subscribe(newSelfOrgPred());
0151:
0152: orgDeployActsSub = (IncrementalSubscription) subscribe(newOrgDeployActsPred());
0153:
0154: drTasksSub = (IncrementalSubscription) subscribe(newDRTasksPred());
0155:
0156: transAssetsPersonSub = (IncrementalSubscription) subscribe(newTransPersonPred());
0157:
0158: transAssetsEquipmentSub = (IncrementalSubscription) subscribe(newTransEquipmentPred());
0159:
0160: failedDRAllocsSub = (IncrementalSubscription) subscribe(newFailedDRAllocPred());
0161:
0162: expansionsSub = (IncrementalSubscription) subscribe(newExpansionsPred());
0163:
0164: if (originFile != null) {
0165: overrideFromLocation = getGeoLoc(originFile);
0166: }
0167:
0168: // Fill in state from subscriptions if rehydrating
0169: if (didRehydrate()) {
0170: // Try to fill in self org info
0171: if (!selfOrgsSub.isEmpty()) {
0172: watchAddedSelfOrgs(selfOrgsSub.elements());
0173: }
0174:
0175: //Initialize deployPlan
0176: if (!orgDeployActsSub.isEmpty()) {
0177: OrgActivity selfOrgAct = findSelfOrgDeployAct(orgDeployActsSub
0178: .elements());
0179: if (selfOrgAct != null) {
0180: replaceDeployPlan(selfOrgAct);
0181: }
0182: }
0183: }
0184: }
0185:
0186: /**
0187: * Execute.
0188: */
0189: protected void execute() {
0190:
0191: if (selfOrgsSub.hasChanged()) {
0192: if (logger.isInfoEnabled()) {
0193: printInfo("selfOrgs hasChanged");
0194: }
0195: watchAddedSelfOrgs(selfOrgsSub.getAddedList());
0196: }
0197:
0198: if (orgDeployActsSub.hasChanged()) {
0199: if (logger.isInfoEnabled()) {
0200: printInfo("orgDeployActs hasChanged");
0201: }
0202: watchChangedOrgDeployActs(orgDeployActsSub.getChangedList());
0203: watchRemovedOrgDeployActs(orgDeployActsSub.getRemovedList());
0204: watchAddedOrgDeployActs(orgDeployActsSub.getAddedList());
0205: }
0206:
0207: if (drTasksSub.hasChanged()) {
0208: if (logger.isInfoEnabled()) {
0209: printInfo("DetermineReqs Tasks hasChanged - changed "
0210: + drTasksSub.getChangedList() + " added "
0211: + drTasksSub.getAddedList() + " removed "
0212: + drTasksSub.getRemovedList());
0213: }
0214: updateDetermineRequirementsTask();
0215: }
0216:
0217: if (transAssetsPersonSub.hasChanged()) {
0218: if (logger.isInfoEnabled()) {
0219: printInfo("Transportable Assets hasChanged");
0220: }
0221: // watchChangedTransportableAssets(transAssetsPersonSub.getChangedList());
0222: watchRemovedTransportableAssets(transAssetsPersonSub
0223: .getRemovedList());
0224: watchAddedTransportableAssets(transAssetsPersonSub
0225: .getAddedList());
0226: }
0227:
0228: if (transAssetsEquipmentSub.hasChanged()) {
0229: if (logger.isInfoEnabled()) {
0230: printInfo("Transportable Assets hasChanged");
0231: }
0232: // watchChangedTransportableAssets(transAssetsEquipmentSub.getChangedList());
0233: watchRemovedTransportableAssets(transAssetsEquipmentSub
0234: .getRemovedList());
0235: watchAddedTransportableAssets(transAssetsEquipmentSub
0236: .getAddedList());
0237: }
0238:
0239: if (failedDRAllocsSub.hasChanged()) {
0240: if (logger.isInfoEnabled()) {
0241: printInfo("Failed DR Subtask Allocation hasChanged");
0242: }
0243: watchFailedDispositions(failedDRAllocsSub.getChangedList());
0244: }
0245:
0246: if (expansionsSub.hasChanged()) {
0247: PluginHelper.updateAllocationResult(expansionsSub);
0248: }
0249:
0250: }
0251:
0252: /**
0253: * Only one plan with one "Deployment" DetermineRequirements Task expected!
0254: */
0255:
0256: protected DeployPlan getDeployPlan() {
0257: return singleDeployPlan;
0258: }
0259:
0260: protected void setDeployPlan(DeployPlan dp) {
0261: singleDeployPlan = dp;
0262: }
0263:
0264: /**
0265: * These methods related to having a single oplan, a single self
0266: * organization, a single self OrgActivity, and a single
0267: * "Deployment" "DetermineRequirements" Task.
0268: */
0269:
0270: protected void watchAddedSelfOrgs(Enumeration eSelfOrgs) {
0271: while (eSelfOrgs.hasMoreElements()) {
0272: Organization org = (Organization) eSelfOrgs.nextElement();
0273: if (this .selfOrg != null) {
0274: printError("Expecting only one \"SELF\" Organization! ignoring "
0275: + org);
0276: continue;
0277: }
0278: this .selfOrg = org;
0279: this .selfOrgId = getOrgID(selfOrg);
0280: if (logger.isInfoEnabled()) {
0281: printInfo("Found Self: " + this .selfOrgId);
0282: }
0283: watchAddedOrgDeployActs(orgDeployActsSub.elements());
0284: }
0285: }
0286:
0287: protected OrgActivity findSelfOrgDeployAct(Enumeration eOrgActs) {
0288: while (true) {
0289: if (!(eOrgActs.hasMoreElements())) {
0290: // self not listed
0291: return null;
0292: }
0293: OrgActivity orgAct = (OrgActivity) eOrgActs.nextElement();
0294: if (selfOrgId.equals(orgAct.getOrgID())) {
0295: // found self org activity
0296: return orgAct;
0297: }
0298: }
0299: }
0300:
0301: protected void watchAddedOrgDeployActs(Enumeration eOrgActs) {
0302: OrgActivity selfOrgAct = findSelfOrgDeployAct(eOrgActs);
0303: if (selfOrgAct != null) {
0304: watchAddedSelfOrgDeployAct(selfOrgAct);
0305: }
0306: }
0307:
0308: protected void watchChangedOrgDeployActs(Enumeration eOrgActs) {
0309: OrgActivity selfOrgAct = findSelfOrgDeployAct(eOrgActs);
0310: if (selfOrgAct != null) {
0311: watchChangedSelfOrgDeployAct(selfOrgAct);
0312: }
0313: }
0314:
0315: protected void watchRemovedOrgDeployActs(Enumeration eOrgActs) {
0316: OrgActivity selfOrgAct = findSelfOrgDeployAct(eOrgActs);
0317: if (selfOrgAct != null) {
0318: watchRemovedSelfOrgDeployAct(selfOrgAct);
0319: }
0320: }
0321:
0322: // protected void watchDueDetermineRequirementsTasks() {
0323: // if ((unhandledDetermineRequirementsTask != null) &&
0324: // (unhandledDetermineRequirementsTask.isDue())) {
0325: // if (logger.isInfoEnabled()) {
0326: // printInfo("watchDueDetermineRequirementsTask - resubmitting dr task");
0327: // }
0328: // handleDetermineRequirementsTask(unhandledDetermineRequirementsTask.task);
0329: // }
0330: // else if (logger.isInfoEnabled ()) {
0331: // printDebug("watchDueDetermineRequirementsTask - ignoring call to watch due, since unhandled d.r. is " +
0332: // unhandledDetermineRequirementsTask +
0333: // ((unhandledDetermineRequirementsTask == null) ? "" : " or isDue is " +
0334: // unhandledDetermineRequirementsTask.isDue ()));
0335: // }
0336: // }
0337:
0338: protected Task getDetermineRequirementsTask() {
0339: Iterator i = drTasksSub.iterator();
0340: if (i.hasNext()) {
0341: Task drTask = (Task) i.next();
0342: if (i.hasNext()) {
0343: // should be only one determine requirements task
0344: printError("Expecting only one DetermineReqs Task! ignoring the others");
0345: }
0346: return drTask;
0347: }
0348: return null;
0349: }
0350:
0351: /**
0352: * Handle removed DetermineRequirements Task.
0353: * <p>
0354: * Removed task should remove it's subtasks, so we only need
0355: * to clean out it's DeployPlan.
0356: */
0357: protected void watchRemovedDetermineRequirementsTasks() {
0358: // Normal rescind processing is sufficient
0359: }
0360:
0361: /**
0362: * Handle added OrgActs with type "Deployment". We want this
0363: * OrgActivity-based <code>DeployPlan</code> saved. Assume only one such OrgActivity
0364: */
0365: protected void watchAddedSelfOrgDeployAct(OrgActivity selfOrgAct) {
0366: if (logger.isInfoEnabled()) {
0367: printInfo("Adding orgActivity!: " + selfOrgAct + "\nbegin");
0368: }
0369:
0370: replaceDeployPlan(selfOrgAct);
0371:
0372: if (didRehydrate()) {
0373: printInfo(">>> Enter Rehydrate Handling of SelfOrg");
0374: if (getDetermineRequirementsTask() != null) {
0375: int count = 0;
0376: if (getDetermineRequirementsTask().getPlanElement() != null) {
0377: Expansion exp = (Expansion) getDetermineRequirementsTask()
0378: .getPlanElement();
0379: for (Enumeration en = exp.getWorkflow().getTasks(); en
0380: .hasMoreElements();) {
0381: Task subtask = (Task) en.nextElement();
0382: if (subtask.getVerb().equals(
0383: Constants.Verb.TRANSPORT)) { // defensive, should always be TRANSPORT
0384: count++;
0385: }
0386: }
0387: }
0388:
0389: if (count < 2) // note: causes (re)-expand if planElement is null.
0390: updateDetermineRequirementsTask(); // (re)-expand the dr task
0391: }
0392: printInfo(">>> Exit Rehydrate Handling of SelfOrg");
0393: } else {
0394: updateDetermineRequirementsTask(); // (re)-expand the dr task
0395: }
0396:
0397: if (logger.isInfoEnabled()) {
0398: printInfo("Added orgActivity!: " + selfOrgAct + "\ndone");
0399: }
0400: }
0401:
0402: /**
0403: * Handle changed OrgActs. We may need to change the associated
0404: * <code>DeployPlan</code> and/or tweek the expansion.
0405: * <p>
0406: * For now we do something harsh:<br>
0407: * <ol>
0408: * <li>clear the existing orgAct deploy plan</li>
0409: * <li>re-add the orgAct for a new deploy plan</li>
0410: * <li>if there was a DRTask, re-add it over the old one.</li>
0411: * </ol>
0412: */
0413: protected void watchChangedSelfOrgDeployAct(OrgActivity selfOrgAct) {
0414: if (logger.isInfoEnabled()) {
0415: printInfo("Changed orgActivity!: " + selfOrgAct + "\nbegin");
0416: }
0417:
0418: watchAddedSelfOrgDeployAct(selfOrgAct);
0419:
0420: if (logger.isInfoEnabled()) {
0421: printInfo("Changed orgActivity!: " + selfOrgAct + "\ndone");
0422: }
0423: }
0424:
0425: /**
0426: * Handle removed selfOrgAct. Remove the expansion of the d.r. task
0427: * if it still exists.
0428: */
0429: protected void watchRemovedSelfOrgDeployAct(OrgActivity selfOrgAct) {
0430: // throw away the deploy plan
0431: DeployPlan oldDeployPlan = getDeployPlan();
0432: if (oldDeployPlan != null) {
0433: if (logger.isInfoEnabled()) {
0434: printInfo("Remove Deployment Plan!\nOLD:\n"
0435: + oldDeployPlan);
0436: }
0437: setDeployPlan(null);
0438: }
0439: Task drTask = getDetermineRequirementsTask();
0440: if (drTask != null) {
0441: PlanElement pe = drTask.getPlanElement();
0442: if (pe != null)
0443: publishRemove(pe);
0444: }
0445: }
0446:
0447: /**
0448: * Take added transportable <code>Assets</code> and expand them to
0449: * transport tasks.
0450: * <p>
0451: * @param eAssets Enumeration of added assets
0452: */
0453: protected void watchAddedTransportableAssets(Enumeration eAssets) {
0454: if (!(eAssets.hasMoreElements())) {
0455: // no assets changed
0456: return;
0457: }
0458: DeployPlan dp = getDeployPlan();
0459: if (dp == null) {
0460: // no deploy plan yet
0461: if (logger.isInfoEnabled()) {
0462: printInfo("Assets added, waiting for OrgActivity");
0463: }
0464: return;
0465: }
0466: Task drTask = getDetermineRequirementsTask();
0467: if (drTask == null) {
0468: // no determine requirements task yet
0469: if (logger.isInfoEnabled()) {
0470: printInfo("Assets added, waiting for DetermineRequirements");
0471: }
0472: return;
0473: }
0474: if (logger.isInfoEnabled()) {
0475: printInfo("Adding Assets with DP: " + dp);
0476: }
0477: expandDetermineRequirements(dp, drTask, eAssets);
0478: }
0479:
0480: /**
0481: * Handle changed transportable <code>Asset</code>s.
0482: * <p>
0483: * Do this the hard way:<br>
0484: * <ol>
0485: * <li>remove all subtasks created to transport the assets</li>
0486: * <li>make new subtasks to transport them</li>
0487: * </ol>
0488: * <p>
0489: * @param eAssets Enumeration of added assets
0490: */
0491: protected void watchChangedTransportableAssets(Enumeration eAssets) {
0492: if (!(eAssets.hasMoreElements())) {
0493: // no assets changed
0494: return;
0495: }
0496: if (logger.isInfoEnabled()) {
0497: printInfo("Changed assets!");
0498: }
0499: Vector v = new Vector();
0500: while (eAssets.hasMoreElements()) {
0501: v.add(eAssets.nextElement());
0502: }
0503: watchRemovedTransportableAssets(v.elements());
0504: watchAddedTransportableAssets(v.elements());
0505: }
0506:
0507: /**
0508: * Handle removed transportable <code>Assets</code> by removing any
0509: * expanded determine requirements subtasks that depend on them.
0510: * <p>
0511: * @param eAssets Enumeration of assets that were removed
0512: */
0513: protected void watchRemovedTransportableAssets(Enumeration eAssets) {
0514: if (!(eAssets.hasMoreElements())) {
0515: // no assets
0516: return;
0517: }
0518: if (logger.isInfoEnabled()) {
0519: printInfo("Handle Asset removal");
0520: }
0521: // get workflow
0522: DeployPlan dp = getDeployPlan();
0523: if (dp == null) {
0524: // no deploy plan
0525: return;
0526: }
0527: Task drTask = getDetermineRequirementsTask();
0528: if (drTask == null) {
0529: // No dr task, nothing to worry about
0530: return;
0531: }
0532: Expansion exp = (Expansion) drTask.getPlanElement();
0533: if (exp == null) {
0534: // No expansion, nothing to worry about
0535: return;
0536: }
0537: NewWorkflow wf = (NewWorkflow) exp.getWorkflow();
0538: if (wf == null) {
0539: // no workflow, so no tasks to worry about
0540: return;
0541: }
0542: // remove tasks
0543: Vector publishRemoveTasks = new Vector();
0544: Vector workflowRemoveTasks = new Vector();
0545: while (eAssets.hasMoreElements()) {
0546: Asset assetForTrans = (Asset) eAssets.nextElement();
0547: if (logger.isInfoEnabled()) {
0548: printInfo("Look for removed asset: " + assetForTrans);
0549: }
0550: workflowRemoveTasks.clear();
0551: Enumeration subTE = wf.getTasks();
0552: while (subTE.hasMoreElements()) {
0553: Task subT = (Task) subTE.nextElement();
0554: // FIXME! what if asset group!
0555: if (subT.getDirectObject() == assetForTrans) {
0556: if (logger.isInfoEnabled()) {
0557: printInfo(" Will remove Task: " + subT
0558: + " with DO: " + assetForTrans);
0559: }
0560: workflowRemoveTasks.add(subT);
0561: publishRemoveTasks.add(subT);
0562: }
0563: }
0564: for (int i = workflowRemoveTasks.size(); --i >= 0;) {
0565: Task removeWFT = (Task) workflowRemoveTasks
0566: .elementAt(i);
0567: if (logger.isInfoEnabled()) {
0568: printInfo("Remove from workflow Task: " + removeWFT);
0569: }
0570: wf.removeTask(removeWFT);
0571: }
0572: }
0573: for (int i = publishRemoveTasks.size(); --i >= 0;) {
0574: Task removeT = (Task) publishRemoveTasks.elementAt(i);
0575: if (logger.isInfoEnabled()) {
0576: printInfo("publishRemove Task: " + removeT);
0577: }
0578: publishRemove(removeT);
0579: }
0580: }
0581:
0582: /**
0583: * Handle failed allocations to tasks that are subtasks to a
0584: * DetermineRequirements task we expanded.
0585: * <p>
0586: * If a subtask failed then we'll simply slide back start/end times
0587: * by the determineRequirement's DeployPlan adjustDurationDays.
0588: * <p>
0589: * Do we want to fix earliestDate against current time?
0590: * <p>
0591: * @param eFailedAllocs Enumeration of failed allocations
0592: */
0593: protected void watchFailedDispositions(Enumeration eFailedAllocs) {
0594: if (!(eFailedAllocs.hasMoreElements())) {
0595: // no failures
0596: return;
0597: }
0598: // get date adjusters
0599: DeployPlan dp = getDeployPlan();
0600: if (dp == null) {
0601: // no deploy plan
0602: return;
0603: }
0604: int adjustDurationDays = dp.adjustDurationDays;
0605: Date earliestDate = dp.startTime;
0606: // fix tasks
0607: do {
0608: Allocation failedAlloc = (Allocation) eFailedAllocs
0609: .nextElement();
0610: NewTask tFailed = (NewTask) failedAlloc.getTask();
0611: if (logger.isWarnEnabled()) {
0612: printWarn("Failed Allocation: "
0613: + failedAlloc.toString() + " of Task: "
0614: + tFailed.toString());
0615: }
0616: } while (eFailedAllocs.hasMoreElements());
0617: }
0618:
0619: /**
0620: * Protected methods other than subcription watchers
0621: */
0622:
0623: /**
0624: * NOBODY CALLS THIS!
0625: *
0626: * Little utility to remove a workflow and expansion
0627: */
0628: protected void killWorkflow(Workflow wf) {
0629: if (logger.isInfoEnabled()) {
0630: printInfo(" kill workflow: " + wf);
0631: }
0632:
0633: // Only need to kill subtasks if wf was set to not propagate
0634: if (!wf.isPropagatingToSubtasks()) {
0635: Enumeration subtasksE = wf.getTasks();
0636: while (subtasksE.hasMoreElements()) {
0637: Task subt = (Task) subtasksE.nextElement();
0638: if (logger.isInfoEnabled()) {
0639: printInfo(" remove task: " + subt);
0640: }
0641: publishRemove(subt);
0642: }
0643: }
0644:
0645: // okay to get parent
0646: Task ptask = wf.getParentTask();
0647: if (ptask != null) {
0648: PlanElement ppe = ptask.getPlanElement();
0649: if (ppe != null) {
0650: if (logger.isInfoEnabled()) {
0651: printInfo(" remove planElement: " + ppe);
0652: printInfo(" publish change the parent task: "
0653: + ptask.getUID());
0654: }
0655: publishRemove(ppe);
0656: //publishChange(ptask); // fix for bug #2329
0657: } else {
0658: if (logger.isInfoEnabled()) {
0659: printInfo(" no wf parent planElement");
0660: }
0661: }
0662: } else {
0663: if (logger.isInfoEnabled()) {
0664: printInfo(" no wf parent");
0665: }
0666: }
0667: }
0668:
0669: protected void replaceDeployPlan(OrgActivity selfOrgAct) {
0670: // We don't know how long this task will take, so we
0671: // use the default task adjustment duration!
0672: int adjustDurationDays = defaultAdjustDurationDays;
0673: Date prepoStartDate = null;
0674:
0675: if (offsetDays > 0) {
0676: // If OffsetDays was specified as an input parameter, use Oplan C Day + offset as
0677: // start date for the Task
0678: Collection oplanCol = query(new OplanByUIDPred(selfOrgAct
0679: .getOplanUID()));
0680: // Should be exactly one oplan for an OrgActivity
0681: Oplan oplan = (Oplan) oplanCol.iterator().next();
0682: prepoStartDate = new Date(oplan.getCday().getTime()
0683: + (MILLIS_PER_DAY * offsetDays));
0684: }
0685:
0686: DeployPlan newDP = new DeployPlan(selfOrg, selfOrgAct,
0687: adjustDurationDays, overrideFromLocation,
0688: prepoStartDate);
0689: if (logger.isInfoEnabled()) {
0690: printInfo(newDP.toString());
0691: }
0692:
0693: if (!newDP.isValid()) {
0694: if (newDP.fromLoc == null)
0695: printError("This Organization lacks a MilitaryPG HomeLocation!");
0696: printError("The DeployPlan lacks needed information and is ignored: "
0697: + newDP);
0698: setDeployPlan(null);
0699: } else {
0700: DeployPlan oldDP = getDeployPlan();
0701: if (oldDP != null) {
0702: if (logger.isInfoEnabled()) {
0703: printInfo("Replace Deployment Plan!\n" + "OLD:\n"
0704: + oldDP + "\n" + "NEW:\n" + newDP);
0705: }
0706: }
0707: setDeployPlan(newDP);
0708: }
0709: }
0710:
0711: /**
0712: * Debug printer
0713: */
0714: protected final void printDebug(String s) {
0715: logger.debug(getAgentIdentifier() + " - " + s);
0716: }
0717:
0718: /**
0719: * Info printer
0720: */
0721: protected final void printInfo(String s) {
0722: logger.info(getAgentIdentifier() + " - " + s);
0723: }
0724:
0725: /**
0726: * Warn printer
0727: */
0728: protected final void printWarn(String s) {
0729: logger.warn(getAgentIdentifier() + " - " + s);
0730: }
0731:
0732: protected final void printError(String s) {
0733: logger.error(getAgentIdentifier() + " - " + s);
0734: }
0735:
0736: protected void setDefaults(Enumeration eParams) {
0737: // delayReprocessMillis = 0;
0738: defaultAdjustDurationDays = -2;
0739: while (eParams.hasMoreElements()) {
0740: String sParam = (String) eParams.nextElement();
0741: int sep = sParam.indexOf('=');
0742: if (sep > 0) {
0743: String name = sParam.substring(0, sep).trim();
0744: String val = sParam.substring(sep + 1).trim();
0745: if (name.equals("debug")) {
0746: } else if (name
0747: .equalsIgnoreCase("defaultAdjustDurationDays")) {
0748: try {
0749: defaultAdjustDurationDays = Integer
0750: .parseInt(val);
0751: } catch (Exception e) {
0752: printError("Invalid integer for " + sParam);
0753: }
0754: } else if (name.equalsIgnoreCase("createAssetGroups")) {
0755: createAssetGroups = (val.equalsIgnoreCase("true"));
0756: } else if (name.equalsIgnoreCase("delayMillis")) {
0757: try {
0758: // delayReprocessMillis = Long.parseLong(val);
0759: } catch (Exception e) {
0760: printError("Invalid long for " + sParam);
0761: }
0762: } else if (name.equalsIgnoreCase("defaultDurationDays")) {
0763: // old name for param!
0764: try {
0765: defaultAdjustDurationDays = (-(Integer
0766: .parseInt(val)));
0767: } catch (Exception e) {
0768: printError("Invalid number for " + sParam);
0769: }
0770: } else if (name.equalsIgnoreCase("OffsetDays")
0771: || name.equalsIgnoreCase("OffsetDay")) {
0772: offsetDays = Integer.parseInt(val);
0773: } else if (name.equalsIgnoreCase("OriginFile")) {
0774: if (!val.equalsIgnoreCase("HOME")
0775: && !val.equalsIgnoreCase("NONE")) {
0776: originFile = val;
0777: }
0778: } else {
0779: printError("Unknown parameter: " + name + "=" + val);
0780: }
0781: }
0782: }
0783: }
0784:
0785: protected static String getOrgID(Organization org) {
0786: try {
0787: // FOR NOW:
0788: return org.getClusterPG().getMessageAddress().toString();
0789: // FOR LATER:
0790: //return org.getItemIdentificationPG().getItemIdentifier().toString();
0791: } catch (Exception e) {
0792: return null;
0793: }
0794: }
0795:
0796: protected static AbstractAsset strans = null;
0797:
0798: /**
0799: * Expand a DetermineRequirements <code>Task</code>.
0800: * <p>
0801: * All the expanded tasks are very similar. Each task instance
0802: * is separately allocated, but the contents are shared (shallow copy)
0803: * <p>
0804: * Here we find the first and second assets from
0805: * the <code>assetEnum</code>, optionally creating an
0806: * <code>AssetGroup</code>, then we expand to tasks.
0807: * <p>
0808: * @param drTask DetermineRequirements Task to expand
0809: * @param assetsEnum Enumeration of assets for transport
0810: */
0811: protected void expandDetermineRequirements(DeployPlan dp,
0812: Task drTask, Enumeration assetsEnum) {
0813: if (logger.isDebugEnabled()) {
0814: printDebug("Expand task: " + drTask + " with DP: " + dp);
0815: }
0816:
0817: // this is protection for problem where database may indicate zero items
0818: // of a certain type.
0819: assetsEnum = removeZeroQuantityAggregates(assetsEnum)
0820: .elements();
0821:
0822: // get first and second assets from enumeration
0823: Asset firstAssetForTransport = null;
0824: Asset secondAssetForTransport = null;
0825: boolean isPersonAsset = false;
0826: while (true) {
0827: if (!(assetsEnum.hasMoreElements())) {
0828: if (firstAssetForTransport != null) {
0829: // okay, need to transport a single asset
0830: break;
0831: } else {
0832: // bad, nothing to transport?
0833: printError("No assets to Transport?!!!");
0834: return;
0835: }
0836: }
0837: Asset a = (Asset) assetsEnum.nextElement();
0838: if (a == null) {
0839: printError("Null asset for Transport?!!!");
0840: continue;
0841: }
0842: if (firstAssetForTransport == null) {
0843: // the first of the assets
0844: firstAssetForTransport = a;
0845:
0846: // Is this a Person or Equipment? Use first element to determine batch
0847: Object o = a;
0848: while (o instanceof AggregateAsset) {
0849: o = ((AggregateAsset) o).getAsset();
0850: }
0851: isPersonAsset = o instanceof Person;
0852: } else {
0853: // okay, need to transport multiple assets
0854: secondAssetForTransport = a;
0855: break;
0856: }
0857: }
0858:
0859: // have one or more assets to transport
0860:
0861: // check if we're grouping assets
0862: if (createAssetGroups && (secondAssetForTransport != null)) {
0863: // make vector of assets
0864: Vector v = new Vector();
0865: v.addElement(secondAssetForTransport);
0866:
0867: while (assetsEnum.hasMoreElements()) {
0868: Asset a = (Asset) assetsEnum.nextElement();
0869: if (a == null) {
0870: printError("Null asset for Transport?!!!");
0871: } else {
0872: v.addElement(a);
0873: }
0874: }
0875:
0876: // create group
0877: AssetGroup ag = (AssetGroup) theLDMF
0878: .createAsset(AssetGroup.class);
0879: try {
0880: NewTypeIdentificationPG typeIdPG = (NewTypeIdentificationPG) theLDMF
0881: .createPropertyGroup(TypeIdentificationPGImpl.class);
0882: typeIdPG.setTypeIdentification("trans_group");
0883: typeIdPG
0884: .setNomenclature("strat-proj-plugin_asset_group");
0885: ag.setTypeIdentificationPG(typeIdPG);
0886: } catch (Exception eFailedTypePG) {
0887: // don't care?
0888: }
0889: ag.setAssets(v);
0890: // pretend that we have only the asset group
0891: firstAssetForTransport = ag;
0892: secondAssetForTransport = null;
0893: }
0894:
0895: // do expansion
0896:
0897: // PREPOSITIONAL PHRASES
0898: Vector prepphrases = new Vector();
0899:
0900: // TO (my activity deployment location)
0901: NewPrepositionalPhrase to = theLDMF.newPrepositionalPhrase();
0902: to.setPreposition(Constants.Preposition.TO);
0903: to.setIndirectObject(dp.toLoc);
0904: prepphrases.addElement(to);
0905:
0906: // FROM (my home location)
0907: NewPrepositionalPhrase from = theLDMF.newPrepositionalPhrase();
0908: from.setPreposition(Constants.Preposition.FROM);
0909: // HACK - assume that all the assets in the Enumeration are of the same type
0910: if (isPersonAsset || (dp.fromPrepoLoc == null)) {
0911: from.setIndirectObject(dp.fromLoc);
0912: } else {
0913: from.setIndirectObject(dp.fromPrepoLoc);
0914: }
0915: prepphrases.addElement(from);
0916:
0917: // FOR (me)
0918: NewPrepositionalPhrase forpp = theLDMF.newPrepositionalPhrase();
0919: forpp.setPreposition(Constants.Preposition.FOR);
0920: Object forOrgID;
0921: try {
0922: forOrgID = dp.forOrg.getItemIdentificationPG()
0923: .getItemIdentification();
0924: } catch (Exception eForOrg) {
0925: printError("SELF " + dp.forOrg
0926: + " Lacks ItemIdentification! Using Org!");
0927: forOrgID = dp.forOrg;
0928: }
0929: forpp.setIndirectObject(forOrgID);
0930: prepphrases.addElement(forpp);
0931:
0932: // OFTYPE (StrategicTransport)
0933: // create prepositionalphrase oftype strategictransportation
0934: NewPrepositionalPhrase pp = theLDMF.newPrepositionalPhrase();
0935: pp.setPreposition(Constants.Preposition.OFTYPE);
0936: if (strans == null) {
0937: try {
0938: PlanningFactory ldmfactory = getFactory();
0939: Asset strans_proto = ldmfactory
0940: .createPrototype(
0941: Class
0942: .forName("org.cougaar.planning.ldm.asset.AbstractAsset"),
0943: "StrategicTransportation");
0944: strans = (AbstractAsset) ldmfactory
0945: .createInstance(strans_proto);
0946: } catch (Exception exc) {
0947: printError("Unable to create abstract strategictransport\n"
0948: + exc);
0949: }
0950: }
0951: pp.setIndirectObject(strans);
0952: prepphrases.addElement(pp);
0953:
0954: // Kludge - add "PREPO" prepositional phrase if we aren't using the Org's from loc
0955: if ((dp.fromPrepoLoc != null) && !isPersonAsset) {
0956: pp = theLDMF.newPrepositionalPhrase();
0957: pp.setPreposition("PREPO");
0958: prepphrases.add(pp);
0959: }
0960:
0961: // PREFERENCES
0962: Vector prefs = new Vector();
0963:
0964: // START DATE (startTime)
0965: AspectValue startAV;
0966: if (isPersonAsset) {
0967: startAV = AspectValue.newAspectValue(AspectType.START_TIME,
0968: dp.startTime.getTime());
0969: } else {
0970: startAV = AspectValue.newAspectValue(AspectType.START_TIME,
0971: dp.prepoStartTime.getTime());
0972: }
0973: ScoringFunction startSF = ScoringFunction.createNearOrAbove(
0974: startAV, 0);
0975: Preference startPref = theLDMF.newPreference(
0976: AspectType.START_TIME, startSF);
0977: prefs.addElement(startPref);
0978:
0979: // END DATE (RDD - 5*range) <= RDD - range <= RDD
0980: Date lateEndDate = dp.thruTime;
0981: Date bestEndDate = ShortDateFormat.adjustDate(lateEndDate, 0,
0982: -dp.thruRange);
0983: Date earlyEndDate = ShortDateFormat.adjustDate(lateEndDate, 0,
0984: -5 * dp.thruRange);
0985:
0986: if (earlyEndDate.before(dp.startTime))
0987: earlyEndDate = dp.startTime;
0988:
0989: AspectValue earlyEndAV = AspectValue.newAspectValue(
0990: AspectType.END_TIME, earlyEndDate.getTime());
0991: AspectValue bestEndAV = AspectValue.newAspectValue(
0992: AspectType.END_TIME, bestEndDate.getTime());
0993: AspectValue lateEndAV = AspectValue.newAspectValue(
0994: AspectType.END_TIME, lateEndDate.getTime());
0995:
0996: ScoringFunction endSF = ScoringFunction
0997: .createStrictlyBetweenWithBestValues(earlyEndAV,
0998: bestEndAV, lateEndAV);
0999: Preference endPref = theLDMF.newPreference(AspectType.END_TIME,
1000: endSF);
1001: prefs.addElement(endPref);
1002:
1003: // Get Workflow
1004: NewWorkflow wf = null;
1005: Expansion exp = (Expansion) drTask.getPlanElement();
1006: if (exp != null) {
1007: wf = (NewWorkflow) exp.getWorkflow();
1008: }
1009: boolean newWf = (wf == null);
1010: if (newWf) {
1011: wf = theLDMF.newWorkflow();
1012: wf.setIsPropagatingToSubtasks(true);
1013: wf.setParentTask(drTask);
1014: if (logger.isDebugEnabled()) {
1015: printDebug("made new workflow - " + wf);
1016: }
1017: } else {
1018: if (logger.isDebugEnabled()) {
1019: printDebug("Using existing workflow - " + wf
1020: + " that has these tasks : ");
1021: }
1022: Enumeration eT = wf.getTasks();
1023: while (eT.hasMoreElements()) {
1024: Task ewft = (Task) eT.nextElement();
1025: if (logger.isDebugEnabled()) {
1026: printDebug(" task: " + ewft.getVerb() + " ("
1027: + ewft.getUID() + ") " + " asset: "
1028: + ewft.getDirectObject());
1029: }
1030: }
1031: }
1032:
1033: // Make sure we can modify the PlanElement!
1034:
1035: // create the subtasks. first add our "first" and "second"
1036: // assets, then use the enumeration.
1037: boolean useAssetsEnum = false;
1038: Asset assetForTransport = firstAssetForTransport;
1039: while (true) {
1040: // Create transport task
1041: NewTask subtask = makeTransportTask(drTask,
1042: assetForTransport, prepphrases, prefs, wf);
1043:
1044: // publish task
1045: publishAdd(subtask);
1046:
1047: // next asset
1048: if (useAssetsEnum) {
1049: // third and later assets
1050: if (!(assetsEnum.hasMoreElements())) {
1051: // done!
1052: break;
1053: }
1054: assetForTransport = (Asset) assetsEnum.nextElement();
1055: if (assetForTransport == null) {
1056: printError("Null asset for Transport?!!!");
1057: continue;
1058: }
1059: } else {
1060: // second asset
1061: if (secondAssetForTransport == null) {
1062: // done! only one asset to transport.
1063: break;
1064: }
1065: assetForTransport = secondAssetForTransport;
1066: // next time use the enumeration
1067: useAssetsEnum = true;
1068: }
1069: }
1070:
1071: // postcondition sanity checking - in the end, in general, there should be exactly 2 TRANSPORT subtasks.
1072: // if less, probably a database issue (NEED CHECK FOR THIS CASE)
1073: // if more, something is wrong with this plugin
1074:
1075: int count = 0;
1076: for (Enumeration en = wf.getTasks(); en.hasMoreElements();) {
1077: Task subtask = (Task) en.nextElement();
1078: if (subtask.getVerb().equals(Constants.Verb.TRANSPORT)) { // defensive, should always be TRANSPORT
1079: count++;
1080: }
1081: }
1082:
1083: if (count > 2) {
1084: logger.warn("drTask - " + drTask.getUID()
1085: + " has too many (" + count + ") subtasks ");
1086: for (Enumeration en = wf.getTasks(); en.hasMoreElements();) {
1087: Task subtask = (Task) en.nextElement();
1088: logger.warn(" - subtask - " + subtask.getUID());
1089: }
1090: }
1091:
1092: if (newWf) {
1093: // make the expansion
1094: if (logger.isDebugEnabled()) {
1095: printDebug("Create expansion of determine requirement task "
1096: + drTask.getUID());
1097: }
1098: AllocationResult estimatedResult = PluginHelper
1099: .createEstimatedAllocationResult(drTask, theLDMF,
1100: 1.0, true);
1101: PlanElement pe = theLDMF.createExpansion(drTask.getPlan(),
1102: drTask, wf, estimatedResult);
1103: publishAdd(pe);
1104:
1105: if (logger.isDebugEnabled()) {
1106: printDebug("Published new DetermineReqs Task Expansion for d.r. task "
1107: + drTask.getUID());
1108: }
1109: } else {
1110: if (logger.isDebugEnabled()) {
1111: printDebug("Publish changed expansion of d.r. task "
1112: + drTask.getUID());
1113: }
1114: publishChange(exp);
1115: }
1116: }
1117:
1118: protected NewTask makeTransportTask(Task drTask,
1119: Asset assetForTransport, Vector prepphrases, Vector prefs,
1120: NewWorkflow wf) {
1121: NewTask subtask = theLDMF.newTask();
1122: subtask.setParentTask(drTask);
1123: subtask.setDirectObject(assetForTransport);
1124: subtask.setPrepositionalPhrases(prepphrases.elements());
1125: subtask.setVerb(Constants.Verb.Transport);
1126: subtask.setPlan(drTask.getPlan());
1127: subtask.setPreferences(prefs.elements());
1128: subtask.setSource(getMessageAddress());
1129:
1130: // add to workflow
1131: wf.addTask(subtask);
1132: subtask.setWorkflow(wf);
1133:
1134: return subtask;
1135: }
1136:
1137: /**
1138: * Filter out invalid zero quantity aggregates from those to make transport tasks for
1139: *
1140: * @param assets original list of assets published to blackboard
1141: * @return Vector of valid assets
1142: */
1143: protected Vector removeZeroQuantityAggregates(Enumeration assets) {
1144: Vector validAssets = new Vector();
1145:
1146: for (; assets.hasMoreElements();) {
1147: Object asset = assets.nextElement();
1148:
1149: if (asset instanceof AggregateAsset) {
1150: AggregateAsset aggregate = (AggregateAsset) asset;
1151: if (aggregate.getQuantity() > 0)
1152: validAssets.add(asset);
1153: else if (logger.isInfoEnabled()) // ignore zero quantity aggregates
1154: logger
1155: .info(getAgentIdentifier()
1156: + " - removeZeroQuantityAggregates - NOTE : "
1157: + " ignoring zero quantity aggregate of : "
1158: + aggregate.getAsset()
1159: + " since it's quantity is "
1160: + aggregate.getQuantity());
1161: } else
1162: validAssets.add(asset);
1163: }
1164:
1165: return validAssets;
1166: }
1167:
1168: private void updateDetermineRequirementsTask() {
1169: DeployPlan dp = getDeployPlan();
1170: if (dp == null) {
1171: // no deploy plan so put in unhandled
1172: if (logger.isInfoEnabled()) {
1173: printInfo("updateDetermineRequirementsTask - no deploy plan -- processing deferred");
1174: }
1175: return;
1176: }
1177: Task drTask = getDetermineRequirementsTask();
1178: if (drTask == null) {
1179: if (logger.isInfoEnabled()) {
1180: printInfo("No drTask for Deploy Plan: " + dp);
1181: }
1182: return;
1183: }
1184:
1185: // if there is already a transport task in the workflow, remove it, since the
1186: // oplan has changed and we need to recreate it
1187: if (drTask.getPlanElement() != null
1188: && drTask.getPlanElement() instanceof Expansion
1189: && ((Expansion) drTask.getPlanElement()).getWorkflow() != null) {
1190: printInfo("drTask - workflow - "
1191: + ((Expansion) drTask.getPlanElement())
1192: .getWorkflow());
1193:
1194: Vector toRemove = new Vector();
1195:
1196: for (Enumeration en = ((Expansion) drTask.getPlanElement())
1197: .getWorkflow().getTasks(); en.hasMoreElements();) {
1198: Task subtask = (Task) en.nextElement();
1199: printInfo("drTask - subtask - " + subtask.getUID()
1200: + " verb " + subtask.getVerb());
1201: if (subtask.getVerb().equals(Constants.Verb.TRANSPORT)) {
1202: printInfo("drTask - subtask TRANSPORT - "
1203: + subtask.getUID());
1204: toRemove.add(subtask);
1205: }
1206: }
1207:
1208: for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
1209: Task subtask = (Task) iter.next();
1210:
1211: ((NewWorkflow) ((Expansion) drTask.getPlanElement())
1212: .getWorkflow()).removeTask(subtask);
1213: publishRemove(subtask);
1214: }
1215: }
1216:
1217: if (logger.isInfoEnabled()) {
1218: printInfo("Add drTask with Deploy Plan: " + dp);
1219: }
1220:
1221: // create tasks for the assets
1222: Enumeration eAssets = transAssetsPersonSub.elements();
1223: if (eAssets.hasMoreElements()) {
1224: expandDetermineRequirements(dp, drTask, eAssets);
1225: } else {
1226: if (logger.isInfoEnabled()) {
1227: printInfo("No assets to transport");
1228: }
1229: }
1230: eAssets = transAssetsEquipmentSub.elements();
1231: if (eAssets.hasMoreElements()) {
1232: expandDetermineRequirements(dp, drTask, eAssets);
1233: } else {
1234: if (logger.isInfoEnabled()) {
1235: printInfo("No assets to transport");
1236: }
1237: }
1238: }
1239:
1240: // private void reprocessDetermineRequirementsTask(Task drTask) {
1241: // if (delayReprocessMillis > 0) {
1242: // // delay specified millis before re-adding task
1243: // if (logger.isInfoEnabled()) {
1244: // printInfo(" delay re-add drTask: "+drTask);
1245: // }
1246: // unhandledDetermineRequirementsTask = new WaitingTask(delayReprocessMillis,
1247: // drTask);
1248: // wakeAfterRealTime(delayReprocessMillis);
1249: // } else {
1250: // // handle task immediately
1251: // if (logger.isInfoEnabled()) {
1252: // printInfo(" immediate re-add drTask: "+drTask);
1253: // }
1254: // handleDetermineRequirementsTask(drTask);
1255: // }
1256: // }
1257:
1258: /**
1259: * Predicate generators
1260: */
1261:
1262: /**
1263: * Self Organization predicate.
1264: **/
1265: protected static UnaryPredicate newSelfOrgPred() {
1266: return new UnaryPredicate() {
1267: public boolean execute(Object o) {
1268: if (o instanceof Organization) {
1269: return ((Organization) o).isSelf();
1270: }
1271: return false;
1272: }
1273: };
1274: }
1275:
1276: /**
1277: * OrgActivity of type "Deployment" predicate.
1278: **/
1279: protected static UnaryPredicate newOrgDeployActsPred() {
1280: return new UnaryPredicate() {
1281: public boolean execute(Object o) {
1282: return ((o instanceof OrgActivity) && "Deployment"
1283: .equals(((OrgActivity) o).getActivityType()));
1284: }
1285: };
1286: }
1287:
1288: /**
1289: * The predicate for our incoming tasks. We are looking for
1290: * DETERMINEREQUIREMENT tasks of type Asset where the asset type is
1291: * StrategicTransportation.
1292: **/
1293: protected static UnaryPredicate newDRTasksPred() {
1294: return new UnaryPredicate() {
1295: public boolean execute(Object o) {
1296: if (o instanceof Task) {
1297: Task t = (Task) o;
1298: if (Constants.Verb.DetermineRequirements.equals(t
1299: .getVerb())) {
1300: return (ExpanderHelper.isOfType(t,
1301: Constants.Preposition.OFTYPE,
1302: "StrategicTransportation"));
1303: }
1304: }
1305: return false;
1306: }
1307: };
1308: }
1309:
1310: protected static UnaryPredicate newTransPersonPred() {
1311: return new UnaryPredicate() {
1312: public boolean execute(Object o) {
1313: while (o instanceof AggregateAsset)
1314: o = ((AggregateAsset) o).getAsset();
1315: return (o instanceof Person);
1316: }
1317: };
1318: }
1319:
1320: /**
1321: * See bug 2998 in bugzilla.
1322: *
1323: * In order to not strat trans move Level2MEIs we filter out equipment with the
1324: * cargo cat code of "000" which means phantom equipment. The
1325: * phantom equipment corresponds to Level2MEIs. The cargo cat code is put
1326: * onto the Level2MEIs retroactively after they have been made that is the
1327: * reason for the DynamicUnaryPredicate.
1328: */
1329: protected static DynamicUnaryPredicate newTransEquipmentPred() {
1330: return new DynamicUnaryPredicate() {
1331: public boolean execute(Object o) {
1332: while (o instanceof AggregateAsset)
1333: o = ((AggregateAsset) o).getAsset();
1334: if (o instanceof ClassVIIMajorEndItem) {
1335: ClassVIIMajorEndItem asset = (ClassVIIMajorEndItem) o;
1336: MovabilityPG moveProp = asset.getMovabilityPG();
1337: if ((moveProp != null)
1338: && (moveProp.getCargoCategoryCode() != null)
1339: && (moveProp.getCargoCategoryCode()
1340: .equals("000"))) {
1341: return false;
1342: }
1343: return true;
1344: }
1345: return false;
1346: }
1347: };
1348: }
1349:
1350: /**
1351: * Pred for failed allocations of a expanded DetermineRequirements tasks we
1352: * published. We use newDRTasksPred for testing the task.
1353: **/
1354: protected static UnaryPredicate newFailedDRAllocPred() {
1355: return new UnaryPredicate() {
1356: protected UnaryPredicate myDRTaskPred = newDRTasksPred();
1357:
1358: public boolean execute(Object o) {
1359: if (o instanceof Allocation) {
1360: AllocationResult ar = ((Allocation) o)
1361: .getReportedResult();
1362: if ((ar != null) && (!(ar.isSuccess()))) {
1363: Task tFailed = ((Allocation) o).getTask();
1364: Workflow wf;
1365: if ((tFailed != null)
1366: && !(tFailed instanceof MPTask)
1367: && (wf = tFailed.getWorkflow()) != null // all these tasks are part of a WF
1368: ) {
1369: Task tParent = wf.getParentTask();
1370: return myDRTaskPred.execute(tParent);
1371: }
1372: }
1373: }
1374: return false;
1375: }
1376: };
1377: }
1378:
1379: /**
1380: * Test if this object is an expansion of one of our tasks. We use
1381: * taskPred for the latter.
1382: **/
1383: protected static UnaryPredicate newExpansionsPred() {
1384: return new UnaryPredicate() {
1385: protected UnaryPredicate myTaskPred = newDRTasksPred();
1386:
1387: public boolean execute(Object o) {
1388: if (o instanceof Expansion) {
1389: return myTaskPred
1390: .execute(((Expansion) o).getTask());
1391: }
1392: return false;
1393: }
1394: };
1395: }
1396:
1397: /**
1398: * Predicate to find a specific Oplan by UID
1399: **/
1400: protected static class OplanByUIDPred implements UnaryPredicate {
1401: UID oplanUID;
1402:
1403: OplanByUIDPred(UID uid) {
1404: oplanUID = uid;
1405: }
1406:
1407: public boolean execute(Object o) {
1408: if (o instanceof Oplan) {
1409: if (oplanUID.equals(((Oplan) o).getUID())) {
1410: return true;
1411: }
1412: }
1413: return false;
1414: }
1415: }
1416:
1417: /**
1418: * Utility classes
1419: */
1420:
1421: /**
1422: * Class <code>DeployPlan</code>
1423: */
1424: protected static class DeployPlan {
1425: /**
1426: * These fields are used to fill out a determine requirements
1427: * task. They are gathered from the oplan and this plugin's
1428: * organization information.
1429: * <p>
1430: * The "adjustDurationDays" field is the time difference from "thruTime"
1431: * to initially try starting the deployment tasks. It should be
1432: * negative, e.g.<br>
1433: * startTime=10/1/99, endTime=10/31/99, adjustDurationDays=-7;<br>
1434: * would first try starting on 10/21/99.
1435: */
1436: public UID oplanId;
1437: public GeolocLocation fromLoc = null;
1438: public GeolocLocation fromPrepoLoc = null;
1439: public GeolocLocation toLoc = null;
1440: public Organization forOrg;
1441: public Date startTime;
1442: public Date prepoStartTime;
1443: public Date thruTime;
1444: public int thruRange = 1;
1445: public int adjustDurationDays;
1446:
1447: public DeployPlan() {
1448: }
1449:
1450: /**
1451: * Contructor. Takes needed fields from parameters.
1452: * <p>
1453: * Caller should check this class with isValid() afterwards.
1454: * <p>
1455: * @param org Organization for the org's deployment
1456: * @param orgAct OrgActivity of type "Deploy"
1457: * @param adjustDurationDays Time needed to do task
1458: */
1459: public DeployPlan(Organization org, OrgActivity orgAct,
1460: int adjustDurationDays,
1461: GeolocLocation overrideFromLocation, Date prepoStartDate) {
1462: if ((org == null) || (orgAct == null)) {
1463: System.err
1464: .println("BAD DeployPlan parameter(s)! org = "
1465: + org + " orgAct = " + orgAct);
1466: return;
1467: }
1468:
1469: // get oplan id
1470: this .oplanId = orgAct.getUID();
1471:
1472: // get plan org
1473: this .forOrg = org;
1474:
1475: // get FROM geographic location
1476: // this is taken from the MilitaryOrgPG
1477: org.cougaar.glm.ldm.asset.MilitaryOrgPG milPG = org
1478: .getMilitaryOrgPG();
1479: if (milPG != null) {
1480: this .fromLoc = (GeolocLocation) milPG.getHomeLocation();
1481: }
1482: // get TO geographic location
1483: this .toLoc = orgAct.getGeoLoc();
1484:
1485: // Use this for equipment
1486: this .fromPrepoLoc = overrideFromLocation;
1487:
1488: // get organization activity information
1489:
1490: TimeSpan actTS = orgAct.getTimeSpan();
1491: if (actTS != null) {
1492: // do we want to fix dates to be after System time?
1493: // startDate will be null if OffsetDays days wasn't an command line parameter
1494: this .thruTime = actTS.getEndDate();
1495: this .startTime = actTS.getStartDate();
1496:
1497: if (prepoStartDate == null) {
1498: // Use Deploy OrgActivity startDate instead
1499: this .prepoStartTime = actTS.getStartDate();
1500: } else {
1501: // Use OrgActivity startDate if the oplan C day + offsetDays is later than
1502: // the Task thruDate.
1503: if (prepoStartDate.compareTo(this .thruTime) < 0)
1504: this .prepoStartTime = prepoStartDate;
1505: else
1506: this .prepoStartTime = actTS.getStartDate();
1507: }
1508: }
1509:
1510: // get adjustment days
1511: this .adjustDurationDays = adjustDurationDays;
1512: }
1513:
1514: /**
1515: * After constructor the caller should check isValid()
1516: * @return true if all necessary deployment fields are set
1517: */
1518: public boolean isValid() {
1519: return ((oplanId != null)
1520: && ((fromLoc != null) && (fromLoc.getGeolocCode() != null))
1521: && ((toLoc != null) && (toLoc.getGeolocCode() != null))
1522: && (forOrg != null) && (startTime != null) && (thruTime != null));
1523: }
1524:
1525: /**
1526: * toString()
1527: * @return String representation of contents
1528: */
1529: public String toString() {
1530: String s = "Deployment Plan:";
1531: s += "\n PlanId: " + oplanId;
1532: s += "\n fromLoc: "
1533: + ((fromLoc != null) ? fromLoc.getGeolocCode()
1534: : "?");
1535: s += "\n fromPrepoLoc: "
1536: + ((fromPrepoLoc != null) ? fromPrepoLoc
1537: .getGeolocCode() : "?");
1538: s += "\n toLoc: "
1539: + ((toLoc != null) ? toLoc.getGeolocCode() : "?");
1540: s += "\n for: " + getOrgID(forOrg);
1541: s += "\n startTime: " + startTime;
1542: s += "\n prepoStartTime: " + prepoStartTime;
1543: s += "\n thruTime: " + thruTime;
1544: s += "\n adjustDurationDays: " + adjustDurationDays;
1545: s += "\n";
1546: return s;
1547: }
1548:
1549: public boolean equals(DeployPlan dp) {
1550: try {
1551: return (oplanId.equals(dp.oplanId)
1552: && (fromLoc == dp.fromLoc)
1553: && (fromPrepoLoc == dp.fromPrepoLoc)
1554: && (toLoc == dp.toLoc) && (forOrg == dp.forOrg)
1555: && startTime.equals(dp.startTime)
1556: && prepoStartTime.equals(dp.prepoStartTime)
1557: && thruTime.equals(dp.thruTime) && (adjustDurationDays == dp.adjustDurationDays));
1558: } catch (NullPointerException ne) {
1559: // both "this" and "dp" should be "isValid()"!
1560: return false;
1561: }
1562: }
1563: }
1564:
1565: public GeolocLocation getGeoLoc(String xmlfilename) {
1566: Document doc = null;
1567: try {
1568: doc = getConfigFinder().parseXMLConfigFile(xmlfilename);
1569: if (doc == null) {
1570: printError(" XML Parser could not handle file "
1571: + xmlfilename);
1572: return null;
1573: }
1574: } catch (java.io.IOException ioex) {
1575: printError("geoloc xml error ");
1576: ioex.printStackTrace();
1577: return null;
1578: }
1579:
1580: Node node = doc.getDocumentElement();
1581: return locationParser.getLocation(getLDM(), node);
1582: }
1583:
1584: /** rely upon load-time introspection to set these services - don't worry about revokation. */
1585: public final void setLoggingService(LoggingService logger) {
1586: this .logger = logger;
1587: }
1588:
1589: LocationParser locationParser = new LocationParser();
1590:
1591: /**
1592: * Everybody needs a logger
1593: **/
1594: protected LoggingService logger;
1595: }
|