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.ArrayList;
0030: import java.util.Collection;
0031: import java.util.Date;
0032: import java.util.Enumeration;
0033: import java.util.Iterator;
0034: import java.util.Vector;
0035:
0036: import org.cougaar.core.blackboard.IncrementalSubscription;
0037: import org.cougaar.core.util.UID;
0038: import org.cougaar.glm.ldm.Constants;
0039: import org.cougaar.glm.ldm.GLMFactory;
0040: import org.cougaar.glm.ldm.asset.Ammunition;
0041: import org.cougaar.glm.ldm.asset.AssignedPGImpl;
0042: import org.cougaar.glm.ldm.asset.BulkPOL;
0043: import org.cougaar.glm.ldm.asset.CSSCapabilityPG;
0044: import org.cougaar.glm.ldm.asset.CSSCapabilityPGImpl;
0045: import org.cougaar.glm.ldm.asset.Capacity;
0046: import org.cougaar.glm.ldm.asset.NewAssignedPG;
0047: import org.cougaar.glm.ldm.asset.NewCSSCapabilityPG;
0048: import org.cougaar.glm.ldm.asset.NewScheduledContentPG;
0049: import org.cougaar.glm.ldm.asset.Organization;
0050: import org.cougaar.glm.ldm.asset.ScheduledContentPGImpl;
0051: import org.cougaar.glm.ldm.oplan.Oplan;
0052: import org.cougaar.glm.ldm.plan.CSSCapability;
0053: import org.cougaar.glm.ldm.plan.CapacityType;
0054: import org.cougaar.glm.ldm.plan.NewQuantityScheduleElement;
0055: import org.cougaar.glm.ldm.plan.PlanScheduleType;
0056: import org.cougaar.glm.ldm.plan.QuantityScheduleElement;
0057: import org.cougaar.glm.ldm.plan.QuantityScheduleElementImpl;
0058: import org.cougaar.planning.ldm.asset.AggregateAsset;
0059: import org.cougaar.planning.ldm.asset.Asset;
0060: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
0061: import org.cougaar.planning.ldm.asset.TypeIdentificationPGImpl;
0062: import org.cougaar.planning.ldm.measure.Duration;
0063: import org.cougaar.planning.ldm.measure.Mass;
0064: import org.cougaar.planning.ldm.measure.Volume;
0065: import org.cougaar.planning.ldm.plan.Allocation;
0066: import org.cougaar.planning.ldm.plan.AllocationResult;
0067: import org.cougaar.planning.ldm.plan.Annotation;
0068: import org.cougaar.planning.ldm.plan.AspectType;
0069: import org.cougaar.planning.ldm.plan.AspectValue;
0070: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
0071: import org.cougaar.planning.ldm.plan.NewRoleSchedule;
0072: import org.cougaar.planning.ldm.plan.NewSchedule;
0073: import org.cougaar.planning.ldm.plan.NewTask;
0074: import org.cougaar.planning.ldm.plan.Plan;
0075: import org.cougaar.planning.ldm.plan.Preference;
0076: import org.cougaar.planning.ldm.plan.Relationship;
0077: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
0078: import org.cougaar.planning.ldm.plan.Role;
0079: import org.cougaar.planning.ldm.plan.RoleSchedule;
0080: import org.cougaar.planning.ldm.plan.Schedule;
0081: import org.cougaar.planning.ldm.plan.ScheduleUtilities;
0082: import org.cougaar.planning.ldm.plan.ScoringFunction;
0083: import org.cougaar.planning.ldm.plan.Task;
0084: import org.cougaar.planning.ldm.plan.TimeAspectValue;
0085: import org.cougaar.planning.ldm.plan.TypedQuantityAspectValue;
0086: import org.cougaar.planning.ldm.plan.Verb;
0087: import org.cougaar.planning.plugin.legacy.SimplePlugin;
0088: import org.cougaar.planning.plugin.util.AllocatorHelper;
0089: import org.cougaar.util.TimeSpan;
0090: import org.cougaar.util.UnaryPredicate;
0091:
0092: /**
0093: * Plugin to allocate Fuel and Ammunition Load and in theater Transport task.
0094: * At FSB, Load tasks are allocated to capacity object; Transport tasks are allocated
0095: * to FuelTransportProvider/AmmunitionTransportProvider aka MSB.
0096: *
0097: * At MSB, Transport tasks are allocated to capacity object. Load tasks are unexpected
0098: *
0099: * No tasks receive failed allocations.
0100: * If capacity is exceded, a SupportRequest task is issued. The resulsts of the SupportRequest
0101: * task are not checked. The plugin assumes that the task is successfull and the available
0102: * capacity is increased accordingly
0103: *
0104: */
0105:
0106: public class LoadAllocatorPlugin extends SimplePlugin {
0107:
0108: // Capacity assets to which tasks are allocated
0109: private LACapacity fuelHandlingCapacity = null;
0110: private LACapacity fuelTransportCapacity = null;
0111: private LACapacity ammoHandlingCapacity = null;
0112: private LACapacity ammoTransportCapacity = null;
0113:
0114: // Only one plan this year. This will be a bug soon
0115: private Plan thePlan;
0116:
0117: // MSB or FSB? (MSB is a transporter)
0118: private boolean isTransporter = false;
0119:
0120: private IncrementalSubscription capacitySubs;
0121: private static UnaryPredicate capacityPredicate = new UnaryPredicate() {
0122: public boolean execute(Object o) {
0123: if (o instanceof Capacity) {
0124: return true;
0125: }
0126: return false;
0127: }
0128: };
0129:
0130: // Oplan is needed for start date.
0131: // End date is wrongly assumed to be 181 days + start date.
0132: // End date should be gleened from OrgActivities
0133: private long oplanStartTime = 0;
0134: private long oplanEndTime = 0;
0135: private IncrementalSubscription oplanSubs;
0136: private static UnaryPredicate oplanPredicate = new UnaryPredicate() {
0137: public boolean execute(Object o) {
0138: if (o instanceof Oplan) {
0139: return true;
0140: }
0141: return false;
0142: }
0143: };
0144:
0145: // Load tasks to be allocated
0146: private IncrementalSubscription transportTasks;
0147: private static UnaryPredicate transportTasksPredicate = new UnaryPredicate() {
0148: public boolean execute(Object o) {
0149: if (o instanceof Task) {
0150: Task t = (Task) o;
0151: if (t.getVerb().equals(Constants.Verb.TRANSPORT)) {
0152: if (AllocatorHelper.isOfType(t,
0153: Constants.Preposition.OFTYPE,
0154: "TheaterTransportation")) {
0155: return true;
0156: }
0157: }
0158: }
0159: return false;
0160: }
0161: };
0162:
0163: // Transport tasks to be allocated
0164: private IncrementalSubscription loadTasks;
0165: private static UnaryPredicate loadTasksPredicate = new UnaryPredicate() {
0166: public boolean execute(Object o) {
0167: if (o instanceof Task) {
0168: Task t = (Task) o;
0169: if (t.getVerb().equals(Constants.Verb.LOAD)) {
0170: Object directObject = t.getDirectObject();
0171: if ((directObject instanceof BulkPOL)
0172: || (directObject instanceof Ammunition)) {
0173: return true;
0174: }
0175: }
0176: }
0177: return false;
0178: }
0179: };
0180:
0181: // This organization/cluster
0182: // Used to find default values for capacities in CSSCapabilitiesPG
0183: private Organization this Org = null;
0184: private IncrementalSubscription this OrgSubs;
0185: private static UnaryPredicate this OrgPredicate = new UnaryPredicate() {
0186: public boolean execute(Object o) {
0187: if (o instanceof Organization) {
0188: return ((Organization) o).isSelf();
0189: }
0190: return false;
0191: }
0192: };
0193:
0194: private IncrementalSubscription supportRequestAllocationSubs;
0195: private static UnaryPredicate supportRequestAllocationPredicate = new UnaryPredicate() {
0196: public boolean execute(Object o) {
0197: if (o instanceof Allocation) {
0198: Task t = ((Allocation) o).getTask();
0199: if (t.getVerb().equals(Constants.Verb.SUPPORTREQUEST)) {
0200: return true;
0201: }
0202: }
0203: return false;
0204: }
0205: };
0206:
0207: private Organization getRoleProvider(Role role, boolean selfRole) {
0208: // This method, like the rest of the plugin, needs to be fixed to support multiple oplans
0209:
0210: //getMatchingRelationships screens on other orgs role. We're looking at the
0211: //self orgs schedule so ... if we want to know if self org provides to other
0212: //an org, we need to screen on the role converse. Example
0213: //self.getMatchingRelationship(STRATEGICTRANSPORTPROVIDER) returns the
0214: //strat trans providers to the self org.
0215: //get.getMatchingRelationship(STRATEGICTRANSPORTCUSTOMER) returns the
0216: //orgs that self supports as a strat trans provider
0217: if (selfRole) {
0218: role = role.getConverse();
0219: }
0220:
0221: RelationshipSchedule this OrgSchedule = this Org
0222: .getRelationshipSchedule();
0223:
0224: Collection providers = this OrgSchedule
0225: .getMatchingRelationships(role, TimeSpan.MIN_VALUE,
0226: TimeSpan.MAX_VALUE);
0227:
0228: if (selfRole) {
0229: return (providers.size() > 0) ? this Org : null;
0230: } else if (providers.size() > 0) {
0231: Relationship relationship = (Relationship) providers
0232: .iterator().next();
0233: return (Organization) this OrgSchedule
0234: .getOther(relationship);
0235: } else {
0236: return null;
0237: }
0238: }
0239:
0240: private boolean isMSB() {
0241: Organization fuelTP = getRoleProvider(
0242: Constants.Role.FUELTRANSPORTPROVIDER, true);
0243: if (fuelTP != null) {
0244: return true;
0245: } else {
0246: Organization ammoTP = getRoleProvider(
0247: Constants.Role.AMMUNITIONTRANSPORTPROVIDER, true);
0248: if (ammoTP != null) {
0249: return true;
0250: }
0251: }
0252: return false;
0253: }
0254:
0255: public void setupSubscriptions() {
0256: //System.out.println("In LoadAllocatorPlugin.setupSubscriptions");
0257: // Subscribe for transport tasks
0258: transportTasks = (IncrementalSubscription) subscribe(transportTasksPredicate);
0259: loadTasks = (IncrementalSubscription) subscribe(loadTasksPredicate);
0260: this OrgSubs = (IncrementalSubscription) subscribe(this OrgPredicate);
0261: oplanSubs = (IncrementalSubscription) subscribe(oplanPredicate);
0262: capacitySubs = (IncrementalSubscription) subscribe(capacityPredicate);
0263: supportRequestAllocationSubs = (IncrementalSubscription) subscribe(supportRequestAllocationPredicate);
0264:
0265: if (didRehydrate()) {
0266:
0267: for (Enumeration e = this OrgSubs.elements(); e
0268: .hasMoreElements();) {
0269: // only expecting one
0270: this Org = (Organization) e.nextElement();
0271: // Are we an MSB?
0272: isTransporter = isMSB();
0273: break;
0274: }
0275:
0276: // recreate the local variables
0277: // Can I assume that the elements of my subscriptions are available now?
0278: LACapacity capacities[] = new LACapacity[4]; // should only be 2
0279: int i = 0;
0280: for (Enumeration e = capacitySubs.elements(); e
0281: .hasMoreElements();) {
0282: Capacity c = (Capacity) e.nextElement();
0283: String typeID = c.getTypeIdentificationPG()
0284: .getTypeIdentification();
0285: if (CapacityType.FUELHANDLING.equals(typeID)) {
0286: fuelHandlingCapacity = new LACapacity(c);
0287: capacities[i++] = fuelHandlingCapacity;
0288: } else if (CapacityType.AMMUNITIONHANDLING
0289: .equals(typeID)) {
0290: ammoHandlingCapacity = new LACapacity(c);
0291: capacities[i++] = ammoHandlingCapacity;
0292: } else if (CapacityType.FUELTRANSPORTATION
0293: .equals(typeID)) {
0294: fuelTransportCapacity = new LACapacity(c);
0295: capacities[i++] = fuelTransportCapacity;
0296: }
0297: if (CapacityType.AMMUNITIONTRANSPORTATION
0298: .equals(typeID)) {
0299: ammoTransportCapacity = new LACapacity(c);
0300: capacities[i++] = ammoHandlingCapacity;
0301: }
0302: }
0303:
0304: for (Enumeration e = supportRequestAllocationSubs
0305: .elements(); e.hasMoreElements();) {
0306: Allocation a = (Allocation) e.nextElement();
0307: Task t = a.getTask();
0308: MyAnnotation annot = (MyAnnotation) t.getAnnotation();
0309: if (annot != null) {
0310: UID uid = annot.getCapacityUID();
0311: if (uid != null) {
0312: for (int j = 0; i < i; j++) {
0313: if (uid.equals(capacities[j].getCapacity()
0314: .getUID())) {
0315: capacities[j].setSupportRequest(t);
0316: capacities[j]
0317: .setSupportRequestAllocation(a);
0318: capacities[j].setQSE(annot.getQSE());
0319: }
0320: }
0321: }
0322: }
0323: }
0324: }
0325: }
0326:
0327: public void execute() {
0328: //System.out.println(getMessageAddress() + " In LoadAllocatorPlugin.execute");
0329:
0330: for (Enumeration e = this OrgSubs.getAddedList(); e
0331: .hasMoreElements();) {
0332: // only expecting one
0333: this Org = (Organization) e.nextElement();
0334: // Are we an MSB?
0335: isTransporter = isMSB();
0336: // System.out.println(getMessageAddress()
0337: // + " LoadAllocator got self "
0338: // + thisOrg
0339: // + " isTransporter " + isTransporter);
0340: break;
0341: }
0342:
0343: // oplan is reset every time execute() runs
0344: oplanStartTime = TimeSpan.MAX_VALUE;
0345: for (Enumeration e = oplanSubs.elements(); e.hasMoreElements();) {
0346: Oplan oplan = (Oplan) e.nextElement();
0347: oplanStartTime = Math.min(oplanStartTime, oplan.getCday()
0348: .getTime());
0349: }
0350: // We can't do anything without the oplan
0351: if (oplanStartTime == TimeSpan.MAX_VALUE)
0352: return;
0353:
0354: // change this: hard code end date for now
0355: oplanEndTime = oplanStartTime
0356: + (long) (181 * ScheduleUtilities.millisperday);
0357:
0358: // If we get to this point, we have the Oplan times and can create
0359: // capacity objects. (No Oplan, no start or end dates)
0360:
0361: // Create Transport Capacities at MSB
0362: if (isTransporter) {
0363: if (fuelTransportCapacity == null) {
0364: Capacity cap = createCapacity(BulkPOL.class,
0365: Constants.Verb.TRANSPORT);
0366: if (cap != null) {
0367: fuelTransportCapacity = new LACapacity(cap);
0368: publishAdd(cap);
0369: }
0370: }
0371: if (ammoTransportCapacity == null) {
0372: Capacity cap = createCapacity(Ammunition.class,
0373: Constants.Verb.TRANSPORT);
0374: if (cap != null) {
0375: ammoTransportCapacity = new LACapacity(cap);
0376: publishAdd(cap);
0377: }
0378: }
0379: }
0380: // Create Handling Capacities at FSB
0381: else {
0382: if (fuelHandlingCapacity == null) {
0383: Capacity cap = createCapacity(BulkPOL.class,
0384: Constants.Verb.LOAD);
0385: if (cap != null) {
0386: fuelHandlingCapacity = new LACapacity(cap);
0387: publishAdd(cap);
0388: }
0389: }
0390: if (ammoHandlingCapacity == null) {
0391: Capacity cap = createCapacity(Ammunition.class,
0392: Constants.Verb.LOAD);
0393: if (cap != null) {
0394: ammoHandlingCapacity = new LACapacity(cap);
0395: publishAdd(cap);
0396: }
0397: }
0398: }
0399:
0400: // Load tasks
0401: for (Enumeration e = loadTasks.getAddedList(); e
0402: .hasMoreElements();) {
0403: Task task = (Task) e.nextElement();
0404:
0405: if (isTransporter) {
0406: System.out
0407: .println(getMessageAddress()
0408: + " LoadAllocator: Why do we have LOAD Tasks here? Isn't this the MSB?");
0409: break;
0410: }
0411:
0412: Asset asset = null;
0413: if (task.getDirectObject() instanceof BulkPOL) {
0414: asset = fuelHandlingCapacity.getCapacity();
0415: fuelHandlingCapacity.changed(true);
0416: // System.out.println(getMessageAddress() + " LoadAllocator got Load fuel task");
0417: } else if (task.getDirectObject() instanceof Ammunition) {
0418: asset = ammoHandlingCapacity.getCapacity();
0419: ammoHandlingCapacity.changed(true);
0420: // System.out.println(getMessageAddress() + " LoadAllocator got Load ammo task");
0421: } else {
0422: System.err
0423: .println(getMessageAddress()
0424: + " LoadAllocator got task of unexpected type :"
0425: + task);
0426: continue;
0427: }
0428:
0429: // System.out.println(getMessageAddress() + "Creating AllocationResult for Load task");
0430: AllocationResult allocation_result = computeAllocationResult(task);
0431:
0432: Allocation allocation = theLDMF.createAllocation(task
0433: .getPlan(), task, asset, allocation_result,
0434: Constants.Role.HANDLER);
0435: // System.out.println(getMessageAddress() + " Allocating Handle Task " /*+ task*/ + " to " + asset);
0436: publishAdd(allocation);
0437: thePlan = task.getPlan();
0438: }
0439:
0440: // Transport tasks
0441: for (Enumeration e = transportTasks.getAddedList(); e
0442: .hasMoreElements();) {
0443: Task task = (Task) e.nextElement();
0444:
0445: Role role = null;
0446: Asset asset = null;
0447: if (isTransporter) {
0448: // We are the MSB, allocate to capacity
0449: Object dobj = task.getDirectObject();
0450: if (dobj instanceof BulkPOL) {
0451: asset = fuelTransportCapacity.getCapacity();
0452: fuelTransportCapacity.changed(true);
0453: role = Constants.Role.FUELTRANSPORTPROVIDER;
0454: // System.out.println(getMessageAddress() + " LoadAllocator got Transport fuel task");
0455: } else if (dobj instanceof Ammunition) {
0456: asset = ammoTransportCapacity.getCapacity();
0457: ammoTransportCapacity.changed(true);
0458: // System.out.println(getMessageAddress() + " LoadAllocator got Transport ammo task");
0459: } else if (dobj instanceof AggregateAsset) {
0460: Object o = ((AggregateAsset) task.getDirectObject())
0461: .getAsset();
0462: if (o instanceof Ammunition) {
0463: asset = ammoTransportCapacity.getCapacity();
0464: ammoTransportCapacity.changed(true);
0465: } else if (o instanceof BulkPOL) {
0466: asset = fuelTransportCapacity.getCapacity();
0467: fuelTransportCapacity.changed(true);
0468: } else {
0469: // we don't deal with whatever ends up here
0470: continue;
0471: //System.err.println(getMessageAddress() + " LoadAllocator asset of unknown type: " + dobj);
0472: }
0473: }
0474: }
0475: // forward from FSB to MSB
0476: else
0477: // Bad! This assumes that either one will do.
0478: asset = getRoleProvider(
0479: Constants.Role.FUELTRANSPORTPROVIDER, false);
0480: if (asset == null)
0481: // try again
0482: asset = getRoleProvider(
0483: Constants.Role.AMMUNITIONTRANSPORTPROVIDER,
0484: false);
0485:
0486: if (asset == null) {
0487: System.err
0488: .println(getMessageAddress()
0489: + " LoadAllocator - no MSB, can't forward the Transport task");
0490: } else {
0491: // create and publish the allocation
0492: // System.out.println(getMessageAddress() + "Creating AllocationResult for Transport task");
0493: AllocationResult allocation_result = computeAllocationResult(task);
0494:
0495: Allocation allocation = theLDMF.createAllocation(task
0496: .getPlan(), task, asset, allocation_result,
0497: Constants.Role.TRANSPORTER);
0498: // System.out.println(getMessageAddress() + "Allocating Transport Task " /*+ task*/ + " to " + asset);
0499: publishAdd(allocation);
0500: thePlan = task.getPlan();
0501: }
0502: }
0503:
0504: // calculate capacity overruns
0505: // if overruns on a given day, ask for more capacity
0506: // assume we get new capacity, and add a QuantityScheduleElement to
0507: // Capacity.ScheduleContentPG.Schedule with added capacity
0508:
0509: if ((fuelHandlingCapacity != null)
0510: && fuelHandlingCapacity.changed()) {
0511: checkOverruns(fuelHandlingCapacity);
0512: fuelHandlingCapacity.changed(false);
0513: }
0514: if ((ammoHandlingCapacity != null)
0515: && ammoHandlingCapacity.changed()) {
0516: checkOverruns(ammoHandlingCapacity);
0517: ammoHandlingCapacity.changed(false);
0518: }
0519: if ((fuelTransportCapacity != null)
0520: && fuelTransportCapacity.changed()) {
0521: checkOverruns(fuelTransportCapacity);
0522: fuelTransportCapacity.changed(false);
0523: }
0524: if ((ammoTransportCapacity != null)
0525: && ammoTransportCapacity.changed()) {
0526: checkOverruns(ammoTransportCapacity);
0527: ammoTransportCapacity.changed(false);
0528: }
0529: }
0530:
0531: // Return an allocation result that gives back a successful/optimistic answer
0532: // consisting of the best value for every aspect
0533: private AllocationResult computeAllocationResult(Task task) {
0534: int num_prefs = 0;
0535: Enumeration prefs = task.getPreferences();
0536: while (prefs.hasMoreElements()) {
0537: prefs.nextElement();
0538: num_prefs++;
0539: }
0540:
0541: int[] types = new int[num_prefs];
0542: double[] results = new double[num_prefs];
0543: prefs = task.getPreferences();
0544:
0545: int index = 0;
0546: while (prefs.hasMoreElements()) {
0547: Preference pref = (Preference) prefs.nextElement();
0548: types[index] = pref.getAspectType();
0549: results[index] = pref.getScoringFunction().getBest()
0550: .getValue();
0551: // System.out.println("Types[" + index + "]= " + types[index] +
0552: // " Results[" + index + "]= " + results[index]);
0553: index++;
0554: }
0555:
0556: AllocationResult result = theLDMF.newAllocationResult(1.0, // Rating,
0557: true, // Success,
0558: types, results);
0559: return result;
0560: }
0561:
0562: private Capacity createCapacity(Class proto_class, String verb) {
0563:
0564: Asset asset = theLDMF.createPrototype(proto_class,
0565: "AssetPrototype");
0566:
0567: NewTypeIdentificationPG typeIdProp = null;
0568: int unit = Volume.GALLONS;
0569: try {
0570: typeIdProp = (NewTypeIdentificationPG) theLDMF
0571: .createPropertyGroup(TypeIdentificationPGImpl.class);
0572: if (verb.equals(Constants.Verb.LOAD)) {
0573: if (asset instanceof BulkPOL) {
0574: typeIdProp
0575: .setTypeIdentification(CapacityType.FUELHANDLING);
0576: typeIdProp
0577: .setNomenclature(CapacityType.FUELHANDLING);
0578: unit = Volume.GALLONS;
0579: } else if (asset instanceof Ammunition) {
0580: typeIdProp
0581: .setTypeIdentification(CapacityType.AMMUNITIONHANDLING);
0582: typeIdProp
0583: .setNomenclature(CapacityType.AMMUNITIONHANDLING);
0584: unit = Mass.TONS;
0585: } else {
0586: System.err
0587: .println(getMessageAddress()
0588: + " LoadAllocator:createCapacity() got unexpected asset type :"
0589: + asset);
0590: return null;
0591: }
0592: } else if (verb.equals(Constants.Verb.TRANSPORT)) {
0593: if (asset instanceof BulkPOL) {
0594: typeIdProp
0595: .setTypeIdentification(CapacityType.FUELTRANSPORTATION);
0596: typeIdProp
0597: .setNomenclature(CapacityType.FUELTRANSPORTATION);
0598: unit = Volume.GALLONS;
0599: } else if (asset instanceof Ammunition) {
0600: typeIdProp
0601: .setTypeIdentification(CapacityType.AMMUNITIONTRANSPORTATION);
0602: typeIdProp
0603: .setNomenclature(CapacityType.AMMUNITIONTRANSPORTATION);
0604: unit = Mass.TONS;
0605: } else {
0606: System.err
0607: .println(getMessageAddress()
0608: + " LoadAllocator:createCapacity() got unexpected asset type :"
0609: + asset);
0610: return null;
0611: }
0612: } else {
0613: System.err
0614: .println(getMessageAddress()
0615: + " LoadAllocator:createCapacity() got unexpected verb :"
0616: + verb);
0617: return null;
0618: }
0619: } catch (Exception exc) {
0620: System.out
0621: .println(getMessageAddress()
0622: + " LoadAllocator - problem creating a Capacity asset.");
0623: exc.printStackTrace();
0624: }
0625:
0626: asset.setTypeIdentificationPG(typeIdProp);
0627: //
0628: // Create a ScheduledContentPG
0629: //
0630: Vector cses = new Vector();
0631: // later - fix CapacityScheduleElement and use it instead
0632: NewQuantityScheduleElement cse = new QuantityScheduleElementImpl();
0633: // from org CSSCapability
0634: // e.g., FuelHandling Volume=105000gallons Duration=1days
0635: CSSCapabilityPG cssPG = this Org.getCSSCapabilityPG();
0636: CSSCapability css = null;
0637: double qty = 105000d;
0638: if (cssPG != null) {
0639: css = getCSSCapabilityType(cssPG, typeIdProp
0640: .getTypeIdentification());
0641: }
0642: if (css == null) {
0643: System.out.println(getMessageAddress()
0644: + "LoadAllocatorPlugin - No capacity for "
0645: + typeIdProp.getTypeIdentification()
0646: + " in CSSCapabilityType - using default value");
0647:
0648: } else
0649: qty = css.getCapacity().getQuantity().getValue(unit);
0650: //System.out.println(getMessageAddress() + " LoadAllocator using " + qty +
0651: // "as capacity for " + typeIdProp.getTypeIdentification());
0652: cse.setQuantity(qty);
0653:
0654: /*cse.setQuantity(1050d);*/
0655: cse.setStartTime(oplanStartTime);
0656: cse.setEndTime(oplanEndTime);
0657: cses.addElement(cse);
0658: NewSchedule sched = GLMFactory.newQuantitySchedule(cses
0659: .elements(), PlanScheduleType.ACTUAL_CAPACITY);
0660: // Create a NewScheduledContentPG for the container.
0661: //
0662: NewScheduledContentPG nscp = (NewScheduledContentPG) new ScheduledContentPGImpl();
0663: nscp.setAsset(asset);
0664: nscp.setSchedule(sched);
0665:
0666: Capacity c;
0667: try {
0668: c = (org.cougaar.glm.ldm.asset.Capacity) theLDMF
0669: .createAsset(Capacity.class);
0670: } catch (Exception exc) {
0671: System.out
0672: .println(getMessageAddress()
0673: + " LoadAllocator - problem creating a Capacity asset.");
0674: exc.printStackTrace();
0675: c = new Capacity();
0676: }
0677:
0678: c.setScheduledContentPG(nscp);
0679:
0680: c.setTypeIdentificationPG(typeIdProp);
0681:
0682: //
0683: // Set the availability on this asset.
0684: //
0685: Schedule ss = theLDMF.newSimpleSchedule(
0686: new Date(oplanStartTime), new Date(oplanEndTime));
0687: ((NewRoleSchedule) c.getRoleSchedule())
0688: .setAvailableSchedule(ss);
0689:
0690: // System.out.println(getMessageAddress() + " LoadAllocator created Capacity Object "
0691: // + c.getUID());
0692: return c;
0693: }
0694:
0695: // Check each day to see if we have allocated more capacity than is available.
0696: // If so, modify the SupportRequest task to ask for more capacity earlier.
0697: // There is only one SupportRequest task per capacity.
0698: // The results of the SupportRequest task are not checked. This Plugin just assumes
0699: // that it gets excactly the additional capacity it asks for.
0700: private void checkOverruns(LACapacity mycapacity) {
0701:
0702: // System.out.println(getMessageAddress() + " LoadAllocator in checkOverruns");
0703: Capacity capacity = mycapacity.getCapacity();
0704: if (capacity == null) {
0705: // This should never happen
0706: System.err
0707: .println(getMessageAddress()
0708: + " LoadAllocator:checkOverruns() no capacity object!");
0709: return;
0710: }
0711: RoleSchedule rs = capacity.getRoleSchedule();
0712: // System.out.println(getMessageAddress() + " LoadAllocator:checkOverruns() Capacity.RoleSchedule:" + rs);
0713: if (rs == null) {
0714: // This should never happen
0715: System.err
0716: .println(getMessageAddress()
0717: + " LoadAllocator:checkOverruns() the capacity has no role schedule");
0718: return;
0719: }
0720: long currentDate = oplanStartTime;
0721: boolean publishChanges = false;
0722: boolean publishNew = false;
0723: Schedule capacitySchedule = capacity.getScheduledContentPG()
0724: .getSchedule();
0725: if (capacitySchedule == null) {
0726: // This should never happen
0727: System.err
0728: .println(getMessageAddress()
0729: + " LoadAllocator:checkOverruns() the capacity's ScheduleContentPG has no schedule");
0730: return;
0731: }
0732:
0733: // Check for overruns on each day
0734: while (currentDate < oplanEndTime) {
0735: double qtyAsked = 0;
0736: double overrun = 0;
0737: double qtyAvailable = 0;
0738: // Find the elements that have allocations for current day
0739: // Assume that oplan started at midnight.
0740: Collection allocatedSet = rs.getOverlappingRoleSchedule(
0741: currentDate, currentDate
0742: + ScheduleUtilities.millisperday);
0743: if (allocatedSet.size() > 0) {
0744: //Find out how much we have allocated
0745: qtyAsked = rs.addAspectValues(allocatedSet,
0746: AspectType.QUANTITY);
0747: Collection capacitySet = capacitySchedule
0748: .getOverlappingScheduleElements(
0749: currentDate,
0750: currentDate
0751: + ScheduleUtilities.millisperday);
0752: // Find out how much capacity we actually have
0753: qtyAvailable = ScheduleUtilities
0754: .sumElements(capacitySet);
0755: // Have we allocated more than we have?
0756: overrun = qtyAsked - qtyAvailable;
0757:
0758: // System.out.println(getMessageAddress()
0759: // + " LoadAllocator:checkOverruns() overrun=" + overrun
0760: // + " qtyAsked=" + qtyAsked
0761: // + " qtyAvaiable=" + qtyAvailable);
0762: } else {
0763: // System.out.println(getMessageAddress()
0764: // + " LoadAllocator:checkOverruns() No schedule for "
0765: // + currentDate);
0766: }
0767:
0768: // more capacity allocated than available?
0769: if (overrun > 0) {
0770:
0771: // create a new SupportRequest task there isn't one already
0772: if (mycapacity.getSupportRequest() == null) {
0773: publishNew = true;
0774:
0775: Task supportRequest = createSupportRequest(
0776: capacity, overrun, currentDate,
0777: oplanEndTime);
0778: mycapacity.setSupportRequest(supportRequest);
0779:
0780: // add new qty schedule element to capcity
0781: // this is the object that represents the optimistic assumption that the
0782: // SupportRequest task is successful
0783: NewQuantityScheduleElement cse = new QuantityScheduleElementImpl();
0784: cse.setQuantity(overrun);
0785: cse.setStartTime(currentDate);
0786: // current date?
0787: cse.setEndTime(oplanEndTime);
0788: ((NewSchedule) capacitySchedule)
0789: .addScheduleElement(cse);
0790: mycapacity.setQSE((QuantityScheduleElement) cse);
0791:
0792: // Add the QSE to the annotation on the task
0793: ((MyAnnotation) supportRequest.getAnnotation())
0794: .setQSE((QuantityScheduleElement) cse);
0795:
0796: } else {
0797: // reset the start date and quantity preferences of the SupportRequest task
0798: publishChanges = true;
0799:
0800: QuantityScheduleElement qse = mycapacity.getQSE();
0801: if (qse == null) {
0802: // Don't know why this would happen, but...
0803: System.err.println(getMessageAddress()
0804: + " LoadAllocator QSE missing");
0805: NewQuantityScheduleElement cse = new QuantityScheduleElementImpl();
0806: cse.setQuantity(0d);
0807: cse.setStartTime(currentDate);
0808: cse.setEndTime(oplanEndTime);
0809: ((NewSchedule) capacitySchedule)
0810: .addScheduleElement(cse);
0811: mycapacity
0812: .setQSE((QuantityScheduleElement) cse);
0813:
0814: // Add the QSE to the annotation on the task
0815: ((MyAnnotation) mycapacity.getSupportRequest()
0816: .getAnnotation())
0817: .setQSE((QuantityScheduleElement) cse);
0818: }
0819:
0820: // this is null
0821: double new_qty = qse.getQuantity() + overrun;
0822:
0823: long newDate = qse.getStartDate().getTime();
0824: if (newDate > currentDate) {
0825: ((NewQuantityScheduleElement) qse)
0826: .setStartTime(currentDate);
0827: newDate = currentDate;
0828: }
0829: modifySupportRequest(
0830: mycapacity.getSupportRequest(), capacity,
0831: new_qty, newDate);
0832:
0833: // new quantity should always be more than old
0834: ((NewQuantityScheduleElement) qse)
0835: .setQuantity(new_qty);
0836:
0837: }
0838:
0839: }
0840: currentDate += ScheduleUtilities.millisperday;
0841: }
0842: if (publishNew || publishChanges) {
0843: // send SupportRequest task to SupportForceProvider
0844: publishSupportRequestAllocation(mycapacity);
0845: }
0846: if (publishNew) {
0847: // System.out.println(getMessageAddress() + " LoadAllocator publishing changed capacity and new SupportRequest");
0848: publishChange(capacity);
0849: publishAdd(mycapacity.getSupportRequest());
0850: publishNew = false;
0851: } else if (publishChanges) {
0852: // System.out.println(getMessageAddress() + " LoadAllocator publishing changed capacity and SupportRequest");
0853: publishChange(capacity);
0854: publishChange(mycapacity.getSupportRequest());
0855: publishChanges = false;
0856: }
0857: }
0858:
0859: private Task createSupportRequest(Capacity capacity, double qty,
0860: long startDate, long endDate) {
0861: //System.out.println(getMessageAddress() + " LoadAllocator in createSupportRequest");
0862:
0863: NewTask t = theLDMF.newTask();
0864: t.setPlan(/*thePlan*/theLDMF.getRealityPlan());
0865: t.setVerb(Verb.get(Constants.Verb.SUPPORTREQUEST));
0866: Vector pps = new Vector();
0867: NewPrepositionalPhrase pp = theLDMF.newPrepositionalPhrase();
0868: pp.setPreposition(Constants.Preposition.FOR);
0869: pp.setIndirectObject(this Org.getItemIdentificationPG()
0870: .getItemIdentification());
0871: pps.add(pp);
0872: pp = theLDMF.newPrepositionalPhrase();
0873: t.setPrepositionalPhrases(pps.elements());
0874:
0875: Vector prefs = new Vector();
0876: prefs.add(createDatePreference(AspectType.START_TIME,
0877: startDate, 1));
0878: prefs
0879: .add(createDatePreference(AspectType.END_TIME, endDate,
0880: 1));
0881:
0882: prefs.add(createTypedPreference(capacity, qty));
0883: t.setPreferences(prefs.elements());
0884:
0885: // mark the Task with the UID of the capacity so we can match them up
0886: // later in case we rehydrate
0887: t.setAnnotation(new MyAnnotation(capacity.getUID()));
0888: return t;
0889: }
0890:
0891: private void modifySupportRequest(Task supportRequest,
0892: Capacity capacity, double qty, long newDate) {
0893:
0894: int num_prefs = 0;
0895: Enumeration prefs = supportRequest.getPreferences();
0896: Vector newPrefs = new Vector();
0897:
0898: while (prefs.hasMoreElements()) {
0899: Preference pref = (Preference) prefs.nextElement();
0900: switch (pref.getAspectType()) {
0901: case AspectType.START_TIME:
0902: newPrefs.add(createDatePreference(
0903: AspectType.START_TIME, newDate, 1));
0904: break;
0905: case AspectType.TYPED_QUANTITY:
0906: newPrefs.add(createTypedPreference(capacity, qty));
0907: break;
0908: default:
0909: newPrefs.add(pref);
0910: }
0911: }
0912: }
0913:
0914: private Preference createDatePreference(int timeAspectType,
0915: long date, int scoringFunction) {
0916: AspectValue timeAV = TimeAspectValue.create(timeAspectType,
0917: date);
0918: ScoringFunction timeSF = ScoringFunction
0919: .createPreferredAtValue(timeAV, scoringFunction);
0920: return theLDMF.newPreference(timeAspectType, timeSF);
0921: }
0922:
0923: /**
0924: * Given CSSCapabilityPG, returns the CSSCapability that matches the given type
0925: */
0926: private static CSSCapability getCSSCapabilityType(
0927: CSSCapabilityPG cssCapPG, String type) {
0928: Iterator theCaps = cssCapPG.getCapabilities().iterator();
0929: CSSCapability theCap = null;
0930: while (theCaps.hasNext()) {
0931: theCap = (CSSCapability) theCaps.next();
0932: if (theCap.getType().equals(type))
0933: return theCap;
0934: }
0935: return null;
0936:
0937: }
0938:
0939: private Preference createTypedPreference(Capacity capacity,
0940: double qty) {
0941: NewCSSCapabilityPG cssCap = (NewCSSCapabilityPG) theLDMF
0942: .createPropertyGroup(CSSCapabilityPGImpl.class);
0943: NewAssignedPG assignedPG = (NewAssignedPG) theLDMF
0944: .createPropertyGroup(AssignedPGImpl.class);
0945:
0946: org.cougaar.planning.ldm.measure.Capacity measureCapacity;
0947: CSSCapability theCapability;
0948: Organization proto = (Organization) theLDMF.createPrototype(
0949: Organization.class, "OrgPrototype");
0950: Role role;
0951:
0952: if (capacity.getScheduledContentPG().getAsset() instanceof BulkPOL) {
0953: Volume myScalar = new Volume(qty, Volume.GALLONS);
0954: measureCapacity = new org.cougaar.planning.ldm.measure.Capacity(
0955: myScalar, new Duration(1, Duration.DAYS));
0956: if (capacity.getTypeIdentificationPG()
0957: .getTypeIdentification().equals(
0958: CapacityType.FUELTRANSPORTATION)) {
0959: role = Constants.Role.FUELTRANSPORTPROVIDER;
0960: theCapability = new CSSCapability(
0961: CapacityType.FUELTRANSPORTATION,
0962: measureCapacity);
0963: } else {
0964: role = Constants.Role.FUELHANDLINGPROVIDER;
0965: theCapability = new CSSCapability(
0966: CapacityType.FUELHANDLING, measureCapacity);
0967: }
0968: } else {
0969: Mass myScalar = new Mass(qty, Mass.TONS);
0970: measureCapacity = new org.cougaar.planning.ldm.measure.Capacity(
0971: myScalar, new Duration(1, Duration.DAYS));
0972: if (capacity.getTypeIdentificationPG()
0973: .getTypeIdentification().equals(
0974: CapacityType.AMMUNITIONTRANSPORTATION)) {
0975: role = Constants.Role.AMMUNITIONTRANSPORTPROVIDER;
0976: theCapability = new CSSCapability(
0977: CapacityType.AMMUNITIONTRANSPORTATION,
0978: measureCapacity);
0979: } else {
0980: role = Constants.Role.AMMUNITIONHANDLINGPROVIDER;
0981: theCapability = new CSSCapability(
0982: CapacityType.AMMUNITIONHANDLING,
0983: measureCapacity);
0984: }
0985:
0986: }
0987:
0988: ArrayList al = new ArrayList(1);
0989: al.add(theCapability);
0990: cssCap.setCapabilities(al);
0991: proto.setPropertyGroup(cssCap);
0992:
0993: al.clear();
0994: al.add(role);
0995: assignedPG.setRoles(al);
0996: proto.setAssignedPG(assignedPG);
0997:
0998: TypedQuantityAspectValue tav = new TypedQuantityAspectValue(
0999: proto, qty);
1000: ScoringFunction sf = ScoringFunction.createPreferredAtValue(
1001: tav, 0.5);
1002: return theLDMF.newPreference(AspectType.TYPED_QUANTITY, sf);
1003: }
1004:
1005: /** Publish new or changed Allocation of SupportRequest task*/
1006: private void publishSupportRequestAllocation(LACapacity mycapacity) {
1007: Organization supportForceProvider = getRoleProvider(
1008: Constants.Role.SUPPORTFORCEPROVIDER, false);
1009: // Can't forward the task if there is no place to send it.
1010: if (supportForceProvider == null) {
1011: System.err
1012: .println(getMessageAddress()
1013: + " LoadAllocator:publishSupportRequestAllocation - No SupportForceProvider!");
1014: return;
1015: }
1016:
1017: AllocationResult allocation_result = computeAllocationResult(mycapacity
1018: .getSupportRequest());
1019: Allocation allocation = mycapacity
1020: .getSupportRequestAllocation();
1021: if (allocation == null) {
1022: allocation = theLDMF.createAllocation(theLDMF
1023: .getRealityPlan(), mycapacity.getSupportRequest(),
1024: supportForceProvider, allocation_result,
1025: Constants.Role.TRANSPORTER);
1026: mycapacity.setSupportRequestAllocation(allocation);
1027: publishAdd(allocation);
1028: // System.out.println(getMessageAddress() + " LoadAllocator Publishing new SupportRequest allocation " + allocation);
1029: } else {
1030: allocation.setEstimatedResult(allocation_result);
1031: publishChange(allocation);
1032: // System.out.println(getMessageAddress() + " LoadAllocator publishChange SupportRequest allocation " + allocation);
1033: }
1034: }
1035:
1036: // Inner class that contains a Capacity asset, a SupportRequest task to increase capacity,
1037: // a SupportRequest allocation, and a dirty flag.
1038: private static class LACapacity {
1039: private boolean changed = false;
1040: private Capacity capacity = null;
1041: private Task supportRequest = null;
1042: private QuantityScheduleElement qse = null;
1043: private Allocation supportRequestAllocation = null;
1044:
1045: public LACapacity(Capacity capacity) {
1046: this .capacity = capacity;
1047: }
1048:
1049: public Capacity getCapacity() {
1050: return capacity;
1051: }
1052:
1053: public void changed(boolean value) {
1054: changed = value;
1055: }
1056:
1057: public boolean changed() {
1058: return changed;
1059: }
1060:
1061: public void setSupportRequest(Task sr) {
1062: supportRequest = sr;
1063: }
1064:
1065: public Task getSupportRequest() {
1066: return supportRequest;
1067: }
1068:
1069: public QuantityScheduleElement getQSE() {
1070: return qse;
1071: }
1072:
1073: public void setQSE(QuantityScheduleElement element) {
1074: qse = element;
1075: }
1076:
1077: public void setSupportRequestAllocation(Allocation a) {
1078: supportRequestAllocation = a;
1079: }
1080:
1081: public Allocation getSupportRequestAllocation() {
1082: return supportRequestAllocation;
1083: }
1084: }
1085:
1086: private static class MyAnnotation implements Annotation {
1087: private UID capacityUID;
1088: private QuantityScheduleElement qse;
1089:
1090: MyAnnotation(UID capacityuid, QuantityScheduleElement qse) {
1091: capacityUID = capacityuid;
1092: this .qse = qse;
1093: }
1094:
1095: MyAnnotation(UID capacityuid) {
1096: capacityUID = capacityuid;
1097: }
1098:
1099: public UID getCapacityUID() {
1100: return capacityUID;
1101: }
1102:
1103: public void setQSE(QuantityScheduleElement qse) {
1104: this .qse = qse;
1105: }
1106:
1107: public QuantityScheduleElement getQSE() {
1108: return qse;
1109: }
1110: }
1111: }
|