001: /*
002: * <copyright>
003: *
004: * Copyright 1999-2004 Honeywell Inc
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:
027: package org.cougaar.glm.packer;
028:
029: // utils
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.HashMap;
033: import java.util.Iterator;
034: import java.util.Vector;
035:
036: import org.cougaar.glm.ldm.Constants;
037: import org.cougaar.glm.ldm.asset.Container;
038: import org.cougaar.glm.ldm.asset.NewContentsPG;
039: import org.cougaar.glm.ldm.asset.NewMovabilityPG;
040: import org.cougaar.glm.ldm.asset.PropertyGroupFactory;
041: import org.cougaar.glm.ldm.plan.GeolocLocation;
042: import org.cougaar.planning.ldm.asset.Asset;
043: import org.cougaar.planning.ldm.asset.NewItemIdentificationPG;
044: import org.cougaar.planning.ldm.plan.NewMPTask;
045: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
046: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
047: import org.cougaar.planning.ldm.plan.Priority;
048: import org.cougaar.planning.ldm.plan.Task;
049:
050: public class AmmoTransport extends AggregationClosure {
051: public static final String AMMO_CATEGORY_CODE = "MBB";
052: public static final String MILVAN_NSN = "NSN/8115001682275";
053:
054: /* From Jeff Berliner -
055: * found this data in an Army Field Manual, FM 55-15, page C-2.
056: *
057: * Table C-3. Mean content weight in tons
058: * by container size
059: * CONTAINER SIZE
060: * CONTENTS 20-Foot 40-Foot
061: * Ammunition 13.90 -----
062: * General Cargo 6.47 15.42
063: *
064: * This, apparently, is the source of the constant 13.9 as the tons of ammo that is
065: * packed into each container by the Ammo Packer. We should probably document this
066: * source of that data.
067: *
068: * I posted this document, along with many other reference-type documents, on my web
069: * page on eiger: http://www.alpine.bbn.com/~berliner/
070: *
071: * The particular Field Manual of Transportation Reference Data is:
072: *
073: * http://www.alpine.bbn.com/~berliner/alp-cougaar-ultralog-data/FM55-15-Transportation-Reference-Data/
074: *
075: * The Appendix with this Transportation-Related data is:
076: *
077: * http://www.alpine.bbn.com/~berliner/alp-cougaar-ultralog-data/FM55-15-Transportation-Reference-Data/APPC.PDF
078: */
079: public static final double PACKING_LIMIT = 13.9; /* short tons */
080:
081: private static Asset MILVAN_PROTOTYPE = null;
082: private static long COUNTER = 0;
083:
084: private GeolocLocation mySource;
085: private GeolocLocation myDestination;
086:
087: public static Collection getTransportGroups(Collection tasks) {
088: HashMap destMap = new HashMap();
089:
090: for (Iterator iterator = tasks.iterator(); iterator.hasNext();) {
091: Task task = (Task) iterator.next();
092: GeolocLocation destination = getDestination(task);
093: Collection destTasks = (Collection) destMap
094: .get(destination);
095: if (destTasks == null) {
096: destTasks = new ArrayList();
097: destMap.put(destination, destTasks);
098: }
099: destTasks.add(task);
100: }
101:
102: return destMap.values();
103: }
104:
105: public AmmoTransport() {
106: }
107:
108: // public AmmoTransport(ArrayList tasks) {
109: // setDestinations(tasks);
110: // }
111:
112: public void setDestinations(ArrayList tasks) {
113: for (Iterator iterator = tasks.iterator(); iterator.hasNext();) {
114: Task t = (Task) iterator.next();
115: GeolocLocation taskSource = getSource(t);
116: GeolocLocation taskDestination = getDestination(t);
117:
118: if ((taskSource == null) || (taskDestination == null)) {
119:
120: _gp
121: .getLoggingService()
122: .error(
123: "AmmoTransport(): task without a source/destination");
124: } else if ((mySource == null) || (myDestination == null)) {
125: mySource = taskSource;
126: myDestination = taskDestination;
127: } else if (!(mySource.getGeolocCode().equals(taskSource
128: .getGeolocCode()))) {
129: _gp.getLoggingService().error(
130: "AmmoTransport(): " + mySource
131: + " not equal to " + taskSource);
132: } else if (!(myDestination.getGeolocCode()
133: .equals(taskDestination.getGeolocCode()))) {
134: _gp.getLoggingService().error(
135: "AmmoTransport(): " + myDestination
136: + " not equal to " + taskDestination);
137: }
138: }
139: }
140:
141: /**
142: * returns max quanitity in short tons
143: *
144: * BOZO - unit picked because it agreed with the incoming supply requests
145: */
146: public double getQuantity() {
147: return PACKING_LIMIT;
148: }
149:
150: /**
151: * returns appropriate transport source location
152: *
153: * Currently hardcoded because incoming supply tasks don't have that
154: * info
155: */
156: public static GeolocLocation getSource(Task task) {
157: return Geolocs.blueGrass();
158: }
159:
160: /**
161: * returns appropriate transport destination location
162: *
163: */
164: public static GeolocLocation getDestination(Task task) {
165: PrepositionalPhrase phrase = task
166: .getPrepositionalPhrase(Constants.Preposition.TO);
167: GeolocLocation destination = null;
168: if (phrase != null) {
169: destination = (GeolocLocation) phrase.getIndirectObject();
170: }
171: return destination;
172: }
173:
174: public boolean validTask(Task t) {
175: return (mySource.getGeolocCode().equals(
176: getSource(t).getGeolocCode()) && myDestination
177: .getGeolocCode().equals(
178: getDestination(t).getGeolocCode()));
179: }
180:
181: /**
182: * Creates a Transport task, per the interface published by TOPS.
183: */
184: public NewMPTask newTask() {
185: if (_gp == null) {
186: _gp
187: .getLoggingService()
188: .error(
189: "AmmoTransport: Error! AmmoTransport not properly initialized: setGenericPlugin not called.");
190: return null;
191: }
192:
193: if ((mySource == null) || (myDestination == null)) {
194: _gp
195: .getLoggingService()
196: .error(
197: "AmmoTransport: Error! AmmoTransport not properly initialized: some parameter(s) are null.");
198: return null;
199: }
200:
201: Asset milvan = makeMilvan();
202: if (milvan == null) {
203: return null;
204: }
205:
206: NewMPTask task = _gp.getGPFactory().newMPTask();
207: task.setVerb(Constants.Verb.Transport);
208:
209: task.setPriority(Priority.UNDEFINED);
210:
211: task.setDirectObject(milvan);
212:
213: Vector preps = new Vector(2);
214:
215: NewPrepositionalPhrase fromPrepositionalPhrase = _gp
216: .getGPFactory().newPrepositionalPhrase();
217: fromPrepositionalPhrase
218: .setPreposition(Constants.Preposition.FROM);
219: fromPrepositionalPhrase.setIndirectObject(mySource);
220: preps.addElement(fromPrepositionalPhrase);
221:
222: NewPrepositionalPhrase toPrepositionalPhrase = _gp
223: .getGPFactory().newPrepositionalPhrase();
224: toPrepositionalPhrase = _gp.getGPFactory()
225: .newPrepositionalPhrase();
226: toPrepositionalPhrase.setPreposition(Constants.Preposition.TO);
227: toPrepositionalPhrase.setIndirectObject(myDestination);
228: preps.addElement(toPrepositionalPhrase);
229:
230: task.setPrepositionalPhrases(preps.elements());
231:
232: return task;
233: }
234:
235: /**
236: * An ancillary method that creates an asset that represents a MILVAN
237: * (military container) carrying ammunition
238: */
239: protected Asset makeMilvan() {
240:
241: if (MILVAN_PROTOTYPE == null) {
242: MILVAN_PROTOTYPE = _gp.getGPFactory().getPrototype(
243: MILVAN_NSN);
244:
245: if (MILVAN_PROTOTYPE == null) {
246: _gp.getLoggingService().error(
247: "AmmoTransport: Error! Unable to get prototype for"
248: + " milvan NSN -" + MILVAN_NSN);
249: return null;
250: }
251: }
252:
253: Container milvan = (Container) _gp.getGPFactory()
254: .createInstance(MILVAN_PROTOTYPE);
255:
256: // AMMO Cargo Code
257: NewMovabilityPG movabilityPG = PropertyGroupFactory
258: .newMovabilityPG(milvan.getMovabilityPG());
259: movabilityPG.setCargoCategoryCode(AMMO_CATEGORY_CODE);
260: milvan.setMovabilityPG(movabilityPG);
261:
262: // Milvan Contents
263: NewContentsPG contentsPG = PropertyGroupFactory.newContentsPG();
264: milvan.setContentsPG(contentsPG);
265:
266: // Unique Item Identification
267: NewItemIdentificationPG itemIdentificationPG = (NewItemIdentificationPG) milvan
268: .getItemIdentificationPG();
269: String itemID = makeMilvanID();
270: itemIdentificationPG.setItemIdentification(itemID);
271: itemIdentificationPG.setNomenclature("Milvan");
272: itemIdentificationPG.setAlternateItemIdentification(itemID);
273: milvan.setItemIdentificationPG(itemIdentificationPG);
274:
275: return milvan;
276: }
277:
278: protected String makeMilvanID() {
279: return new String("Milvan" + getCounter());
280: }
281:
282: private static synchronized long getCounter() {
283: return COUNTER++;
284: }
285:
286: }
|