001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.logistics.plugin.trans;
027:
028: import java.math.BigDecimal;
029:
030: import java.util.Collection;
031: import java.util.Collections;
032: import java.util.Enumeration;
033: import java.util.HashSet;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Set;
037: import java.util.Vector;
038:
039: import org.cougaar.planning.ldm.LDMServesPlugin;
040:
041: import org.cougaar.logistics.ldm.Constants;
042:
043: import org.cougaar.glm.ldm.asset.ContainPG;
044: import org.cougaar.glm.ldm.asset.ForUnitPG;
045: import org.cougaar.glm.ldm.asset.GLMAsset;
046: import org.cougaar.glm.ldm.asset.MovabilityPG;
047: import org.cougaar.glm.ldm.asset.NewForUnitPG;
048: import org.cougaar.glm.ldm.asset.NewMovabilityPG;
049: import org.cougaar.glm.ldm.asset.NewPhysicalPG;
050: import org.cougaar.glm.ldm.asset.PhysicalPG;
051: import org.cougaar.glm.ldm.asset.PropertyGroupFactory;
052:
053: import org.cougaar.glm.ldm.plan.GeolocLocation;
054:
055: import org.cougaar.logistics.plugin.trans.GLMTransConst;
056:
057: import org.cougaar.glm.util.GLMPrepPhrase;
058:
059: import org.cougaar.lib.callback.UTILAssetCallback;
060: import org.cougaar.lib.callback.UTILAssetListener;
061:
062: import org.cougaar.lib.filter.UTILExpanderPluginAdapter;
063:
064: import org.cougaar.planning.ldm.asset.AggregateAsset;
065: import org.cougaar.planning.ldm.asset.Asset;
066: import org.cougaar.planning.ldm.asset.AssetGroup;
067: import org.cougaar.planning.ldm.asset.ItemIdentificationPG;
068: import org.cougaar.planning.ldm.asset.NewItemIdentificationPG;
069: import org.cougaar.planning.ldm.asset.PropertyGroup;
070:
071: import org.cougaar.planning.ldm.measure.*;
072:
073: import org.cougaar.planning.ldm.plan.Task;
074: import org.cougaar.planning.ldm.plan.MPTask;
075: import org.cougaar.planning.ldm.plan.NewTask;
076:
077: /**
078: * Breaks up incoming tasks into aggregates that are no bigger than the largest carrier asset.
079: * Carrier could be truck, ship, or plane.
080: */
081: public class TransportExpanderPlugin extends UTILExpanderPluginAdapter
082: implements UTILAssetListener {
083:
084: protected static final double CAP_FUDGE = 0.1;
085:
086: public void localSetup() {
087: super .localSetup();
088: glmPrepHelper = new GLMPrepPhrase(logger);
089: ldmProtoCache = getLDMService().getLDM();
090: }
091:
092: /**
093: * <pre>
094: * The idea is to add subscriptions (via the filterCallback), and when
095: * they change, to have the callback react to the change, and tell
096: * the listener (many times the plugin) what to do.
097: *
098: * Override and call super to add new filters, or override
099: * createXXXCallback to change callback behaviour.
100: * </pre>
101: */
102: public void setupFilters() {
103: super .setupFilters();
104:
105: addFilter(myAssetCallback = new UTILAssetCallback(this , logger));
106: }
107:
108: /**
109: * State that we are interested in all transport tasks
110: * @param task the task to test.
111: * @return true if the tasks verb is TRANSPORT, false otherwise
112: */
113: public boolean interestingTask(Task task) {
114: boolean hasStratTrans = false;
115:
116: if (prepHelper.hasPrepNamed(task, "OFTYPE")) {
117: Asset oftype = (Asset) prepHelper.getIndirectObject(task,
118: "OFTYPE");
119: String typeid = oftype.getTypeIdentificationPG()
120: .getTypeIdentification();
121: hasStratTrans = typeid.equals("StrategicTransportation");
122: }
123:
124: boolean hasTransport = task.getVerb().equals(
125: Constants.Verb.TRANSPORT);
126: if (!hasTransport)
127: return false;
128:
129: if (!prepHelper.hasPrepNamed(task, Constants.Preposition.FROM)) {
130: if (isDebugEnabled())
131: debug(".interestingTask - ignoring TRANSPORT task "
132: + task.getUID()
133: + " that doesn't have a FROM prep.");
134: return false;
135: }
136: if (!prepHelper.hasPrepNamed(task, Constants.Preposition.TO)) {
137: if (isDebugEnabled())
138: debug(".interestingTask - ignoring TRANSPORT task "
139: + task.getUID()
140: + " that doesn't have a TO prep.");
141: return false;
142: }
143:
144: boolean val = (!(task instanceof MPTask))
145: && !prepHelper.hasPrepNamed(task, "VISHNU");
146:
147: if (isDebugEnabled() && val
148: && (task.getDirectObject() instanceof AssetGroup))
149: debug(".interested in task with asset group? "
150: + task.getUID());
151:
152: if (isDebugEnabled() && !val) {
153: debug(".interestingTask - IGNORING " + task.getUID());
154: } else if (isDebugEnabled()) {
155: debug(".interestingTask - interested in " + task.getUID());
156: }
157:
158: if ((task.getDirectObject() instanceof AggregateAsset)
159: && (((AggregateAsset) task.getDirectObject())
160: .getQuantity() == 0)) {
161: info(".interestingTask - NOTE - ignoring task "
162: + task.getUID()
163: + " which has a zero quantity for aggregate asset "
164: + task.getDirectObject());
165: val = false;
166: }
167:
168: return val;
169: }
170:
171: public void processTasks(java.util.List tasks) {
172: super .processTasks(getPrunedTaskList(tasks));
173: }
174:
175: protected List getPrunedTaskList(List tasks) {
176: java.util.List prunedTasks = new java.util.ArrayList(tasks
177: .size());
178:
179: Collection removed = myInputTaskCallback.getSubscription()
180: .getRemovedCollection();
181:
182: for (Iterator iter = tasks.iterator(); iter.hasNext();) {
183: Task task = (Task) iter.next();
184: if (removed.contains(task)) {
185: if (isInfoEnabled()) {
186: info("ignoring task on removed list "
187: + task.getUID());
188: }
189: } else
190: prunedTasks.add(task);
191: }
192: return prunedTasks;
193: }
194:
195: /**
196: * Breaks up task aggregates into truck sized chunks if bigger
197: * than biggest truck. This is defined by a parameter : maxTruckContainWeight
198: *
199: * @param task the task to expand
200: * @return a vector with the exapnded subtask
201: */
202: public Vector getSubtasks(Task task) {
203: Vector subtasks = new Vector();
204: ForUnitPG unitPG = getForUnitPG(task.getDirectObject());
205:
206: if (!didSetCapacity)
207: resetCapacities();
208:
209: try {
210: if (prepHelper.hasPrepNamed(task,
211: GLMTransConst.LOW_FIDELITY)
212: && (!isSelfPropelled(task, task.getDirectObject()) || (getAgentIdentifier()
213: .toString().indexOf("Packer") != -1))) {
214: expandLowFi(task, subtasks);
215: } else if (task.getDirectObject() instanceof AggregateAsset) {
216: expandAggregates(task, subtasks);
217: if (subtasks.isEmpty())
218: error(".getSubtasks -- ERROR - after expanding aggregate asset of task "
219: + task + " got no subtasks.");
220: } else if (task.getDirectObject() instanceof AssetGroup) {
221: if (isDebugEnabled())
222: debug(".getSubtasks - got asset group for task "
223: + task.getUID());
224: Collection assets = assetHelper
225: .expandAssetGroup((AssetGroup) task
226: .getDirectObject());
227: for (Iterator iter = assets.iterator(); iter.hasNext();) {
228: Asset subasset = (Asset) iter.next();
229: // if (subasset instanceof AggregateAsset)
230: // expandAggregates (task, subtasks);
231: // else
232: subtasks.add(makeTask(task, subasset, unitPG));
233: }
234: if (subtasks.isEmpty())
235: error(".getSubtasks -- ERROR - after expanding AssetGroup of task "
236: + task + " got no subtasks.");
237: } else
238: subtasks.add(makeTask(task, task.getDirectObject(),
239: unitPG));
240:
241: } catch (Exception e) {
242: logger.error(e.getMessage(), e);
243: }
244: if (isDebugEnabled()) {
245: String uids = "";
246: for (Iterator iter = subtasks.iterator(); iter.hasNext();)
247: uids = uids + ((Task) iter.next()).getUID() + " ";
248:
249: debug(" created subtasks " + uids);
250: }
251:
252: if (subtasks.isEmpty())
253: error("getSubtasks - tried to create subtasks for "
254: + task.getUID() + " but couldn't.");
255:
256: return subtasks;
257: }
258:
259: protected ForUnitPG getForUnitPG(Asset asset) {
260: return (ForUnitPG) asset.resolvePG(
261: org.cougaar.glm.ldm.asset.ForUnitPG.class,
262: Asset.UNSPECIFIED_TIME);
263: }
264:
265: /**
266: * gets the contribution each individual item makes to consuming
267: * the capacity of the transport vehicle
268: * Sub classes may want to override this
269: * @param itemAsset -- the asset of the direct object of the task
270: * @return double of the contribution in TONS
271: */
272: public double getItemContribution(GLMAsset itemAsset) {
273: double itemWeight = 0.01;
274: try {
275: itemWeight = itemAsset.getPackagePG().getPackMass()
276: .getTons();
277: if (itemWeight < 0.00001) {
278: try {
279: itemWeight = itemAsset.getPhysicalPG().getMass()
280: .getTons();
281: } catch (Exception ee) {
282: if (!itemAsset.hasPersonPG())
283: warn(".getItemContribution - WARNING - unable to determine "
284: + itemAsset.getUID() + "'s weight.");
285: }
286: }
287: } catch (Exception e) {
288: try {
289: itemWeight = itemAsset.getPhysicalPG().getMass()
290: .getTons();
291: } catch (Exception ee) {
292: if (!itemAsset.hasPersonPG())
293: warn(".getItemContribution - WARNING - unable to determine "
294: + itemAsset.getUID() + "'s weight.");
295: }
296: }
297:
298: return itemWeight;
299: }
300:
301: /**
302: * gets the quantity of items in this task
303: * Sub classes may want to override this
304: * @param aggAsset asset that has quantity
305: * @return quantity in int
306: */
307: public int getAssetQuantity(AggregateAsset aggAsset) {
308: return (int) aggAsset.getQuantity();
309: }
310:
311: protected void expandLowFi(Task task, Vector subtasks) {
312: if (task.getDirectObject() instanceof AggregateAsset) {
313: expandAggregates(task, subtasks); // it's a person, or an aggregate of very small items
314: } else {
315: expandLowFiAsset(task, subtasks);
316: }
317: }
318:
319: /**
320: * <pre>
321: * expands aggregate assets into truck-sized chunks, putting the
322: * subtasks into <code>subtasks</code>
323: *
324: * Rounds the item wt to the same precision as vishnu uses so no disaggreements
325: * about how much a truck can hold.
326: * </pre>
327: **/
328: protected void expandAggregates(Task task, Vector subtasks) {
329: AggregateAsset directObject = (AggregateAsset) task
330: .getDirectObject();
331: GLMAsset itemProto = (GLMAsset) directObject.getAsset();
332: ForUnitPG unitPG = getForUnitPG(directObject);
333:
334: boolean isPerson = itemProto.hasPersonPG();
335:
336: double itemContrib = getItemContribution(itemProto);
337:
338: if (isPerson)
339: itemContrib = 1.0;
340: double maxCap = (isPerson) ? maxPassengerCapacity
341: : maxContainCapacity - CAP_FUDGE;
342:
343: // round item weight to same precision as Vishnu
344: BigDecimal bigD = new BigDecimal(itemContrib);
345: itemContrib = bigD.setScale(2, BigDecimal.ROUND_UP)
346: .doubleValue();
347:
348: int remainingQuantity = getAssetQuantity(directObject);
349: double totalAggregateContrib = ((double) remainingQuantity)
350: * itemContrib;
351:
352: boolean mustExpand = (totalAggregateContrib > maxCap);
353:
354: if (isDebugEnabled()) {
355: debug(".expandAggregates - item contribution "
356: + itemContrib + " quantity " + remainingQuantity
357: + " total " + totalAggregateContrib
358: + " maxCapacity " + maxCap
359: + ((mustExpand) ? " must expand " : ""));
360: }
361:
362: int numItemsOnTruck = (int) (maxCap / itemContrib);
363:
364: // sanity checking
365: if (numItemsOnTruck == 0) {
366: warn(".expandAggregates - WARNING - max items on truck "
367: + numItemsOnTruck
368: + " is ZERO. Base asset of aggregate : "
369: + itemProto + " is " + itemContrib
370: + " tons, which is larger than"
371: + " carrier asset's max capacity " + maxCap);
372: numItemsOnTruck = 1;
373: }
374:
375: if (remainingQuantity == 0)
376: error(".expandAggregates - ERROR - aggregate asset quantity is zero for direct object "
377: + directObject + " of task " + task.getUID());
378:
379: double maxOnTruck = ((double) numItemsOnTruck) * itemContrib;
380:
381: if (isDebugEnabled())
382: debug(".expandAggregates - max items on truck "
383: + numItemsOnTruck + " max num " + maxOnTruck);
384:
385: // keep making subtasks
386: while (totalAggregateContrib > maxCap) {
387: Task newtask;
388: Asset truckSizedSet = ldmf.createAggregate(itemProto,
389: numItemsOnTruck);
390: setItemPG(truckSizedSet, itemProto);
391: subtasks
392: .add(newtask = makeTask(task, truckSizedSet, unitPG));
393: totalAggregateContrib -= maxOnTruck;
394: remainingQuantity -= numItemsOnTruck;
395:
396: if (isDebugEnabled())
397: debug(".expandAggregates - cargo > truckload, "
398: + "Expanding with " + numItemsOnTruck
399: + " boxes on truck, task id "
400: + newtask.getUID() + " remaining quantity "
401: + remainingQuantity + ", contribution "
402: + totalAggregateContrib);
403: }
404:
405: // if there's any left over, make one last task
406: if (remainingQuantity > 0) {
407: Asset truckSizedSet = (mustExpand) ? ldmf.createAggregate(
408: itemProto, remainingQuantity) : task
409: .getDirectObject();
410: setItemPG(truckSizedSet, itemProto);
411:
412: if (isDebugEnabled() && mustExpand)
413: debug(".expandAggregates - cargo was > truckload, "
414: + remainingQuantity
415: + " items on truck, truckSizedSet had "
416: + ((AggregateAsset) truckSizedSet)
417: .getQuantity() + " items");
418: subtasks.add(makeTask(task, truckSizedSet, unitPG));
419: }
420: }
421:
422: /**
423: * <pre>
424: * expands aggregate assets into truck-sized chunks, putting the
425: * subtasks into <code>subtasks</code>
426: *
427: * Rounds the item wt to the same precision as vishnu uses so no disaggreements
428: * about how much a truck can hold.
429: * </pre>
430: **/
431: protected void expandLowFiAsset(Task task, Vector subtasks) {
432: if (isDebugEnabled())
433: debug("expanding low fi asset for task " + task.getUID());
434: // test();
435: GLMAsset itemProto = (GLMAsset) task.getDirectObject();
436: if (isDebugEnabled()) {
437: debug(".expandLowFiAsset d.o. "
438: + itemProto.getUID()
439: + " original dimensions :"
440: + " m "
441: + itemProto.getPhysicalPG().getMass().getTons()
442: + " tons, "
443: + " v "
444: + itemProto.getPhysicalPG().getVolume()
445: .getCubicFeet() + " ft^3");
446: }
447:
448: ForUnitPG unitPG = getForUnitPG(itemProto);
449:
450: boolean isPerson = itemProto.hasPersonPG();
451: double totalContrib = getItemContribution(itemProto);
452: boolean originalWasTiny = (totalContrib <= 0.00001);
453:
454: if (originalWasTiny) {
455: warn(".expandLowFiAsset - item contribution "
456: + totalContrib + " for task " + task.getUID()
457: + "'s direct object " + itemProto
458: + " is < 0.00001, was " + totalContrib);
459: }
460:
461: if (isPerson)
462: totalContrib = 1.0;
463: double maxCap = (isPerson) ? maxPassengerCapacity
464: : maxContainCapacity - CAP_FUDGE;
465:
466: // round item weight to same precision as Vishnu
467: BigDecimal bigD = new BigDecimal(totalContrib);
468: totalContrib = bigD.setScale(2, BigDecimal.ROUND_UP)
469: .doubleValue();
470:
471: boolean mustExpand = (totalContrib > maxCap);
472: double itemContrib = (mustExpand) ? maxCap : totalContrib;
473:
474: if (isDebugEnabled()) {
475: debug(".expandLowFiAsset - item contribution "
476: + itemContrib + " maxCapacity " + maxCap
477: + ((mustExpand) ? " must expand " : ""));
478: }
479:
480: int numItemsOnTruck = 1;
481:
482: double maxOnTruck = maxCap;
483:
484: if (isDebugEnabled())
485: debug(".expandLowFiAsset - max items on truck "
486: + numItemsOnTruck + " max num " + maxOnTruck);
487:
488: PhysicalPG originalPhysicalPG = itemProto.getPhysicalPG();
489:
490: // keep making subtasks
491: while (totalContrib > maxCap) {
492: Task newtask;
493:
494: if (isDebugEnabled()) {
495: debug(".expandLowFiAsset d.o. " + itemProto.getUID()
496: + " before adjust dimensions :" + " m "
497: + itemProto.getPhysicalPG().getMass().getTons()
498: + " tons, ");
499: }
500:
501: String itemID = getUniqueID(itemProto);
502:
503: Asset truckSizedAsset = getTruckSizedAsset(itemProto,
504: originalPhysicalPG, itemID, maxOnTruck);
505:
506: if (isDebugEnabled()) {
507: debug(".expandLowFiAsset d.o. " + itemProto.getUID()
508: + " after adjust dimensions :" + " m "
509: + itemProto.getPhysicalPG().getMass().getTons()
510: + " tons, ");
511: }
512:
513: subtasks.add(newtask = makeTask(task, truckSizedAsset,
514: unitPG));
515: totalContrib -= itemContrib;
516:
517: if (isDebugEnabled())
518: debug(".expandLowFiAsset - cargo > truckload, "
519: + "Expanding with " + numItemsOnTruck
520: + " items on truck, task id "
521: + newtask.getUID() + ", contribution "
522: + maxOnTruck);
523: }
524:
525: // if there's any left over, make one last task
526: if (totalContrib > 0.00001 || originalWasTiny) {
527: Asset truckSizedAsset;
528: if (mustExpand) {
529: String itemID = getUniqueID(itemProto);
530:
531: truckSizedAsset = getTruckSizedAsset(itemProto,
532: originalPhysicalPG, itemID, totalContrib);
533: } else
534: truckSizedAsset = task.getDirectObject();
535:
536: if (isDebugEnabled() && mustExpand)
537: debug(".expandLowFiAsset - cargo was > truckload, "
538: + " truckSizedAsset is " + totalContrib
539: + " tons");
540: subtasks.add(makeTask(task, truckSizedAsset, unitPG));
541: }
542: if (isDebugEnabled()) {
543: debug(".expandLowFiAsset d.o. "
544: + itemProto.getUID()
545: + " after dimensions :"
546: + " m "
547: + itemProto.getPhysicalPG().getMass().getTons()
548: + " tons, "
549: + " v "
550: + itemProto.getPhysicalPG().getVolume()
551: .getCubicFeet() + " ft^3");
552: }
553: }
554:
555: protected boolean isSelfPropelled(Task t, Asset directObject) {
556: GLMAsset baseAsset = (directObject instanceof AggregateAsset) ? (GLMAsset) ((AggregateAsset) directObject)
557: .getAsset()
558: : (GLMAsset) directObject;
559:
560: MovabilityPG move_prop = baseAsset.getMovabilityPG();
561:
562: if (move_prop != null) {
563: String cargocatcode = move_prop.getCargoCategoryCode();
564: if (cargocatcode.charAt(0) == 'R') {
565: if (isDebugEnabled())
566: debug(getName()
567: + ".isSelfPropelled - found self-propelled vehicle on task "
568: + t.getUID());
569: return true;
570: }
571: }
572:
573: return false;
574: }
575:
576: protected Asset getTruckSizedAsset(Asset itemProto,
577: PhysicalPG originalPhysicalPG, String itemID, double contrib) {
578: Asset truckSizedAsset = assetHelper.createInstance(
579: ldmProtoCache, GLMTransConst.LOW_FIDELITY_PROTOTYPE,
580: itemID);
581:
582: LowFidelityAssetPG currentLowFiAssetPG = (LowFidelityAssetPG) itemProto
583: .resolvePG(LowFidelityAssetPG.class);
584: truckSizedAsset.addOtherPropertyGroup(currentLowFiAssetPG);// now subobject has pointer back to parent
585:
586: NewMovabilityPG movabilityPG = (NewMovabilityPG) ldmf
587: .createPropertyGroup(MovabilityPG.class);
588: ((GLMAsset) truckSizedAsset).setMovabilityPG(movabilityPG);
589: movabilityPG.setCargoCategoryCode(currentLowFiAssetPG
590: .getCCCDim().getCargoCatCode());
591:
592: adjustDimensions((GLMAsset) truckSizedAsset,
593: originalPhysicalPG, contrib);
594:
595: return truckSizedAsset;
596: }
597:
598: void test() {
599: GLMAsset original = (GLMAsset) ldmf.createInstance(
600: GLMTransConst.LOW_FIDELITY_PROTOTYPE, "low_original");
601:
602: debug(".test original " + original.getUID() + " - " + original
603: + " mass before "
604: + original.getPhysicalPG().getMass().getKilograms());
605:
606: GLMAsset child = (GLMAsset) ldmf.createInstance(original,
607: "child");
608:
609: debug(".test child " + child.getUID() + " - " + child
610: + " mass before "
611: + child.getPhysicalPG().getMass().getKilograms());
612:
613: if (original.getPhysicalPG() == child.getPhysicalPG()) {
614: debug(".test pgs are the same(EXPECTED)");
615: } else {
616: debug(".test pgs are different");
617: }
618:
619: debug(".test original pg "
620: + original.getPhysicalPG().getClass());
621: NewPhysicalPG newPhysicalPG = PropertyGroupFactory
622: .newPhysicalPG();
623: debug(".test " + newPhysicalPG.getClass());
624: newPhysicalPG.setMass(new Mass(666, Mass.KILOGRAMS));
625: child.setPhysicalPG(newPhysicalPG);
626:
627: if (original.getPhysicalPG() == child.getPhysicalPG()) {
628: debug(".test pgs are the same (WEIRD) !");
629: } else {
630: debug(".test pgs are different (EXPECTED)");
631: }
632:
633: debug(".test child " + child.getUID() + " - " + child
634: + " mass after "
635: + child.getPhysicalPG().getMass().getKilograms());
636:
637: debug(".test original " + original.getUID() + " - " + original
638: + " mass after "
639: + original.getPhysicalPG().getMass().getKilograms());
640: }
641:
642: protected void setItemPG(Asset newAsset, Asset boxProto) {
643: ItemIdentificationPG itemPG = PropertyGroupFactory
644: .newItemIdentificationPG();
645: newAsset.setItemIdentificationPG(itemPG);
646: String name = getUniqueID(boxProto);
647: if (isDebugEnabled())
648: debug(".setItemPG - item name " + name);
649:
650: ((NewItemIdentificationPG) itemPG).setItemIdentification(name);
651: ((NewItemIdentificationPG) itemPG).setNomenclature(name);
652: }
653:
654: int uniqueID = 0;
655:
656: protected String getUniqueID(Asset boxProto) {
657: return boxProto.getTypeIdentificationPG()
658: .getTypeIdentification()
659: + "_" + getAgentIdentifier() + "_" + uniqueID++;
660: }
661:
662: protected void adjustDimensions(GLMAsset asset,
663: PhysicalPG originalPhysicalPG, double tons) {
664: if (isDebugEnabled())
665: debug(".adjustDimensions called on " + asset.getUID());
666:
667: double aggregateTons = originalPhysicalPG.getMass().getTons();
668:
669: double ratio = tons / aggregateTons;
670:
671: double area = originalPhysicalPG.getFootprintArea()
672: .getSquareMeters();
673: double volume = originalPhysicalPG.getVolume().getCubicMeters();
674: double mass = originalPhysicalPG.getMass().getKilograms();
675:
676: NewPhysicalPG newPhysicalPG = PropertyGroupFactory
677: .newPhysicalPG();
678: newPhysicalPG.setMass(new Mass(mass * ratio, Mass.KILOGRAMS));
679:
680: newPhysicalPG.setFootprintArea(new Area(area * ratio,
681: Area.SQUARE_METERS));
682: newPhysicalPG.setVolume(new Volume(volume * ratio,
683: Volume.CUBIC_METERS));
684:
685: if (isDebugEnabled()) {
686: debug(".adjustDimensions chunk " + asset.getUID()
687: + " original dimensions :" + " m "
688: + asset.getPhysicalPG().getMass().getTons()
689: + " tons, " + " v "
690: + asset.getPhysicalPG().getVolume().getCubicFeet()
691: + " ft^3");
692: }
693:
694: asset.setPhysicalPG(newPhysicalPG);
695:
696: if (isDebugEnabled()) {
697: debug(".adjustDimensions chunk " + asset.getUID()
698: + " dimensions :" + " m "
699: + asset.getPhysicalPG().getMass().getTons()
700: + " tons, " + " v "
701: + asset.getPhysicalPG().getVolume().getCubicFeet()
702: + " ft^3");
703: }
704: }
705:
706: /**
707: * Makes subtask of parent task, with given direct object.
708: *
709: * removes OFTYPE prep, since it's not needed by scheduler
710: **/
711: Task makeTask(Task parentTask, Asset directObject, ForUnitPG unitPG) {
712: Task newtask = expandHelper.makeSubTask(ldmf, parentTask,
713: directObject, getAgentIdentifier());
714: glmPrepHelper.removePrepNamed(newtask,
715: Constants.Preposition.OFTYPE);
716: ((NewTask) newtask).setContext(parentTask.getContext());
717:
718: if (unitPG == null) {
719: // Next four lines create a Property Group for unit and attach it to all assets attached to task
720: unitPG = (ForUnitPG) ldmf
721: .createPropertyGroup(ForUnitPG.class);
722: if (!glmPrepHelper.hasPrepNamed(newtask,
723: Constants.Preposition.FOR)) {
724: String owner = directObject.getUID().getOwner();
725:
726: if (isWarnEnabled()) {
727: warn(".makeTask - WARNING : got task "
728: + parentTask.getUID()
729: + " which has no FOR unit prep, using owner - "
730: + owner + ".");
731: }
732:
733: ((NewForUnitPG) unitPG).setUnit(owner);
734: } else {
735: ((NewForUnitPG) unitPG).setUnit((String) glmPrepHelper
736: .getIndirectObject(newtask,
737: Constants.Preposition.FOR));
738: glmPrepHelper.removePrepNamed(newtask,
739: Constants.Preposition.FOR);
740: }
741: }
742:
743: attachPG(directObject, unitPG);
744:
745: return newtask;
746: }
747:
748: /**
749: * Since FOR preps are lost a custom property is added to determine unit
750: */
751: public void attachPG(Asset asset, PropertyGroup this PG) {
752: if (asset instanceof AssetGroup) {
753: Vector assetList = ((AssetGroup) asset).getAssets();
754: for (int i = 0; i < assetList.size(); i++) {
755: attachPG((Asset) assetList.elementAt(i), this PG);
756: }
757: } else if (asset instanceof AggregateAsset) {
758: // Put in both because unsure of behavior
759: asset.addOtherPropertyGroup(this PG);
760: // Don't want to do this, since every aggregate of X
761: //XX asset will then have this pg
762: // attachUnitPG(((AggregateAsset)asset).getAsset(),unitPG);
763: } else {
764: asset.addOtherPropertyGroup(this PG);
765: }
766: }
767:
768: /**
769: * <pre>
770: * Implemented for UTILAssetListener
771: *
772: * OVERRIDE to see which assets you
773: * think are interesting
774: * </pre>
775: * @param a asset to check for notification
776: * @return boolean true if asset is interesting
777: */
778: public boolean interestingAsset(Asset a) {
779: if (!(a instanceof GLMAsset)) {
780: if (isDebugEnabled())
781: debug(".interestingAsset - ignoring asset " + a
782: + " because it's not an GLMAsset.");
783: return false;
784: }
785:
786: boolean val = ((GLMAsset) a).hasContainPG();
787: if (isDebugEnabled() && !val)
788: debug(".interestingAsset - ignoring GLMAsset " + a
789: + " because it's missing a Contain PG.");
790: if (isDebugEnabled() && val)
791: debug(".interestingAsset - interested in asset " + a);
792: return val;
793:
794: }
795:
796: public void handleChangedAssets(Enumeration newAssets) {
797: }
798:
799: public void resetCapacities() {
800: Collection carriers = myAssetCallback.getSubscription()
801: .getCollection();
802: handleNewAssets(Collections.enumeration(carriers));
803: if (isWarnEnabled())
804: warn(getName()
805: + ".getSubtasks - recalculated maxContainContrib after rehydration.");
806:
807: if (maxContainCapacity == Double.MAX_VALUE) {
808: error(getName()
809: + ".getSubtasks - maxContainCapacity has not been set, it's "
810: + maxContainCapacity);
811: }
812: }
813:
814: /**
815: * <pre>
816: * Place to handle new assets.
817: *
818: * Looks for least common denominator
819: *
820: * </pre>
821: * @param newAssets new assets found in the container
822: */
823: public void handleNewAssets(Enumeration newAssets) {
824: if (isDebugEnabled())
825: debug(".handleNewAssets - called.");
826:
827: // Look through the assets, and find the least common denominator
828: for (; newAssets.hasMoreElements();) {
829: Object asset = newAssets.nextElement();
830: if (asset instanceof GLMAsset) {
831: GLMAsset alpasset = (GLMAsset) asset;
832: if (alpasset.hasContainPG()) {
833: double[] maxContain = getAssetMaxContain(alpasset);
834: calculateCommonMaxContain(maxContain);
835: didSetCapacity = true;
836: } else {
837: if (isDebugEnabled())
838: debug(".handleNewAssets - ignoring GLMAsset without contain pg - "
839: + alpasset.getUID());
840: }
841: } else {
842: if (isDebugEnabled())
843: debug(".handleNewAssets - ignoring non GLMAsset - "
844: + asset);
845: }
846: }
847: }
848:
849: //
850: // Sub classes may need to derive this separately
851: //
852: public double[] getAssetMaxContain(GLMAsset glmasset) {
853: double max[] = new double[2];
854: max[0] = 1.0d;
855: max[1] = 1.0d;
856: if (glmasset.hasContainPG()) {
857: try {
858: max[0] = glmasset.getContainPG().getMaximumWeight()
859: .getTons();
860: } catch (Exception e) {
861: if (isDebugEnabled())
862: debug(".getAssetMaxContain : no contain pg for asset "
863: + glmasset);
864: }
865:
866: max[1] = glmasset.getContainPG().getMaximumPassengers();
867: if (isDebugEnabled())
868: debug(".getAssetMaxContain : max weight - " + max[0]
869: + " max pax " + max[1]);
870: }
871: return max;
872: }
873:
874: /** calculates the max contain -- smallest of all seen */
875: protected void calculateCommonMaxContain(double[] maxcontain) {
876: if (maxcontain[0] < maxContainCapacity)
877: maxContainCapacity = maxcontain[0];
878:
879: if (maxcontain[1] < maxPassengerCapacity)
880: maxPassengerCapacity = maxcontain[1];
881: }
882:
883: protected double maxContainCapacity = Double.MAX_VALUE;
884: protected double maxPassengerCapacity = Double.MAX_VALUE;
885: protected boolean didSetCapacity = false;
886:
887: protected GLMPrepPhrase glmPrepHelper;
888: protected LDMServesPlugin ldmProtoCache;
889: protected UTILAssetCallback myAssetCallback;
890: }
|