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.text.*;
029: import java.util.Collection;
030: import java.util.Enumeration;
031: import java.util.Iterator;
032:
033: import org.cougaar.lib.util.UTILAllocate;
034: import org.cougaar.lib.util.UTILPreference;
035:
036: import org.cougaar.lib.vishnu.client.XMLizer;
037: import org.cougaar.lib.vishnu.client.custom.CustomVishnuAggregatorPlugin;
038:
039: import org.cougaar.planning.ldm.asset.AbstractAsset;
040: import org.cougaar.planning.ldm.asset.AggregateAsset;
041: import org.cougaar.planning.ldm.asset.Asset;
042: import org.cougaar.planning.ldm.asset.AssetGroup;
043: import org.cougaar.planning.ldm.plan.Task;
044: import org.cougaar.logistics.ldm.Constants;
045:
046: import org.cougaar.glm.ldm.asset.GLMAsset;
047: import org.cougaar.glm.ldm.plan.GeolocLocation;
048: import org.cougaar.glm.util.GLMMeasure;
049: import org.cougaar.glm.util.GLMPrepPhrase;
050:
051: public class GenericVishnuPlugin extends CustomVishnuAggregatorPlugin {
052:
053: private static final double NM_TO_MILE = 1.15078;
054: private static final double MILE_TO_NM = 1.0d / 1.15078d;
055: private static final NumberFormat format = new DecimalFormat("##.#");
056:
057: public void localSetup() {
058: super .localSetup();
059:
060: glmPrepHelper = new GLMPrepPhrase(logger);
061: measureHelper = new GLMMeasure(logger);
062: }
063:
064: protected XMLizer createXMLizer(boolean direct) {
065: GenericDataXMLize xmlizer = new GenericDataXMLize(direct,
066: logger);
067: setDataXMLizer(xmlizer);
068: return xmlizer;
069: }
070:
071: protected void setDataXMLizer(GenericDataXMLize xmlizer) {
072: dataXMLizer = xmlizer;
073: }
074:
075: // java.util.Set seen = new java.util.HashSet ();
076:
077: public void processTasks(java.util.List tasks) {
078: java.util.List prunedTasks = new java.util.ArrayList(tasks
079: .size());
080:
081: Collection removed = myWorkflowCallback.getSubscription()
082: .getRemovedCollection();
083:
084: for (Iterator iter = tasks.iterator(); iter.hasNext();) {
085: Task task = (Task) iter.next();
086: if (removed.contains(task)) {
087: if (isInfoEnabled()) {
088: info("ignoring task on removed list "
089: + task.getUID());
090: }
091: } else {
092: /* if (seen.contains(task.getUID())) {
093: if (isInfoEnabled()) {
094: info ("ignoring already processed " + task.getUID());
095: }
096: }
097: else {
098: seen.add (task.getUID());
099: */
100: prunedTasks.add(task);
101: // }
102: }
103: }
104: super .processTasks(prunedTasks);
105: }
106:
107: /** prints out date info on failure */
108: protected void handleImpossibleTasks(Collection impossibleTasks) {
109: if (!foundMaxAssetValues) {
110: findMaxAssetValues();
111: foundMaxAssetValues = true;
112: }
113:
114: if (!impossibleTasks.isEmpty() && isInfoEnabled()) {
115: info(getName() + ".handleImpossibleTasks - failing "
116: + impossibleTasks.size() + " tasks.");
117: }
118:
119: for (Iterator iter = impossibleTasks.iterator(); iter.hasNext();) {
120: Task task = (Task) iter.next();
121:
122: publishAdd(allocHelper.makeFailedDisposition(this , ldmf,
123: task));
124: error(getName()
125: + ".handleImpossibleTasks - impossible task : "
126: + task.getUID() + "\nreadyAt "
127: + prefHelper.getReadyAt(task) + "\nearly "
128: + prefHelper.getEarlyDate(task) + "\nbest "
129: + prefHelper.getBestDate(task) + "\nlate "
130: + prefHelper.getLateDate(task));
131:
132: GeolocLocation from = glmPrepHelper.getFromLocation(task);
133: GeolocLocation to = glmPrepHelper.getToLocation(task);
134: float great = (float) measureHelper.distanceBetween(from,
135: to).getNauticalMiles();
136: float timeDiff = (float) (prefHelper.getBestDate(task)
137: .getTime() - prefHelper.getReadyAt(task).getTime());
138: float time = timeDiff / 3600000.0f;
139: float speed = great / time;
140:
141: if (speed > maxSpeed) {
142: error(getName()
143: + ".handleImpossibleTasks - impossible task : "
144: + task.getUID()
145: + "\ndistance from "
146: + from
147: + " to "
148: + to
149: + " is great-circle "
150: + format.format(great)
151: + " nm, ("
152: + format.format(great * NM_TO_MILE)
153: + " miles) \narrival-departure is "
154: + format.format(time)
155: + " hrs so"
156: + " speed would have to be at least "
157: + format.format(speed)
158: + " knots ("
159: + format.format(speed * NM_TO_MILE)
160: + " mph).\n"
161: + "This is greater than the speed of the fastest asset : "
162: + format.format(maxSpeed) + " knots ("
163: + format.format(maxSpeed * NM_TO_MILE)
164: + " mph).\n");
165: } else {
166: if (isWarnEnabled()) {
167: warn(getName()
168: + ".handleImpossibleTasks - impossible task : "
169: + task.getUID()
170: + "\ndistance from "
171: + from
172: + " to "
173: + to
174: + " is great-circle "
175: + format.format(great)
176: + " nm, ("
177: + format.format(great * NM_TO_MILE)
178: + " miles) \narrival-departure is "
179: + format.format(time)
180: + " hrs so"
181: + " speed would have to be at least "
182: + format.format(speed)
183: + " knots ("
184: + format.format(speed * NM_TO_MILE)
185: + " mph).\n"
186: + "But this is not greater than the speed of the fastest asset : "
187: + format.format(maxSpeed) + " knots ("
188: + format.format(maxSpeed * NM_TO_MILE)
189: + " mph). So should be OK.\n");
190: }
191: }
192:
193: Asset directObject = task.getDirectObject();
194: GLMAsset baseAsset = null;
195:
196: if (directObject instanceof AggregateAsset) {
197: baseAsset = (GLMAsset) ((AggregateAsset) directObject)
198: .getAsset();
199: } else if (directObject instanceof AssetGroup) {
200: error(getName()
201: + ".handleImpossibleTasks - something is really wrong - "
202: + " input task had a d.o. that was an asset group, task was "
203: + task.getUID());
204: return;
205: } else {
206: baseAsset = (GLMAsset) directObject;
207: }
208:
209: if (dataXMLizer.getArea(baseAsset) > maxAreaCap) {
210: error(getName()
211: + ".handleImpossibleTasks - impossible task : "
212: + task.getUID() + "\narea of "
213: + format.format(dataXMLizer.getArea(baseAsset))
214: + " sq ft is > max carrier area "
215: + format.format(maxAreaCap));
216: }
217:
218: if (dataXMLizer.getWeight(baseAsset) > maxWeightCap) {
219: error(getName()
220: + ".handleImpossibleTasks - impossible task : "
221: + task.getUID()
222: + "\nweight of "
223: + format.format(dataXMLizer
224: .getWeight(baseAsset))
225: + " tons is > max carrier weight "
226: + format.format(maxWeightCap));
227: }
228: }
229:
230: if (stopOnFailure && !impossibleTasks.isEmpty()) {
231: if (isWarnEnabled()) {
232: warn(getName()
233: + ".handleImpossibleTasks - stopping on failure!");
234: }
235: System.exit(-1);
236: }
237: }
238:
239: /** get max dimensions and speed on error so can aid reporting */
240: protected void findMaxAssetValues() {
241: for (Iterator iter = getAssetCallback().getSubscription()
242: .getCollection().iterator(); iter.hasNext();) {
243: Asset asset = (Asset) iter.next();
244: if (asset instanceof GLMAsset) {
245: GLMAsset glmAsset = (GLMAsset) asset;
246: if (glmAsset.hasContainPG()) {
247: if (dataXMLizer == null)
248: error("huh? dataxmlizer is null???");
249: double speed = dataXMLizer.getSpeed(glmAsset); // mph
250:
251: double knots = speed * MILE_TO_NM;
252: if (maxSpeed < knots)
253: maxSpeed = knots;
254:
255: double weightCap = dataXMLizer
256: .getWeightCapacity(glmAsset); // tons
257: if (maxWeightCap < weightCap)
258: maxWeightCap = weightCap;
259:
260: double areaCap = dataXMLizer
261: .getAreaCapacity(glmAsset); // square feet
262: if (maxAreaCap < areaCap)
263: maxAreaCap = areaCap;
264: }
265: }
266: }
267:
268: if (isDebugEnabled()) {
269: debug(getName() + " - max speed " + maxSpeed + " area "
270: + maxAreaCap + " weight " + maxWeightCap);
271: }
272: }
273:
274: /**
275: * Implemented for UTILAssetListener
276: * <p>
277: * OVERRIDE to see which assets you think are interesting.
278: * <p>
279: * For instance, if you are scheduling trucks/ships/planes,
280: * you'd want to check like this :
281: * <code>
282: * return (GLMAsset).hasContainPG ();
283: * </code>
284: * @param a asset to check
285: * @return boolean true if asset is interesting
286: */
287: public boolean interestingAsset(Asset a) {
288: if (a instanceof GLMAsset) {
289: return ((GLMAsset) a).hasContainPG();
290: }
291: return false;
292: }
293:
294: public boolean interestingTask(Task t) {
295: if (t.getVerb().equals(Constants.Verb.TRANSPORT)) {
296: if (t.getDirectObject() instanceof AbstractAsset) {
297: error("Whoops, apparently interesting AbstractAsset: "
298: + t);
299: return false;
300: }
301: return super .interestingTask(t);
302: }
303: return false;
304: }
305:
306: protected GLMPrepPhrase glmPrepHelper;
307: protected GLMMeasure measureHelper;
308: protected GenericDataXMLize dataXMLizer;
309:
310: protected boolean foundMaxAssetValues = false;
311:
312: protected double maxSpeed = 0;
313: protected double maxWeightCap = 0;
314: protected double maxAreaCap = 0;
315: }
|