001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.logistics.plugin.packer;
027:
028: import org.cougaar.glm.ldm.Constants;
029: import org.cougaar.glm.ldm.asset.GLMAsset;
030: import org.cougaar.glm.ldm.asset.NewContentsPG;
031: import org.cougaar.glm.ldm.asset.PropertyGroupFactory;
032: import org.cougaar.planning.ldm.asset.Asset;
033: import org.cougaar.planning.ldm.asset.ItemIdentificationPG;
034: import org.cougaar.planning.ldm.asset.TypeIdentificationPG;
035: import org.cougaar.planning.ldm.measure.Mass;
036: import org.cougaar.planning.ldm.plan.*;
037:
038: import java.util.ArrayList;
039: import java.util.Date;
040: import java.util.HashSet;
041: import java.util.Iterator;
042: import java.util.List;
043: import java.util.Vector;
044:
045: class Filler {
046: double MIN_DELTA = 0.0001; // 1/10000 of a pound
047:
048: protected boolean FIND_FOR_UNIT_PREP_ON_TASK = false;
049: protected long ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
050:
051: // no two tasks can have arrival dates farther than this time apart and
052: // be on the same milvan
053: protected long MAX_GROUP_DAYS = 2;
054:
055: private static final String UNKNOWN = "UNKNOWN";
056: private Sizer _sz;
057:
058: private GenericPlugin _gp;
059:
060: /**
061: * This is the generator for the Multi-parent tasks that
062: * are the "product" of the aggregation. Currently assumes that
063: * we're creating Transport tasks.
064: */
065: private AggregationClosure _ac;
066:
067: private PreferenceAggregator _pa;
068: /**
069: * The AllocationResultDistributor that should be used on
070: * any Containers created by this Filler
071: */
072: private AllocationResultDistributor _ard;
073:
074: public static double TRANSPORT_TONS;
075: ALPacker packer = null;
076:
077: Filler(Sizer sz, GenericPlugin gp, AggregationClosure ac,
078: AllocationResultDistributor ard, PreferenceAggregator pa) {
079: _sz = sz;
080: _gp = gp;
081: _ac = ac;
082: _ard = ard;
083: _pa = pa;
084:
085: if (gp instanceof ALPacker)
086: packer = (ALPacker) gp;
087: }
088:
089: /**
090: * This is the driving function in the whole packing process.
091: */
092: public double execute() {
093: //boolean finished = false;
094: double tonsPacked = 0;
095:
096: if (_gp.getLoggingService().isInfoEnabled())
097: _gp.getLoggingService().info("Filler.execute - entered.");
098: int numTasks = 0;
099: int numParents = 0;
100:
101: // while there's still ammo to put in milvans
102: while (_sz.moreTasksInQueue()) {
103: // initialize the aggregation
104: ArrayList agglist = new ArrayList();
105: double amount = 0.0;
106: double earliest = 0.0;
107: double latest = java.lang.Double.POSITIVE_INFINITY;
108:
109: // while our milvan is not yet full and there is more ammo left to pack
110: while (_ac.getQuantity() - amount > MIN_DELTA
111: && _sz.moreTasksInQueue()) {
112: // ask the sizer for what an amount that would fill the milvan
113: Task t = _sz.provide(_ac.getQuantity() - amount,
114: earliest, latest);
115: if (t == null) { // the next task is outside the earliest->latest window
116: // finished = true;
117: break;
118: }
119: numTasks++;
120:
121: // if we reach here, t is a Task that provides
122: // some amount towards our overall amount
123: double provided = t
124: .getPreferredValue(AspectType.QUANTITY);
125:
126: if (_gp.getLoggingService().isInfoEnabled()) {
127: _gp.getLoggingService().info(
128: "Filler.execute - adding " + provided
129: + " to agg list vs "
130: + (_ac.getQuantity() - amount)
131: + " amount " + amount);
132: }
133:
134: Preference endDatePref = t
135: .getPreference(AspectType.END_TIME);
136: ScoringFunction sf = endDatePref.getScoringFunction();
137:
138: AspectScorePoint aspStart = sf.getDefinedRange()
139: .getRangeStartPoint();
140: AspectScorePoint aspBest = sf.getBest();
141: AspectScorePoint aspEnd = sf.getDefinedRange()
142: .getRangeEndPoint();
143:
144: Date taskEarlyDate = new Date((long) aspStart
145: .getValue());
146: Date taskBestDateMinusFiveDays = new Date(
147: (long) aspBest.getValue() - MAX_GROUP_DAYS
148: * ONE_DAY_MILLIS);
149:
150: // no earlier than earliest arrival, but no more than 5 days before best
151: if (taskBestDateMinusFiveDays.getTime() < taskEarlyDate
152: .getTime())
153: taskBestDateMinusFiveDays = taskEarlyDate;
154: if (taskBestDateMinusFiveDays.getTime() > earliest) {
155: earliest = taskBestDateMinusFiveDays.getTime();
156: }
157:
158: // restrict the window of time within which we'll aggregate tasks together
159: // to be
160: //
161: // earliest arrival->best date + one day
162: //
163: // instead of
164: //
165: // earliest arrival->latest arrival
166: //
167: // because that can have problems when we replan
168: // tasks without plan elements (happens when all aggregations of an mptask get
169: // removed when any parent is removed). Resulting task has too narrow a time
170: // window, since the replanned transport task will have an arrival window of
171: // now->best date, and now could potentially be too close to the best date.
172:
173: Date taskLateDate = new Date((long) aspEnd.getValue());
174: Date taskBestDatePlusOneDay = new Date((long) aspBest
175: .getValue()
176: + ONE_DAY_MILLIS);
177:
178: // no later than late date, but no more than one day after best
179: if (taskBestDatePlusOneDay.getTime() > taskLateDate
180: .getTime())
181: taskBestDatePlusOneDay = taskLateDate;
182: if (taskBestDatePlusOneDay.getTime() < latest) {
183: latest = taskBestDatePlusOneDay.getTime();
184: }
185:
186: amount += provided;
187: agglist.add(t);
188: }
189:
190: if (!agglist.isEmpty()) {
191: double loadedQuantity = createMPTask(agglist);
192: numParents += agglist.size();
193: TRANSPORT_TONS += loadedQuantity;
194: tonsPacked += loadedQuantity;
195: }
196:
197: if (_gp.getLoggingService().isInfoEnabled()) {
198: _gp.getLoggingService().info(
199: "Filler.execute - aggregating together "
200: + agglist.size() + " parents:");
201: for (Iterator iter = agglist.iterator(); iter.hasNext();) {
202: Task task = (Task) iter.next();
203: _gp
204: .getLoggingService()
205: .info(
206: "Filler.execute - "
207: + task.getUID()
208: + " end date "
209: + new Date(
210: (long) task
211: .getPreferredValue(AspectType.END_TIME)));
212: }
213: }
214:
215: }
216:
217: if (numTasks != numParents)
218: _gp.getLoggingService().error(
219: "Filler.execute - num tasks created " + numTasks
220: + " != parents of MPTask " + numParents);
221:
222: if (numParents != _sz.sizedMade)
223: _gp.getLoggingService().error(
224: "Filler.execute - sizer num tasks made "
225: + _sz.sizedMade
226: + " != total parents of MPTask "
227: + numParents);
228:
229: if (_gp.getLoggingService().isInfoEnabled())
230: _gp.getLoggingService().info(
231: "Packer - current aggregated requested transport: "
232: + TRANSPORT_TONS + " tons.");
233:
234: if (_gp.getLoggingService().isInfoEnabled())
235: _gp.getLoggingService().info("Filler.execute - exited.");
236:
237: return tonsPacked;
238: }
239:
240: public double handleUnplanned(Task unplanned) {
241: if (_gp.getLoggingService().isDebugEnabled())
242: _gp.getLoggingService().debug(
243: "Filler.handleUnplanned - replanning "
244: + unplanned.getUID());
245: List agglist = new ArrayList();
246: // packer.subtractTaskFromReceiver (unplanned);
247: agglist.add(unplanned);
248: double loadedQuantity = createMPTask(agglist);
249: return loadedQuantity;
250: }
251:
252: /** agglist is the list of parent tasks */
253: protected double createMPTask(List agglist) {
254: // now we do the aggregation
255: NewMPTask mpt = _ac.newTask();
256:
257: HashSet set = new HashSet();
258: Iterator taskIt = agglist.iterator();
259: Task parentTask;
260: while (taskIt.hasNext()) {
261: parentTask = (Task) taskIt.next();
262: if (parentTask.getContext() != null) {
263: set.addAll((ContextOfOplanIds) parentTask.getContext());
264: }
265: }
266: mpt.setContext(new ContextOfOplanIds(set));
267:
268: // Set ContentsPG on container
269: addContentsInfo((GLMAsset) mpt.getDirectObject(), agglist);
270:
271: //BOZO
272: mpt.setPreferences(new Vector(_pa.aggregatePreferences(agglist
273: .iterator(), _gp.getGPFactory())).elements());
274: double loadedQuantity = mpt
275: .getPreferredValue(AspectType.QUANTITY);
276: Plan plan = ((Task) agglist.get(0)).getPlan();
277:
278: _gp.createAggregation(agglist.iterator(), mpt, plan, _ard);
279:
280: if (mpt.getComposition().getParentTasks().size() != agglist
281: .size())
282: _gp.getLoggingService().error(
283: "Filler.createMPTask - received "
284: + agglist.size()
285: + " tasks to be agggregated, but only "
286: + mpt.getComposition().getParentTasks()
287: .size() + " tasks as parents of "
288: + mpt.getUID());
289: //System.out.println( " FILLER : what is the loadedQuantity " + loadedQuantity);
290: return loadedQuantity;
291: }
292:
293: protected void addContentsInfo(GLMAsset container, List agglist) {
294: ArrayList typeIDs = new ArrayList();
295: ArrayList nomenclatures = new ArrayList();
296: ArrayList weights = new ArrayList();
297: ArrayList receivers = new ArrayList();
298:
299: for (Iterator iterator = agglist.iterator(); iterator.hasNext();) {
300: Task task = (Task) iterator.next();
301: TypeIdentificationPG typeIdentificationPG = task
302: .getDirectObject().getTypeIdentificationPG();
303: String typeID;
304: String nomenclature;
305: if (typeIdentificationPG != null) {
306: typeID = typeIdentificationPG.getTypeIdentification();
307: if ((typeID == null) || (typeID.equals(""))) {
308: typeID = UNKNOWN;
309: }
310:
311: nomenclature = typeIdentificationPG.getNomenclature();
312: if ((nomenclature == null) || (nomenclature.equals(""))) {
313: nomenclature = UNKNOWN;
314: }
315: } else {
316: typeID = UNKNOWN;
317: nomenclature = UNKNOWN;
318: }
319: typeIDs.add(typeID);
320: nomenclatures.add(nomenclature);
321:
322: double quantity = task
323: .getPreferredValue(AspectType.QUANTITY);
324: Mass mass = Mass.newMass(quantity, Mass.SHORT_TONS);
325: weights.add(mass);
326:
327: String receiverID;
328: if (FIND_FOR_UNIT_PREP_ON_TASK) {
329: receiverID = getReceiverID(task);
330: } else {
331: receiverID = _gp.getGPMessageAddress().getAddress();
332: }
333:
334: _gp.getLoggingService().info(
335: "Adding - " + task.getUID() + " for " + receiverID
336: + " - " + typeID + " - " + quantity);
337: packer.addToReceiver(receiverID, typeID, quantity);
338:
339: receivers.add(receiverID);
340: }
341:
342: // Contents
343: NewContentsPG contentsPG = PropertyGroupFactory.newContentsPG();
344: contentsPG.setNomenclatures(nomenclatures);
345: contentsPG.setTypeIdentifications(typeIDs);
346: contentsPG.setWeights(weights);
347: contentsPG.setReceivers(receivers);
348: container.setContentsPG(contentsPG);
349: }
350:
351: protected String getReceiverID(Task task) {
352: String receiverID;
353:
354: Object receiver = task
355: .getPrepositionalPhrase(Constants.Preposition.FOR);
356:
357: if (receiver != null)
358: receiver = ((PrepositionalPhrase) receiver)
359: .getIndirectObject();
360:
361: // Add field with recipient
362: if (receiver == null) {
363: receiverID = UNKNOWN;
364: _gp.getLoggingService().error(
365: "Filler.addContentsInfo - Task " + task.getUID()
366: + " had no FOR prep.");
367: } else if (receiver instanceof String) {
368: receiverID = (String) receiver;
369: } else if (!(receiver instanceof Asset)) {
370: receiverID = UNKNOWN;
371: } else {
372: ItemIdentificationPG itemIdentificationPG = ((Asset) receiver)
373: .getItemIdentificationPG();
374: if ((itemIdentificationPG == null)
375: || (itemIdentificationPG.getItemIdentification() == null)
376: || (itemIdentificationPG.getItemIdentification()
377: .equals(""))) {
378: receiverID = UNKNOWN;
379: } else {
380: receiverID = itemIdentificationPG
381: .getItemIdentification();
382: }
383: }
384: return receiverID;
385: }
386: }
|