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.tools;
027:
028: import java.util.Collection;
029: import java.util.Collections;
030: import java.util.Enumeration;
031: import java.util.HashSet;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.Map;
035: import java.util.Set;
036: import java.util.Vector;
037:
038: import org.cougaar.core.blackboard.IncrementalSubscription;
039: import org.cougaar.planning.ldm.PlanningFactory;
040:
041: import org.cougaar.glm.callback.GLMLocationListener;
042: import org.cougaar.glm.callback.GLMLocationCallback;
043:
044: import org.cougaar.glm.ldm.asset.Container;
045: import org.cougaar.glm.ldm.asset.GLMAsset;
046: import org.cougaar.glm.ldm.asset.TransportationNode;
047: import org.cougaar.glm.ldm.asset.TransportationRoute;
048: import org.cougaar.glm.ldm.asset.TransportationSeaLink;
049:
050: import org.cougaar.glm.ldm.plan.GeolocLocation;
051: import org.cougaar.glm.ldm.plan.NewGeolocLocation;
052:
053: import org.cougaar.logistics.plugin.trans.SequentialGlobalAirPlugin;
054:
055: import org.cougaar.glm.util.GLMMeasure;
056:
057: import org.cougaar.lib.filter.UTILPluginAdapter;
058: import org.cougaar.lib.util.UTILAllocate;
059:
060: import org.cougaar.planning.ldm.asset.AggregateAsset;
061: import org.cougaar.planning.ldm.asset.Asset;
062: import org.cougaar.planning.ldm.asset.AssetGroup;
063:
064: import org.cougaar.planning.ldm.plan.Task;
065:
066: import org.cougaar.planning.ldm.measure.Distance;
067: import org.cougaar.planning.ldm.measure.Latitude;
068: import org.cougaar.planning.ldm.measure.Longitude;
069:
070: import org.cougaar.planning.ldm.plan.Location;
071:
072: import org.cougaar.util.UnaryPredicate;
073: import org.cougaar.util.log.Logger;
074:
075: /**
076: * An object for finding the correct POE or POD for a given geoloc
077: */
078: public class PortLocatorImpl extends LocatorImpl {
079: /*
080: * Locator must be instantiated within the setupFilters() method on its
081: * parent plugIn. This is because the LocationCallback has to be
082: * instantiated within the context of an open transaction.
083: */
084: public PortLocatorImpl(BlackboardPlugin pi, Logger logger) {
085: super (pi, logger);
086:
087: }
088:
089: /**
090: * A new asset has appeared on the blackboard - if it's the ammo port, add it to list of POEExceptions
091: * Also, if it's a theater port, mark it as an exception (i.e. don't use it to look for POEs).
092: */
093: public void handleNewLocations(Enumeration newLocations) {
094: Vector newPorts = allocHelper.enumToVector(newLocations);
095: super .handleNewLocations(newPorts.elements());
096:
097: if (POEExceptions == null) {
098: allocHelper = new UTILAllocate(logger);
099: POEExceptions = new HashSet();
100: POEExceptionsNotSunnyPoint = new HashSet();
101: routeCache = new HashMap();
102: }
103:
104: if (POEExceptions.isEmpty()) {
105: Object port = getAssetAtGeolocCode("WMPT");
106: if (port != null)
107: POEExceptions.add(getLocationOfAsset(port));
108: }
109:
110: for (Iterator iter = newPorts.iterator(); iter.hasNext();) {
111: Asset asset = (Asset) iter.next();
112: if (asset.getTypeIdentificationPG().getTypeIdentification()
113: .equals("TheaterSeaport")) {
114: POEExceptions.add(getLocationOfAsset(asset));
115: POEExceptionsNotSunnyPoint
116: .add(getLocationOfAsset(asset));
117: }
118: }
119: }
120:
121: public boolean isKnownException(Asset seaport) {
122: return POEExceptions.contains(getLocationOfAsset(seaport));
123: }
124:
125: public TransportationRoute getRoute(Task parentTask) {
126: GeolocLocation origin = glmPrepHelper
127: .getFromLocation(parentTask);
128: GeolocLocation destination = glmPrepHelper
129: .getToLocation(parentTask);
130:
131: Asset asset = parentTask.getDirectObject();
132: boolean isAmmo = false;
133:
134: TransportationRoute route = null;
135:
136: if (asset instanceof AssetGroup) {
137: Vector assetList = ((AssetGroup) asset).getAssets();
138: for (int i = 0; i < assetList.size(); i++) {
139: Asset subAsset = (Asset) assetList.elementAt(i);
140:
141: if (subAsset instanceof AggregateAsset)
142: subAsset = ((AggregateAsset) subAsset).getAsset();
143:
144: if ((subAsset instanceof GLMAsset)
145: && isAmmo((GLMAsset) subAsset))
146: isAmmo = true;
147:
148: break;
149: }
150: } else if (asset instanceof AggregateAsset) {
151: // route = getGreatCircleRoute(origin, destination);
152: Asset subAsset = ((AggregateAsset) asset).getAsset();
153:
154: // if not ammo, don't know what it is -- it must not be ammo
155: isAmmo = (subAsset instanceof GLMAsset) ? isAmmo((GLMAsset) subAsset)
156: : false;
157:
158: // logger.info ("PortLocatorImpl - got great circle route from " + origin + " to " + destination);
159: } else {
160: isAmmo = isAmmo((GLMAsset) asset);
161: }
162:
163: if (route == null) {
164: if (isAmmo) {
165: if (logger.isInfoEnabled()) {
166: logger
167: .info("PortLocatorImpl.getRoute - task "
168: + parentTask.getUID()
169: + " found ammo so getting route starting at SunnyPoint.");
170: }
171:
172: Object seaport = getAssetAtGeolocCode("WMPT");
173: if (seaport != null) {
174: origin = (GeolocLocation) getLocationOfAsset(seaport);
175: if (logger.isInfoEnabled()) {
176: logger.info("PortLocatorImpl.getRoute - task "
177: + parentTask.getUID()
178: + " getting route starting at "
179: + origin);
180: }
181: } else {
182: if (logger.isWarnEnabled()) {
183: logger
184: .warn("PortLocatorImpl.getRoute - could not find SunnyPoint port among known ports?");
185: }
186: }
187: }
188:
189: // determine POE that has the shortest ship route to the POD
190: // this may differ a great deal from the simple great-circle distance
191: route = getRoute(origin, destination, isAmmo);
192:
193: if (!route.getSource().getGeolocLocation().equals(origin)) {
194: if (logger.isInfoEnabled()) {
195: logger.info("asked for a route from " + origin
196: + " but got one from " + route.getSource()
197: + " geoloc "
198: + route.getSource().getGeolocLocation());
199: }
200: }
201: }
202:
203: if (logger.isDebugEnabled()) {
204: boolean fromIsPOE = isKnownGeolocCode(origin
205: .getGeolocCode());
206: boolean toIsPOD = isKnownGeolocCode(destination
207: .getGeolocCode());
208:
209: logger.debug("PortLocatorImpl - getting route from "
210: + origin + ((fromIsPOE) ? " POE " : "") + " to "
211: + destination + ((toIsPOD) ? " POD " : ""));
212: logger.debug("PortLocatorImpl - route obtained was from "
213: + route.getSource().getGeolocLocation() + " to "
214: + route.getDestination().getGeolocLocation());
215: }
216:
217: return route;
218: }
219:
220: /** caches routes found for FROM-TO pairs */
221: protected TransportationRoute getRoute(GeolocLocation origin,
222: GeolocLocation destination, boolean isAmmo) {
223: TransportationRoute route = getRouteFromCache(origin,
224: destination);
225:
226: if (route == null) {
227: route = getRoute(origin, destination,
228: isAmmo ? POEExceptionsNotSunnyPoint : POEExceptions);
229: cacheRoute(origin, destination, route);
230: }
231:
232: return route;
233: }
234:
235: /*
236: protected TransportationRoute getGreatCircleRoute (GeolocLocation origin, GeolocLocation destination) {
237: TransportationRoute route = getRouteFromCache (origin, destination);
238:
239: if (route == null) {
240: route = routeFinder.makeSimpleRoute (origin, destination);
241: cacheRoute (origin, destination, route);
242: }
243:
244: return route;
245: }
246: */
247:
248: protected TransportationRoute getRouteFromCache(
249: GeolocLocation origin, GeolocLocation destination) {
250: TransportationRoute route = null;
251: Map destinationMap = (Map) routeCache.get(origin
252: .getGeolocCode());
253:
254: if (destinationMap != null)
255: route = (TransportationRoute) destinationMap
256: .get(destination.getGeolocCode());
257:
258: return route;
259: }
260:
261: protected void cacheRoute(GeolocLocation origin,
262: GeolocLocation destination, TransportationRoute route) {
263: Map destinationMap = (Map) routeCache.get(origin
264: .getGeolocCode());
265:
266: if (!route.getSource().getGeolocLocation().equals(origin)) {
267: if (logger.isInfoEnabled()) {
268: logger.info("cacheing route from " + origin
269: + " that starts from " + route.getSource()
270: + " geoloc "
271: + route.getSource().getGeolocLocation());
272: }
273: }
274:
275: if (destinationMap == null)
276: routeCache.put(origin.getGeolocCode(),
277: (destinationMap = new HashMap()));
278:
279: if (logger.isInfoEnabled()) {
280: logger.info("cacheing route from " + origin + " to "
281: + destination + " with route from "
282: + route.getSource() + " to "
283: + route.getDestination());
284: }
285:
286: destinationMap.put(destination.getGeolocCode(), route);
287: }
288:
289: public Location getPortNearestToFromLoc(Task parentTask) {
290: if (!isAmmo((GLMAsset) parentTask.getDirectObject())) {
291: return getPOENearestToFromLoc(parentTask, POEExceptions);
292: }
293:
294: // Object seaport = geolocToAirport.get ("WMPT");
295: Object seaport = getAssetAtGeolocCode("WMPT");
296: if (seaport != null) {
297: return getLocationOfAsset(seaport);
298: } else {
299: logger
300: .error(".getPOENearestToFromLoc - "
301: + " could not find sunny point port, using nearest port instead.");
302: return getPOENearestToFromLoc(parentTask);
303: }
304: }
305:
306: protected boolean isContainer(GLMAsset asset) {
307: return asset instanceof Container;
308: }
309:
310: /**
311: * An asset is an ammo container if it has a contents pg, since
312: * only the Ammo Packer put a contents pg on a container.
313: *
314: * @return true if asset has a contents PG - i.e. is a milvan
315: */
316: protected boolean isAmmo(GLMAsset asset) {
317: return asset.hasContentsPG();
318: }
319:
320: protected String getAssetType(Asset asset) {
321: String name = "";
322:
323: try {
324: name = asset.getTypeIdentificationPG().getNomenclature();
325: } catch (Exception e) {
326: logger.error(".getAssetType - ERROR - no type id pg on "
327: + asset);
328: }
329:
330: if (name == null) {
331: try {
332: name = asset.getTypeIdentificationPG()
333: .getTypeIdentification();
334: } catch (Exception e) {
335: logger
336: .error(".getAssetType - ERROR - no type id pg on "
337: + asset);
338: }
339: }
340: if (name == null)
341: name = "";
342: return name;
343: }
344:
345: protected transient Set POEExceptions; // Locations not to leave from including Sunny Point
346: protected transient Set POEExceptionsNotSunnyPoint; // Locations not to leave from, except Sunny Point
347: protected transient Map routeCache;
348:
349: UTILAllocate allocHelper;
350: }
|