0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 2001-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: package org.cougaar.logistics.plugin.trans;
0027:
0028: import java.util.ArrayList;
0029: import java.util.Collection;
0030: import java.util.Date;
0031: import java.util.Enumeration;
0032: import java.util.HashMap;
0033: import java.util.HashSet;
0034: import java.util.Map;
0035: import java.util.Iterator;
0036: import java.util.List;
0037: import java.util.Random;
0038: import java.util.Set;
0039: import java.util.Vector;
0040:
0041: import org.cougaar.core.service.BlackboardService;
0042:
0043: import org.cougaar.glm.callback.GLMOrganizationCallback;
0044: import org.cougaar.glm.callback.GLMOrganizationListener;
0045:
0046: import org.cougaar.logistics.ldm.Constants;
0047:
0048: import org.cougaar.glm.ldm.asset.AirportPG;
0049: import org.cougaar.glm.ldm.asset.GLMAsset;
0050: import org.cougaar.glm.ldm.asset.MilitaryOrgPG;
0051: import org.cougaar.glm.ldm.asset.Organization;
0052: import org.cougaar.glm.ldm.asset.TransportationNode;
0053:
0054: import org.cougaar.glm.ldm.plan.GeolocLocation;
0055:
0056: import org.cougaar.logistics.plugin.trans.GLMTransConst;
0057: import org.cougaar.logistics.plugin.trans.base.SequentialPlannerPlugin;
0058: import org.cougaar.logistics.plugin.trans.base.SequentialScheduleElement;
0059:
0060: import org.cougaar.logistics.plugin.trans.tools.BlackboardPlugin;
0061: import org.cougaar.logistics.plugin.trans.tools.Locator;
0062: import org.cougaar.logistics.plugin.trans.tools.LocatorImpl;
0063:
0064: import org.cougaar.glm.util.AssetUtil;
0065: import org.cougaar.glm.util.GLMPrepPhrase;
0066:
0067: import org.cougaar.lib.callback.UTILExpandableTaskCallback;
0068: import org.cougaar.lib.callback.UTILFilterCallback;
0069: import org.cougaar.lib.callback.UTILGenericListener;
0070:
0071: import org.cougaar.lib.util.UTILAllocate;
0072: import org.cougaar.lib.util.UTILExpand;
0073: import org.cougaar.lib.util.UTILPreference;
0074:
0075: import org.cougaar.planning.ldm.asset.Asset;
0076: import org.cougaar.planning.ldm.asset.LocationSchedulePG;
0077:
0078: import org.cougaar.planning.ldm.plan.Allocation;
0079: import org.cougaar.planning.ldm.plan.AspectType;
0080: import org.cougaar.planning.ldm.plan.AspectValue;
0081: import org.cougaar.planning.ldm.plan.Expansion;
0082: import org.cougaar.planning.ldm.plan.Location;
0083: import org.cougaar.planning.ldm.plan.LocationScheduleElement;
0084: import org.cougaar.planning.ldm.plan.NewSchedule;
0085: import org.cougaar.planning.ldm.plan.NewTask;
0086: import org.cougaar.planning.ldm.plan.PlanElement;
0087: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
0088: import org.cougaar.planning.ldm.plan.Relationship;
0089: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
0090: import org.cougaar.planning.ldm.plan.Role;
0091: import org.cougaar.planning.ldm.plan.Schedule;
0092: import org.cougaar.planning.ldm.plan.ScheduleImpl;
0093: import org.cougaar.planning.ldm.plan.Task;
0094: import org.cougaar.planning.ldm.plan.NewWorkflow;
0095:
0096: import org.cougaar.util.TimeSpan;
0097: import org.cougaar.util.log.Logger;
0098:
0099: /**
0100: * <pre>
0101: * This class orchestrates the backwards planning that goes on in GLMTrans.
0102: *
0103: * It makes decisions about how to expand incoming tasks into their appropriate
0104: * forms, e.g CONUSGround-Air-TheaterGround. It monitors the state of each subtask
0105: * and then notices when a task that is dependent on another has all its dependencies
0106: * met and is ready to be planned. This task is then planned.
0107: *
0108: * </pre>
0109: * <!--
0110: * (When printed, any longer line will wrap...)
0111: *2345678901234567890123456789012345678901234567890123456789012345678901234567890
0112: * 1 2 3 4 5 6 7 8
0113: * -->
0114: */
0115: public class SequentialGlobalAirPlugin extends SequentialPlannerPlugin
0116: implements GLMOrganizationListener, BlackboardPlugin {
0117:
0118: protected TranscomDataXMLize dataXMLizer; // we need it for getOrganizationRole
0119:
0120: private static final long ONE_HOUR = 1000l * 60l * 60l;
0121: //private static final double BILLION = 1000000000.0d;
0122: //private static final String SAND = "SAND";
0123: public static int CONUS_THEATER_DIVIDING_LONGITUDE = Integer
0124: .getInteger(
0125: "SequentialGlobalAirPlugin.CONUS_THEATER_DIVIDING_LONGITUDE",
0126: 25).intValue();
0127: public int numTheaterGroundAgents = 2;
0128:
0129: public void localSetup() {
0130: super .localSetup();
0131:
0132: try {
0133: if (getMyParams().hasParam("bestDateBackoff")) {
0134: bestDateBackoff = getMyParams().getLongParam(
0135: "bestDateBackoff");
0136: } else {
0137: bestDateBackoff = ONE_HOUR;
0138: }
0139: if (getMyParams().hasParam("numTheaterGroundAgents")) {
0140: numTheaterGroundAgents = getMyParams().getIntParam(
0141: "numTheaterGroundAgents");
0142: } else {
0143: numTheaterGroundAgents = 2; // by default we run with the TRANSCOM-20 society
0144: }
0145: } catch (Exception e) {
0146: warn("got really unexpected exception " + e);
0147: }
0148:
0149: if (isDebugEnabled())
0150: debug("localSetup - Creating prep helper and asset helper.");
0151:
0152: if (isDebugEnabled())
0153: debug("localSetup - this " + this + " prep helper "
0154: + glmPrepHelper);
0155:
0156: dataXMLizer = new TranscomDataXMLize(true, logger,
0157: new HashSet());
0158: }
0159:
0160: protected UTILFilterCallback createThreadCallback(
0161: UTILGenericListener bufferingThread) {
0162: myInputTaskCallback = new UTILExpandableTaskCallback(
0163: bufferingThread, logger);
0164: return myInputTaskCallback;
0165: }
0166:
0167: /**
0168: * Implemented for UTILGenericListener interface
0169: *
0170: * Look for tasks that
0171: * 1) Have TRANSPORT as their verb
0172: *
0173: * @param t Task to check for interest
0174: * @return boolean true if task is interesting
0175: * @see org.cougaar.lib.callback.UTILGenericListener
0176: */
0177:
0178: public boolean interestingTask(Task t) {
0179: boolean hasTransportVerb = t.getVerb().equals(
0180: Constants.Verb.TRANSPORT);
0181: if (isDebugEnabled() && hasTransportVerb) {
0182: debug(" : interested in expandable task " + t
0183: + " with direct obj " + t.getDirectObject());
0184: }
0185: if (isDebugEnabled() && !hasTransportVerb)
0186: debug(" : Ignoring task with verb " + t.getVerb());
0187:
0188: return hasTransportVerb;
0189: }
0190:
0191: public boolean interestingExpandedTask(Task t) {
0192: if (!t.getSource().equals(getAgentIdentifier()))
0193: return true;
0194: return glmPrepHelper.hasPrepNamed(t,
0195: GLMTransConst.SequentialSchedule);
0196: }
0197:
0198: /**
0199: * Implemented for AssetListener interface<br>
0200: * only interested in airports/seaports
0201: */
0202: public boolean interestingAsset(Asset asset) {
0203: boolean retval = asset instanceof TransportationNode;
0204: if (isDebugEnabled())
0205: debug(".interestingAsset : "
0206: + ((retval) ? "interested in " : "ignoring ")
0207: + asset);
0208:
0209: return retval;
0210: }
0211:
0212: /*** Organization Listener ***/
0213:
0214: public void setupFilters() {
0215: glmPrepHelper = new GLMPrepPhrase(logger);
0216: glmAssetHelper = new AssetUtil(logger);
0217:
0218: super .setupFilters();
0219:
0220: if (isInfoEnabled())
0221: info(" : Filtering for Organizations...");
0222:
0223: addFilter(myOrgCallback = createOrganizationCallback());
0224:
0225: makeLocator();
0226: }
0227:
0228: /** Instantiate the Locator, which adds a LocationCallback */
0229: protected void makeLocator() {
0230: locator = new LocatorImpl(this , logger);
0231: }
0232:
0233: /** implemented for BlackboardPlugin interface -- need public access! */
0234: public BlackboardService getBlackboard() {
0235: return blackboard;
0236: }
0237:
0238: protected GLMOrganizationCallback getOrganizationCallback() {
0239: return myOrgCallback;
0240: }
0241:
0242: protected GLMOrganizationCallback createOrganizationCallback() {
0243: return new GLMOrganizationCallback(this , logger);
0244: }
0245:
0246: public Enumeration getOrganizationAssets() {
0247: return myOrgCallback.getSubscription().elements();
0248: }
0249:
0250: public Organization getSelf() {
0251: return glmAssetHelper.getSelf(getOrganizationAssets());
0252: }
0253:
0254: public void handleNewOrganization(Enumeration org_assets) {
0255: shouldRefreshOrgList = true;
0256: for (; org_assets.hasMoreElements();) {
0257: info(getName() + " - got new org "
0258: + org_assets.nextElement());
0259: }
0260: }
0261:
0262: public void handleChangedOrganization(Enumeration org_assets) {
0263: }
0264:
0265: public void handleTask(Task t) {
0266: NewTask subtask = expandHelper.makeSubTask(ldmf, t, t
0267: .getDirectObject(), getAgentIdentifier());
0268: subtask.setContext(t.getContext());
0269:
0270: NewWorkflow wf = ldmf.newWorkflow();
0271: wf.setParentTask(t);
0272: ((NewTask) subtask).setWorkflow(wf);
0273: ((NewTask) subtask).setParentTask(t);
0274: wf.addTask(subtask);
0275:
0276: Expansion exp = ldmf.createExpansion(t.getPlan(), t, wf, null);
0277:
0278: publishAdd(subtask);
0279: publishAdd(exp);
0280:
0281: super .handleTask(subtask);
0282: }
0283:
0284: public Schedule createEmptyPlan(Task parent) {
0285: TheaterPortion theater = new TheaterPortion(parent);
0286: // IsbPortion isb = new IsbPortion(parent);
0287: AirPortion air = new AirPortion(parent);
0288: ConusPortion conus = new ConusPortion(parent);
0289:
0290: boolean needsTheater = needsTheater(parent);
0291: // boolean needsISB = needsISB (parent);
0292: boolean needsCONUS = needsCONUS(parent);
0293: boolean needsAirOrSea = needsAirOrSea(parent);
0294:
0295: // create the dependencies ------------------
0296:
0297: if (isDebugEnabled())
0298: debug(".createEmptyPlan - "
0299: + parent.getDirectObject().getUID().getOwner()
0300: + "'s task " + parent.getUID() + " - "
0301: + parent.getDirectObject() + " Legs : "
0302: + ((needsCONUS) ? "G" : "")
0303: + ((needsAirOrSea) ? "A/S" : "")
0304: + ((needsTheater) ? "T" : ""));
0305:
0306: // Vector isbdep = new Vector();
0307: // if (needsTheater)
0308: // isbdep.addElement(theater);
0309: // isb.setDependencies(isbdep);
0310:
0311: // if (needsISB)
0312: // airdep.addElement(isb);
0313: if (needsTheater) {
0314: Vector airdep = new Vector();
0315: airdep.addElement(theater);
0316: air.setDependencies(airdep);
0317: }
0318:
0319: if (needsAirOrSea) {
0320: Vector conusdep = new Vector();
0321: conusdep.addElement(air);
0322: conus.setDependencies(conusdep);
0323: }
0324:
0325: // create the Schedule ------------------
0326:
0327: NewSchedule retSchedule = new ScheduleImpl();
0328: if (needsTheater)
0329: retSchedule.addScheduleElement(theater);
0330: // if (needsISB)
0331: // retSchedule.addScheduleElement(isb);
0332: if (needsAirOrSea)
0333: retSchedule.addScheduleElement(air);
0334: if (needsAirOrSea && needsCONUS)
0335: retSchedule.addScheduleElement(conus);
0336:
0337: if (isDebugEnabled())
0338: debug(".createEmptyPlan - " + retSchedule);
0339: if (retSchedule.isEmpty()) {
0340: Object origin = glmPrepHelper.getFromLocation(parent);
0341: Object destination = glmPrepHelper.getToLocation(parent);
0342: error(".createEmptyPlan - created an empty portion schedule. "
0343: + "For task "
0344: + parent.getUID()
0345: + " going from "
0346: + origin + " to " + destination);
0347: }
0348:
0349: return retSchedule;
0350: }
0351:
0352: /**
0353: * needs a theater leg if TO location is not an airbase OR if FROM loc is in theater (i.e. starts in theater).
0354: */
0355: boolean needsTheater(Task task) {
0356: if (glmAssetHelper.isPassenger(task.getDirectObject()))
0357: return false;
0358: boolean inTheater = startsInTheater(task);
0359: GeolocLocation destinationGeoloc = (GeolocLocation) glmPrepHelper
0360: .getIndirectObject(task, Constants.Preposition.TO);
0361: Object asset = locator.getAssetAtGeolocCode(destinationGeoloc
0362: .getGeolocCode());
0363:
0364: if (isDebugEnabled()) {
0365: if (asset == null) {
0366: debug(".needsTheater - Theater move needed, since TO location <"
0367: + destinationGeoloc
0368: + "> is not a "
0369: + type()
0370: + " among these "
0371: + type()
0372: + "s : "
0373: + locator.knownGeolocCodes());
0374: } else {
0375: debug(".needsTheater - no Theater move needed, since TO location <"
0376: + destinationGeoloc
0377: + "> is a "
0378: + type()
0379: + " ("
0380: + asset + ").");
0381: }
0382: }
0383:
0384: // if the destination is not an airbase/seaport, add a theater ground move leg
0385: return (inTheater || (asset == null));
0386: }
0387:
0388: protected String type() {
0389: return "airport";
0390: }
0391:
0392: /**
0393: * sort of cheesy, but anything starting east of 25 degrees Longitude gets a final theater leg.
0394: * (The 25 degrees can be set with a system property.)
0395: */
0396: boolean startsInTheater(Task task) {
0397: GeolocLocation sourceGeoloc = (GeolocLocation) glmPrepHelper
0398: .getIndirectObject(task, Constants.Preposition.FROM);
0399: return (sourceGeoloc.getLongitude().getDegrees() > CONUS_THEATER_DIVIDING_LONGITUDE);
0400: }
0401:
0402: /**
0403: * sort of cheesy, but anything starting west of 25 degrees Longitude gets an initial ground leg.
0404: * (The 25 degrees can be set with a system property.)
0405: */
0406: boolean startsInCONUS(Task task) {
0407: GeolocLocation sourceGeoloc = (GeolocLocation) glmPrepHelper
0408: .getIndirectObject(task, Constants.Preposition.FROM);
0409: return (sourceGeoloc.getLongitude().getDegrees() < CONUS_THEATER_DIVIDING_LONGITUDE);
0410: }
0411:
0412: /**
0413: ** if the task is coming from CONUS, needs an air leg to get it to theater
0414: ** Also, if the task is coming from an airbase, e.g. Rhein Mein in Germany
0415: **/
0416: boolean needsAirOrSea(Task task) {
0417: String origin = glmPrepHelper.getFromLocation(task)
0418: .getGeolocCode();
0419: boolean startsAtPOE = startsAtPOE(task);
0420: boolean startsInCONUS = startsInCONUS(task);
0421:
0422: if (isDebugEnabled() && !startsInCONUS && !startsAtPOE)
0423: debug(".needsAirOrSea - could not find FROM " + origin
0424: + " on list of possible POEs : "
0425: + locator.knownGeolocCodes()
0426: + " and doesn't start in CONUS.");
0427:
0428: return startsInCONUS || startsAtPOE;
0429: }
0430:
0431: boolean startsAtPOE(Task task) {
0432: String origin = glmPrepHelper.getFromLocation(task)
0433: .getGeolocCode();
0434: Object airport = locator.getAssetAtGeolocCode(origin);
0435: return (airport != null);
0436: }
0437:
0438: /*
0439: boolean needsISB (Task task) {
0440: GeolocLocation PODGeoloc =
0441: (GeolocLocation) glmPrepHelper.getIndirectObject(task, Constants.Preposition.VIA);
0442: GLMAsset airport = (GLMAsset) geolocToAirport.get (PODGeoloc.getGeolocCode());
0443:
0444: try {
0445: AirportPG airportPG = airport.getAirportPG ();
0446: if (isDebugEnabled())
0447: debug(".needsISB - for " + PODGeoloc +
0448: " airport is " + airport + " with runway " + airportPG.getRunwayType());
0449:
0450: return (airportPG.getRunwayType().equals (SAND)); // if the airbase has sand runways, need an isb (= Cairo)
0451: }
0452: catch (Exception e) {
0453: error(".needsISB - ERROR - no airport for " + PODGeoloc);
0454: }
0455:
0456: return false;
0457: }
0458: */
0459:
0460: boolean needsCONUS(Task task) {
0461: if (glmAssetHelper.isPassenger(task.getDirectObject()))
0462: return false;
0463: boolean inCONUS = startsInCONUS(task);
0464:
0465: if (!inCONUS) {
0466: if (isDebugEnabled()) {
0467: GeolocLocation sourceGeoloc = (GeolocLocation) glmPrepHelper
0468: .getIndirectObject(task,
0469: Constants.Preposition.FROM);
0470: debug(".needsCONUS - no CONUS move needed, since from "
0471: + sourceGeoloc + " is not in CONUS.");
0472: }
0473: return false;
0474: }
0475:
0476: GeolocLocation sourceGeoloc = (GeolocLocation) glmPrepHelper
0477: .getIndirectObject(task, Constants.Preposition.FROM);
0478: String geoloc = sourceGeoloc.getGeolocCode();
0479: // Object airport = geolocToAirport.get (geoloc);
0480: Object airport = locator.getAssetAtGeolocCode(geoloc);
0481:
0482: if (isDebugEnabled()) {
0483: if (airport == null) {
0484: debug(".needsCONUS - CONUS move needed, since from <"
0485: + geoloc + "> is not a " + type()
0486: + " among these " + type() + "s : "
0487: + locator.knownGeolocCodes());
0488: } else {
0489: debug(".needsCONUS - no CONUS move needed, since from "
0490: + sourceGeoloc + " is a " + type() + " ("
0491: + airport + ").");
0492: }
0493: }
0494:
0495: // if the source is not an airbase, add a conus ground move leg to the airbase
0496: return (airport == null);
0497: }
0498:
0499: public Organization findOrgForMiddleStep(Task ignored) {
0500: Organization organicAir = findOrgWithRole(GLMTransConst.ORGANIC_AIR_ROLE);
0501: if (organicAir == null) {
0502: error(".findOrgForMiddleStep - ERROR - No subordinate with role "
0503: + GLMTransConst.ORGANIC_AIR_ROLE);
0504: return null;
0505: }
0506: return organicAir;
0507: }
0508:
0509: boolean warnedBefore = false;
0510:
0511: protected boolean allNecessaryAssetsReported() {
0512: Organization conusGround = findOrgWithRole(GLMTransConst.CONUS_GROUND_ROLE);
0513: if (conusGround == null) {
0514: if (isInfoEnabled())
0515: info("conus ground subord is missing.");
0516:
0517: return false;
0518: }
0519:
0520: if (!allNecessaryAssetsReportedMiddleStep()) {
0521: if (isInfoEnabled())
0522: info("middle (air/sea) subord is missing.");
0523:
0524: return false;
0525: }
0526:
0527: Organization theater = findOrgWithRole(GLMTransConst.THEATER_MCC_ROLE);
0528: if (theater == null) {
0529: if (isInfoEnabled())
0530: info("theater subord is missing.");
0531:
0532: return false;
0533: }
0534:
0535: List orgs = (List) roleToOrg
0536: .get(GLMTransConst.THEATER_MCC_ROLE); // sets roleToOrg
0537: if (orgs.size() < getNumTheaterGroundAgents()) {
0538: if (isWarnEnabled() && !warnedBefore) {
0539: warn("only "
0540: + orgs.size()
0541: + " theater subords have reported, expecting "
0542: + numTheaterGroundAgents
0543: + ". "
0544: + "Set numTheaterGroundAgents to 1 in GLMT.Transcom.env.xml in configs/glmtrans "
0545: + "if running in TRANSCOM-7 configuration. "
0546: + "2 is correct for the TRANSCOM-20 configuration.");
0547: warnedBefore = true;
0548: }
0549:
0550: shouldRefreshOrgList = true; // let's try again later -- see findOrgWithRole
0551:
0552: return false;
0553: }
0554:
0555: return true;
0556: }
0557:
0558: public int getNumTheaterGroundAgents() {
0559: Object ammoShipPacker = findOrgWithRole(GLMTransConst.AMMO_SHIP_PACKER_ROLE);
0560: if (getAgentIdentifier().toString().toLowerCase().startsWith(
0561: "ammo")) {
0562: return 1; // ammo sea only needs one theater ground agent - ammo theater ground
0563: } else {
0564: return numTheaterGroundAgents;
0565: }
0566: }
0567:
0568: /** overridden in sequentialglobalseaplugin */
0569: protected boolean allNecessaryAssetsReportedMiddleStep() {
0570: Organization middleOrg = findOrgWithRole(GLMTransConst.ORGANIC_AIR_ROLE);
0571: return (middleOrg != null);
0572: }
0573:
0574: protected abstract static class ElementBase extends
0575: SequentialScheduleElement {
0576: protected ElementBase(Task parent) {
0577: super (parent);
0578: }
0579:
0580: /** check to see if was an error */
0581: protected void reportZeroDuration(Allocation alloc,
0582: SequentialPlannerPlugin plugin) {
0583: GLMPrepPhrase glmPrepHelper = ((SequentialGlobalAirPlugin) plugin)
0584: .getPrepHelper();
0585: Logger logger = ((SequentialGlobalAirPlugin) plugin)
0586: .getLogger();
0587:
0588: Task task = alloc.getTask();
0589: Asset directObject = task.getDirectObject();
0590:
0591: if (!glmPrepHelper.getFromLocation(task).getGeolocCode()
0592: .equals(
0593: glmPrepHelper.getToLocation(task)
0594: .getGeolocCode()))
0595: logger
0596: .info("SequentialGlobalAirPlugin.finishPlan - WARNING - start = end time for task "
0597: + task.getUID()
0598: + " asset "
0599: + directObject.getUID()
0600: + " from "
0601: + glmPrepHelper.getFromLocation(task)
0602: + " != to "
0603: + glmPrepHelper.getToLocation(task));
0604: }
0605: }
0606:
0607: protected static class TheaterPortion extends ElementBase {
0608: public TheaterPortion(Task parent) {
0609: super (parent);
0610: }
0611:
0612: public String toString() {
0613: return "TheaterPortion";
0614: }
0615:
0616: public Task planMe(SequentialPlannerPlugin myPlugin) {
0617: SequentialGlobalAirPlugin plugin = (SequentialGlobalAirPlugin) myPlugin;
0618: Logger logger = plugin.getLogger();
0619: UTILExpand expandHelper = plugin.getExpandHelper();
0620: GLMPrepPhrase glmPrepHelper = plugin.getPrepHelper();
0621:
0622: if (logger.isDebugEnabled())
0623: logger
0624: .debug(".TheaterPortion.planMe - starting planning.");
0625:
0626: NewTask new_task = expandHelper.makeSubTask(myPlugin
0627: .publicGetFactory(), parentTask, parentTask
0628: .getDirectObject(), myPlugin
0629: .publicGetMessageAddress());
0630: new_task.setContext(parentTask.getContext());
0631:
0632: // find the theater org
0633:
0634: Organization theater = plugin
0635: .findOrgWithRole(GLMTransConst.THEATER_MCC_ROLE);
0636: if (theater == null) {
0637: logger
0638: .error(".TheaterPortion.planMe - ERROR - No subordinate with role "
0639: + GLMTransConst.THEATER_MCC_ROLE);
0640: return null;
0641: }
0642:
0643: // if we've got an air move, find the nearest airbase, otherwise, just do ground move from from loc
0644: Location PODLocation = (plugin.startsInTheater(parentTask)) ? glmPrepHelper
0645: .getFromLocation(parentTask)
0646: : plugin.getPOD(parentTask);
0647:
0648: glmPrepHelper.replacePrepOnTask(new_task, glmPrepHelper
0649: .makePrepositionalPhrase(plugin.publicGetFactory(),
0650: Constants.Preposition.FROM, PODLocation));
0651: if (logger.isDebugEnabled())
0652: logger
0653: .debug(".TheaterPortion.planMe - created leg FROM "
0654: + PODLocation
0655: + " TO "
0656: + glmPrepHelper.getToLocation(new_task));
0657:
0658: glmPrepHelper.removePrepNamed(new_task,
0659: GLMTransConst.SEAROUTE);
0660: glmPrepHelper.removePrepNamed(new_task,
0661: GLMTransConst.SEAROUTE_DISTANCE);
0662:
0663: PlanElement pe = plugin.getAllocHelper().makeAllocation(
0664: myPlugin, myPlugin.publicGetFactory(),
0665: myPlugin.publicGetRealityPlan(), new_task, theater,
0666: plugin.getPrefHelper().getReadyAt(new_task),
0667: plugin.getPrefHelper().getBestDate(new_task),
0668: plugin.getAllocHelper().MEDIUM_CONFIDENCE,
0669: Constants.Role.TRANSPORTER);
0670: myPlugin.publicPublishAdd(pe);
0671: return new_task;
0672: }
0673: }
0674:
0675: /** comment this back in whenever we want to revivify the ISB planning */
0676: /*
0677: protected class IsbPortion extends ElementBase {
0678: protected double myMaxCost = BILLION;
0679:
0680: public IsbPortion(Task parent) {
0681: super(parent);
0682: }
0683:
0684: public String toString () { return "IsbPortion"; }
0685:
0686: public Task planMe(SequentialPlannerPlugin myPlugin) {
0687: SequentialGlobalAirPlugin plugin = (SequentialGlobalAirPlugin) myPlugin;
0688: Logger logger = plugin.getLogger();
0689: UTILExpand expandHelper = plugin.getExpandHelper();
0690: GLMPrepPhrase glmPrepHelper = plugin.getPrepHelper();
0691: if (logger.isDebugEnabled())
0692: logger.debug (".IsbPortion.planMe - starting planning.");
0693:
0694: NewTask new_task = expandHelper.makeSubTask(myPlugin.publicGetFactory(),
0695: parentTask,
0696: parentTask.getDirectObject(),
0697: myPlugin.publicGetMessageAddress());
0698:
0699: // find the ISB org
0700: Organization isb = plugin.findOrgWithRole(GLMTransConst.C130_ROLE);
0701: if (isb == null) {
0702: logger.error(".IsbPortion.planMe - ERROR - No subordinate with role " +
0703: GLMTransConst.C130_ROLE);
0704: return null;
0705: }
0706:
0707: Organization theater = plugin.findOrgWithRole(GLMTransConst.THEATER_MCC_ROLE);
0708: if (theater == null) {
0709: logger.error(".TheaterPortion.planMe - ERROR - No subordinate with role " +
0710: GLMTransConst.THEATER_MCC_ROLE);
0711: return null;
0712: }
0713:
0714: Date end = null;
0715:
0716: if (getDependencies().isEmpty()) { // if there was no theater leg
0717: end = prefHelper.getLateDate(parentTask);
0718: if (logger.isDebugEnabled())
0719: logger.debug (".IsbPortion.planMe - no dependencies, end preference is " +
0720: end);
0721: } else {
0722: end = ((SequentialScheduleElement)getDependencies().elementAt(0)).getStartDate();
0723: prefHelper.replacePreference(new_task,
0724: prefHelper.makeEndDatePreference(myPlugin.publicGetFactory(), end));
0725: if (logger.isDebugEnabled())
0726: logger.debug (".IsbPortion.planMe - dependent on theater, end preference is " +
0727: end);
0728: }
0729:
0730: Location isbLocation = plugin.getISBLocation(end); // doesn't matter when
0731: Location PODLocation = plugin.getPOD (parentTask);
0732:
0733: glmPrepHelper.replacePrepOnTask(new_task,
0734: glmPrepHelper.makePrepositionalPhrase(myPlugin.publicGetFactory(),
0735: Constants.Preposition.FROM,
0736: isbLocation));
0737: glmPrepHelper.replacePrepOnTask(new_task,
0738: glmPrepHelper.makePrepositionalPhrase(myPlugin.publicGetFactory(),
0739: Constants.Preposition.TO,
0740: PODLocation));
0741:
0742: glmPrepHelper.removePrepNamed(new_task, GLMTransConst.MODE);
0743:
0744: new_task.addPreference (prefHelper.makeCostPreference (myPlugin.publicGetFactory(), myMaxCost));
0745:
0746: List aspects = new ArrayList ();
0747: aspects.add (AspectValue.newAspectValue (AspectType.START_TIME,
0748: (double) prefHelper.getReadyAt(new_task).getTime ()));
0749: aspects.add (AspectValue.newAspectValue (AspectType.END_TIME,
0750: (double) end.getTime ()));
0751: aspects.add (AspectValue.newAspectValue (AspectType.COST, 0));
0752:
0753: PlanElement c130_alloc = plugin.getAllocHelper().makeAllocation (myPlugin,
0754: myPlugin.publicGetFactory(),
0755: myPlugin.publicGetRealityPlan(),
0756: new_task,
0757: isb,
0758: (AspectValue []) aspects.toArray (new AspectValue[0]),
0759: plugin.getAllocHelper().MEDIUM_CONFIDENCE,
0760: Constants.Role.TRANSPORTER);
0761: myPlugin.publicPublishAdd(c130_alloc);
0762: return new_task;
0763: }
0764: }
0765: */
0766:
0767: protected static class AirPortion extends ElementBase {
0768: public AirPortion(Task parent) {
0769: super (parent);
0770: }
0771:
0772: public String toString() {
0773: return "AirPortion";
0774: }
0775:
0776: public Task planMe(SequentialPlannerPlugin myPlugin) {
0777: SequentialGlobalAirPlugin plugin = (SequentialGlobalAirPlugin) myPlugin;
0778: Logger logger = plugin.getLogger();
0779: UTILExpand expandHelper = plugin.getExpandHelper();
0780: GLMPrepPhrase glmPrepHelper = plugin.getPrepHelper();
0781:
0782: if (logger.isDebugEnabled())
0783: logger.debug(".AirPortion.planMe - starting planning.");
0784:
0785: NewTask new_task = expandHelper.makeSubTask(myPlugin
0786: .publicGetFactory(), parentTask, parentTask
0787: .getDirectObject(), myPlugin
0788: .publicGetMessageAddress());
0789: new_task.setContext(parentTask.getContext());
0790:
0791: Vector getDependencies = getDependencies();
0792:
0793: /*
0794: boolean dependsOnISB = false;
0795:
0796: for (int i = 0; i < getDependencies.size(); i++) {
0797: if (getDependencies.get (i) instanceof IsbPortion) {
0798: dependsOnISB = true;
0799: break;
0800: }
0801: }
0802: */
0803:
0804: Location[] locations = plugin.getPOEandPOD(parentTask,
0805: new_task);
0806: Location fromLocation = locations[0];
0807: Location toLocation = locations[1];
0808:
0809: Date end = null;
0810: Date early, best;
0811:
0812: if (getDependencies().isEmpty()) { // if there was neither a theater nor a isb leg
0813: end = plugin.getPrefHelper().getLateDate(parentTask);
0814: best = end;
0815: } else {
0816: SequentialScheduleElement sse = (SequentialScheduleElement) getDependencies()
0817: .elementAt(0);
0818: end = sse.getStartDate();
0819: // early = plugin.getPrefHelper().getReadyAt(new_task);
0820: best = new Date(end.getTime() - plugin.bestDateBackoff);
0821: early = plugin
0822: .getEarlyArrivalMiddleStep(new_task, best);
0823: if (best.getTime() < early.getTime())
0824: best = early;
0825:
0826: plugin.getPrefHelper().replacePreference(
0827: new_task,
0828: plugin.getPrefHelper().makeEndDatePreference(
0829: myPlugin.publicGetFactory(), early,
0830: best, end));
0831: GeolocLocation theaterLegFrom = plugin.getPrepHelper()
0832: .getFromLocation(sse.getTask());
0833:
0834: if (!theaterLegFrom.getGeolocCode().equals(
0835: ((GeolocLocation) toLocation).getGeolocCode()))
0836: plugin.getLogger().error(
0837: " - Theater leg task "
0838: + sse.getTask().getUID() + " FROM "
0839: + theaterLegFrom
0840: + " is not equal to air/sea TO "
0841: + toLocation);
0842:
0843: // if (dependsOnISB)
0844: // toLocation = plugin.getISBLocation(end); // doesn't matter when
0845: }
0846:
0847: if (logger.isDebugEnabled())
0848: logger.debug(".AirPortion.planMe - created leg FROM "
0849: + fromLocation + " TO " + toLocation);
0850:
0851: glmPrepHelper.replacePrepOnTask(new_task, glmPrepHelper
0852: .makePrepositionalPhrase(myPlugin
0853: .publicGetFactory(),
0854: Constants.Preposition.FROM, fromLocation));
0855:
0856: glmPrepHelper.replacePrepOnTask(new_task, glmPrepHelper
0857: .makePrepositionalPhrase(myPlugin
0858: .publicGetFactory(),
0859: Constants.Preposition.TO, toLocation));
0860:
0861: Organization middleOrg = plugin
0862: .findOrgForMiddleStep(new_task);
0863:
0864: List aspects = new ArrayList();
0865: aspects.add(AspectValue.newAspectValue(
0866: AspectType.START_TIME, (double) plugin
0867: .getPrefHelper().getReadyAt(new_task)
0868: .getTime()));
0869: aspects.add(AspectValue.newAspectValue(AspectType.END_TIME,
0870: (double) best.getTime()));
0871:
0872: plugin.removePrepsFromMiddleStep(new_task);
0873:
0874: PlanElement pe = plugin.getAllocHelper()
0875: .makeAllocation(
0876: myPlugin,
0877: myPlugin.publicGetFactory(),
0878: myPlugin.publicGetRealityPlan(),
0879: new_task,
0880: middleOrg,
0881: (AspectValue[]) aspects
0882: .toArray(new AspectValue[0]),
0883: plugin.getAllocHelper().MEDIUM_CONFIDENCE,
0884: Constants.Role.TRANSPORTER);
0885:
0886: myPlugin.publicPublishAdd(pe);
0887: return new_task;
0888: }
0889:
0890: }
0891:
0892: protected Date getEarlyArrivalMiddleStep(Task task, Date best) {
0893: return prefHelper.getReadyAt(task);
0894: }
0895:
0896: protected void removePrepsFromMiddleStep(Task new_task) {
0897: glmPrepHelper.removePrepNamed(new_task, GLMTransConst.SEAROUTE);
0898: glmPrepHelper.removePrepNamed(new_task,
0899: GLMTransConst.SEAROUTE_DISTANCE);
0900: }
0901:
0902: protected static class ConusPortion extends ElementBase {
0903: public ConusPortion(Task parent) {
0904: super (parent);
0905: }
0906:
0907: public String toString() {
0908: return "ConusPortion";
0909: }
0910:
0911: public Task planMe(SequentialPlannerPlugin myPlugin) {
0912: SequentialGlobalAirPlugin plugin = (SequentialGlobalAirPlugin) myPlugin;
0913: Logger logger = plugin.getLogger();
0914: UTILExpand expandHelper = plugin.getExpandHelper();
0915: GLMPrepPhrase glmPrepHelper = plugin.getPrepHelper();
0916: Location toLocation = null;
0917: Date end = null;
0918:
0919: NewTask new_task = expandHelper.makeSubTask(myPlugin
0920: .publicGetFactory(), parentTask, parentTask
0921: .getDirectObject(), myPlugin
0922: .publicGetMessageAddress());
0923: new_task.setContext(parentTask.getContext());
0924:
0925: if (!getDependencies().isEmpty()) {
0926: SequentialScheduleElement sse = (SequentialScheduleElement) getDependencies()
0927: .elementAt(0);
0928: Task dependingTask = sse.getTask();
0929: if (dependingTask == null) {
0930: logger
0931: .error(" - problem with replanning earlier tasks - no task on schedule element "
0932: + sse);
0933: } else {
0934: end = sse.getStartDate();
0935: toLocation = glmPrepHelper
0936: .getFromLocation(dependingTask);
0937: }
0938: } else {
0939: end = plugin.getPrefHelper().getLateDate(new_task);
0940: toLocation = plugin.getLocator()
0941: .getPOENearestToFromLoc(parentTask);
0942: }
0943:
0944: Date early = plugin.getPrefHelper().getReadyAt(new_task);
0945: Date best = new Date(end.getTime() - 1000);
0946:
0947: plugin.getPrefHelper().replacePreference(
0948: new_task,
0949: plugin.getPrefHelper().makeEndDatePreference(
0950: myPlugin.publicGetFactory(), early, best,
0951: end));
0952:
0953: glmPrepHelper.replacePrepOnTask(new_task, glmPrepHelper
0954: .makePrepositionalPhrase(myPlugin
0955: .publicGetFactory(),
0956: Constants.Preposition.TO, toLocation));
0957: if (logger.isDebugEnabled())
0958: logger.debug(".ConusPortion.planMe - created leg FROM "
0959: + glmPrepHelper.getFromLocation(new_task)
0960: + " TO " + toLocation);
0961:
0962: Organization conusGround = plugin
0963: .findOrgWithRole(GLMTransConst.CONUS_GROUND_ROLE);
0964: if (conusGround == null) {
0965: logger
0966: .error(".ConusPortion.planMe - ERROR - No subordinate with role "
0967: + GLMTransConst.CONUS_GROUND_ROLE);
0968: return null;
0969: }
0970:
0971: glmPrepHelper.removePrepNamed(new_task,
0972: GLMTransConst.SEAROUTE);
0973: glmPrepHelper.removePrepNamed(new_task,
0974: GLMTransConst.SEAROUTE_DISTANCE);
0975:
0976: PlanElement pe = plugin.getAllocHelper().makeAllocation(
0977: myPlugin,
0978: myPlugin.publicGetFactory(),
0979: myPlugin.publicGetRealityPlan(),
0980: new_task,
0981: conusGround, // allocate to conus ground
0982: plugin.getPrefHelper().getReadyAt(new_task), end,
0983: plugin.getAllocHelper().MEDIUM_CONFIDENCE,
0984: Constants.Role.TRANSPORTER);
0985: myPlugin.publicPublishAdd(pe);
0986: return new_task;
0987: }
0988:
0989: public void finishPlan(Allocation alloc,
0990: SequentialPlannerPlugin myPlugin) {
0991: SequentialGlobalAirPlugin plugin = (SequentialGlobalAirPlugin) myPlugin;
0992: Logger logger = plugin.getLogger();
0993:
0994: if (logger.isDebugEnabled())
0995: logger
0996: .debug(".ConusPortion.finishPlan - Planning complete.");
0997: super .finishPlan(alloc, plugin);
0998: }
0999: }
1000:
1001: /** supports finding an ISB at a certain time -- assumes it can move! */
1002: /*
1003: Location getISBLocation (Date when) {
1004: Organization isb = findOrgWithRole (GLMTransConst.C130_ROLE);
1005: Location loc = (Location) airportToLocation.get (isb);
1006: if (loc == null) {
1007: loc = findLocationAtTime (isb, when.getTime());
1008: airportToLocation.put (isb, loc);
1009: }
1010: return loc;
1011: }
1012: */
1013:
1014: /**
1015: * <pre>
1016: * Given a task, find the POE and POD for the task
1017: * This will be a search among possible POEs and PODs for those that
1018: * are closest to the FROM-TO pair on the parent task.
1019: *
1020: * The choice will be affected by the how long it takes
1021: * to get from POE to POD.
1022: * </pre>
1023: */
1024: protected Location[] getPOEandPOD(Task parentTask, Task subtask) {
1025: Location[] locs = new Location[2];
1026:
1027: locs[0] = locator.getPOENearestToFromLoc(parentTask);
1028: locs[1] = getPOD(parentTask);
1029:
1030: return locs;
1031: }
1032:
1033: /**
1034: * Uses locator to get POD
1035: **/
1036: Location getPOD(Task task) {
1037: /*
1038: Location POD =locator.getNearestLocation(glmPrepHelper.getToLocation(task));
1039: System.out.println ("SeqGlobalAir.getPOD - chose POD " + POD +
1040: " nearest to " + glmPrepHelper.getToLocation(task) + " from among " +
1041: ((LocatorImpl)locator).myLocations);
1042: */
1043: return (Location) locator.getNearestLocation(glmPrepHelper
1044: .getToLocation(task));
1045: }
1046:
1047: Location getPOENearestToFromLocMiddleStep(Task parentTask) {
1048: return locator.getPOENearestToFromLoc(parentTask);
1049: }
1050:
1051: /**
1052: * cache role to org mapping <p>
1053: *
1054: * Supports spawning -- choosing among several possible subordinates with role
1055: * <tt>role</tt>. <p>
1056: *
1057: * Calls chooseAmongOrgs.
1058: *
1059: * @see #chooseAmongOrgs
1060: */
1061: public Organization findOrgWithRole(Role role) {
1062: List orgs = (List) roleToOrg.get(role);
1063:
1064: if (orgs == null || shouldRefreshOrgList) {
1065: orgs = new ArrayList();
1066: roleToOrg.put(role, orgs);
1067: RelationshipSchedule sched = getSelf()
1068: .getRelationshipSchedule();
1069: Collection matchingRels = sched.getMatchingRelationships(
1070: role, TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
1071: if (isInfoEnabled()) {
1072: info(getName() + " found " + matchingRels.size()
1073: + " matches for role " + role);
1074: }
1075: for (Iterator it = matchingRels.iterator(); it.hasNext();) {
1076: Relationship rel = (Relationship) it.next();
1077: Object other = sched.getOther(rel);
1078: if (isInfoEnabled()) {
1079: info(getName() + " adding other " + other
1080: + " to known orgs for " + role);
1081: }
1082: orgs.add(other);
1083:
1084: if (isInfoEnabled()) {
1085: info(getName() + " has " + orgs.size()
1086: + " orgs for role " + role);
1087: }
1088: }
1089:
1090: if (matchingRels.size() == 1) {
1091: Collection selfProviders = sched
1092: .getMatchingRelationships(
1093: Constants.RelationshipType.PROVIDER_SUFFIX,
1094: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
1095:
1096: info(getName() + " self providers schedule was "
1097: + selfProviders);
1098: /*
1099: List otherWay = getOrgsWithRole (role);
1100: if (otherWay.size () > 1) {
1101: info (getName () + " found more orgs by direct interrogation, so using them.");
1102: orgs = otherWay;
1103: }
1104: */
1105: }
1106:
1107: shouldRefreshOrgList = false;
1108: }
1109:
1110: if (orgs.isEmpty()) {
1111: if (isInfoEnabled()) {
1112: info(getName()
1113: + ".findOrgWithRole - could not find any organizations with role "
1114: + role
1115: + " among subordinates -- relationship schedule is:\n"
1116: + getSelf().getRelationshipSchedule());
1117: }
1118:
1119: return null;
1120: }
1121:
1122: return chooseAmongOrgs(orgs);
1123: }
1124:
1125: /**
1126: * thought this might help, but didn't - self org and individual org role schedules
1127: * do in fact agree
1128: */
1129: protected List getOrgsWithRole(Role role) {
1130: // send subscription contents through again...
1131: Collection assets = getOrganizationCallback().getSubscription()
1132: .getCollection();
1133: List orgs = new ArrayList();
1134:
1135: for (Iterator iter = assets.iterator(); iter.hasNext();) {
1136: Asset asset = (Asset) iter.next();
1137: if (asset instanceof Organization) {
1138: String name = dataXMLizer.getOrganizationRole(asset);
1139:
1140: if (isInfoEnabled()) {
1141: info(getName() + " examining " + asset
1142: + " for role " + role + " says it's "
1143: + name);
1144: }
1145: if (role.getName().equals(name)) {
1146: if (isInfoEnabled()) {
1147: info(getName() + " " + asset
1148: + " indeed has role " + role);
1149: }
1150:
1151: orgs.add(asset);
1152: }
1153: }
1154: }
1155:
1156: return orgs;
1157: }
1158:
1159: /**
1160: * re-examine the workflow to see if the any tasks overlap the time
1161: * of the recently changed allocation, if they do, replan tasks
1162: * that depend on it.
1163: */
1164: protected void replanDependingTasks(Task parentTask, long beforeTime) {
1165: Expansion exp = (Expansion) parentTask.getPlanElement();
1166: if (exp == null) {
1167: if (isInfoEnabled()) {
1168: info("no expansion for " + parentTask.getUID()
1169: + " must be in middle of rescinds.");
1170: }
1171:
1172: return;
1173: }
1174:
1175: PrepositionalPhrase prep = prepHelper.getPrepNamed(parentTask,
1176: GLMTransConst.SequentialSchedule);
1177: Schedule sched = (Schedule) prep.getIndirectObject();
1178: Enumeration en = sched.getAllScheduleElements();
1179: boolean overlap = false;
1180: Set toReplan = new HashSet();
1181:
1182: while (en.hasMoreElements()) {
1183: SequentialScheduleElement spe = (SequentialScheduleElement) en
1184: .nextElement();
1185: String uid = "<NO TASK>";
1186: if (spe.getTask() != null)
1187: uid = spe.getTask().getUID().toString();
1188:
1189: if (isInfoEnabled()) {
1190: info("for task " + parentTask.getUID() + " spe task "
1191: + uid + " spe planned " + spe.isPlanned()
1192: + " spe end date " + spe.getEndDate()
1193: + " before time " + new Date(beforeTime));
1194: }
1195:
1196: if (spe.isPlanned()) {
1197: for (Iterator iter = spe.getDependencies().iterator(); iter
1198: .hasNext();) {
1199: SequentialScheduleElement dependency = (SequentialScheduleElement) iter
1200: .next();
1201:
1202: // |--- spe ---| (overlap)
1203: // |--- dep ---|
1204: // OR
1205: // |--- dep ---| |--- spe ---| (dependency should always be after!)
1206:
1207: if (spe.overlapSchedule(dependency)
1208: || dependency.getEndTime() < spe
1209: .getStartTime()) {
1210: if (isInfoEnabled()) {
1211: info("for task " + parentTask.getUID()
1212: + " replanning spe at "
1213: + spe.getEndDate());
1214: }
1215: toReplan.add(spe);
1216: }
1217: }
1218: }
1219: }
1220:
1221: for (Iterator iter = toReplan.iterator(); iter.hasNext();) {
1222: SequentialScheduleElement replanSSE = (SequentialScheduleElement) iter
1223: .next();
1224: replanPortion(exp, replanSSE);
1225: }
1226:
1227: // let's replan!
1228: if (!toReplan.isEmpty()) {
1229: if (isInfoEnabled()) {
1230: info("got overlap of " + parentTask.getUID());
1231: }
1232: turnCrank(parentTask);
1233: }
1234: }
1235:
1236: protected void replanPortion(Expansion exp,
1237: SequentialScheduleElement spe) {
1238: handleRemovedAlloc((Allocation) spe.getTask().getPlanElement());
1239: if (exp != null) { // fix for bug #13417
1240: try {
1241: NewWorkflow nw = (NewWorkflow) exp.getWorkflow();
1242: if (nw != null)
1243: nw.removeTask(spe.getTask());
1244: publishRemove(spe.getTask());
1245: } catch (IllegalArgumentException iae) {
1246: error(getName()
1247: + " - task "
1248: + spe.getTask().getUID()
1249: + " is not in workflow for task "
1250: + exp.getTask().getUID()
1251: + " - likely rescinds happening concurrently. Exception was "
1252: + iae);
1253: }
1254: publishChange(exp);
1255: }
1256:
1257: spe.unplan();
1258: spe.setTask(null);
1259: }
1260:
1261: /**
1262: * this could be more sophisticated in the future
1263: *
1264: * Right now, just round-robin.
1265: */
1266: protected Organization chooseAmongOrgs(List orgs) {
1267: int i = r.nextInt(orgs.size());
1268:
1269: if (isDebugEnabled())
1270: debug(".chooseAmongOrgs - choosing org #" + i + " ("
1271: + orgs.get(i) + ") from " + orgs.size() + " orgs :"
1272: + orgs);
1273:
1274: return (Organization) orgs.get(i);
1275: }
1276:
1277: private Location findLocationAtTime(Organization org, long time) {
1278: LocationSchedulePG locPG = org.getLocationSchedulePG();
1279: if (locPG == null) {
1280: MilitaryOrgPG moPG = org.getMilitaryOrgPG();
1281: return moPG.getHomeLocation();
1282: }
1283:
1284: Schedule sched = locPG.getSchedule();
1285: Collection schedElements = sched
1286: .getScheduleElementsWithTime(time);
1287: LocationScheduleElement lse = (LocationScheduleElement) schedElements
1288: .iterator().next();
1289: return lse.getLocation();
1290: }
1291:
1292: public GLMPrepPhrase getPrepHelper() {
1293: return glmPrepHelper;
1294: }
1295:
1296: public AssetUtil getAssetHelper() {
1297: return glmAssetHelper;
1298: }
1299:
1300: public UTILExpand getExpandHelper() {
1301: return expandHelper;
1302: }
1303:
1304: public UTILPreference getPrefHelper() {
1305: return prefHelper;
1306: }
1307:
1308: public UTILAllocate getAllocHelper() {
1309: return allocHelper;
1310: }
1311:
1312: public Logger getLogger() {
1313: return logger;
1314: }
1315:
1316: public Locator getLocator() {
1317: return locator;
1318: }
1319:
1320: protected GLMOrganizationCallback myOrgCallback;
1321:
1322: protected Map roleToOrg = new HashMap();
1323: protected Locator locator;
1324:
1325: protected long bestDateBackoff;
1326: boolean shouldRefreshOrgList = false;
1327: private Random r = new Random();
1328:
1329: protected transient GLMPrepPhrase glmPrepHelper;
1330: protected transient AssetUtil glmAssetHelper;
1331: }
|