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:
027: /** The Oplan is a LDM Object that articulates operation plan
028: * information to clusters. The Oplan object includes items such as
029: * time phasing, priority, and cday information along with an oplan ID
030: * and references to other oplan objects. To initially create the
031: * Oplan object, the OplanPlugin loads the specified oplan.xml file,
032: * parses the oplan file for operational information and publishes the
033: * Oplan object to the Log Plan. The Oplan is initially created in the
034: * J3 (Joint Operational Officer) cluster and then is transferred to
035: * other clusters by the Propagation Plugin. Subordinate clusters can
036: * subscribe to changes in the Oplan in order to retrieve oplan
037: * information and to react to changes accordingly. Subordinate
038: * clusters should not modify (set) ForcePacakge information.
039: *
040: *
041: **/package org.cougaar.glm.ldm.oplan;
042:
043: import java.beans.PropertyChangeListener;
044: import java.beans.PropertyChangeSupport;
045: import java.io.Serializable;
046: import java.util.Collection;
047: import java.util.Date;
048: import java.util.Enumeration;
049: import java.util.Iterator;
050: import java.util.Vector;
051:
052: import org.cougaar.core.util.OwnedUniqueObject;
053: import org.cougaar.core.util.UID;
054: import org.cougaar.core.util.UniqueObject;
055: import org.cougaar.planning.ldm.plan.Transferable;
056:
057: /**
058: * Oplan
059: **/
060: public class Oplan extends OwnedUniqueObject implements Transferable,
061: Serializable, Cloneable, UniqueObject {
062:
063: private String oplanID;
064: private String opName;
065: private String priority;
066: private Date cDay;
067: private Date endDay; // End day of oplan
068: private String xmlfilename_;
069: private double version = 1.0;
070:
071: private String theaterID;
072: private String terrainType;
073: private String season;
074: private String enemyForceType;
075: private boolean hnsPOL;
076: private String hnsPOLCap;
077: private String hnsWaterCap;
078: private boolean hnsWater;
079: private Vector pods = new Vector();
080: private Vector dfspVector = new Vector();
081:
082: // The max stage currently active
083: private int maxActiveStage = -1;
084: // The minimum stage where we become active
085: private int minRequiredStage = 0;
086:
087: // Priority values
088: public static final String HIGH = "High";
089: public static final String MEDIUM = "Medium";
090: public static final String LOW = "Low";
091:
092: // Default oplan duration
093: public static final long DEFAULT_OPLAN_DURATION = 180 * 86400000L;// 180 days
094: public static final long INFER_END_DAY_FUDGE = 30 * 86400000L;// 30 days
095:
096: // Theater values
097: public static final String SOUTH_WEST_ASIA = "SWA";
098:
099: // Terrain values
100: public static final String DESERT = "Desert";
101:
102: // Enemy values
103: public static final String REGULAR = "Regular Forces";
104:
105: // Season values
106: public static final String SPRING = "Spring";
107: public static final String SUMMER = "Summer";
108: public static final String AUTUMN = "Autumn";
109: public static final String FALL = "Autumn";
110: public static final String WINTER = "Winter";
111:
112: public static final String DEFAULT_FILE_NAME = "oplan.xml";
113:
114: /**
115: * Constructor for the Oplan object.
116: *
117: */
118: public Oplan() {
119: // empty oplan
120: }// Oplan
121:
122: /**
123: * Constructor for the Oplan object. This should only be used by
124: * the OPlanPlugin.
125: * @param xmlfilename Name of the oplan xml file to be parsed.
126: *
127: */
128: public Oplan(String xmlfilename) {
129: setXMLFileName(xmlfilename);
130: /*
131: System.out.println("<<<OPlanPlugin>>> The XML file name is: "
132: + getXMLFileName() );
133: */
134: } //Oplan
135:
136: /**
137: * Constructor for the Oplan object. This should only be used by
138: * the OPlanPlugin.
139: *
140: */
141: public Oplan(UID uid, String oplanID, String opName,
142: String priority, Date cDay) {
143: this (uid, oplanID, opName, priority, cDay, null);
144: }
145:
146: public Oplan(UID uid, String oplanID, String opName,
147: String priority, Date cDay, Date endDay) {
148: setUID(uid);
149: this .oplanID = unique(oplanID);
150: this .opName = unique(opName);
151: this .priority = unique(priority);
152: this .cDay = cDay;
153: if (endDay == null) {
154: this .endDay = getDefaultEndDay();
155: } else {
156: this .endDay = endDay;
157: }
158: }//Oplan
159:
160: /**
161: * Constructor for the Oplan object. This should only be used by
162: * the OPlanPlugin.
163: * @param xmlfilename Name of the oplan xml file to be parsed.
164: *
165: */
166: public Oplan(String xmlfilename, UID uid, String oplanID,
167: String opName, String priority, Date cDay) {
168: this (xmlfilename, uid, oplanID, opName, priority, cDay, null);
169: }
170:
171: public Oplan(String xmlfilename, UID uid, String oplanID,
172: String opName, String priority, Date cDay, Date endDay) {
173: this (uid, oplanID, opName, priority, cDay, endDay);
174: setXMLFileName(xmlfilename);
175: }//Oplan
176:
177: // pods
178: public void addPOD(POD pod) {
179: pods.addElement(pod);
180: }//setAPOE
181:
182: Vector getPODsV() {
183: return pods;
184: }
185:
186: public Enumeration getPODs() {
187: return pods.elements();
188: }// getPOD
189:
190: public POD[] getPODArray() {
191: POD[] tmp = new POD[pods.size()];
192: return (POD[]) pods.toArray(tmp);
193: }//getDFSP
194:
195: /**
196: * Sets the theaterID
197: * @param theaterID See constants above for valid values.
198: */
199: public void setTheaterID(String theaterID) {
200: this .theaterID = unique(theaterID);
201: }
202:
203: /**
204: * Sets the terraintype
205: * @param terrainType See constants above for valid values.
206: */
207: public void setTerrainType(String terrainType) {
208: this .terrainType = unique(terrainType);
209: }
210:
211: /**
212: * Sets the season
213: * @param season See constants above for valid values.
214: */
215: public void setSeason(String season) {
216: this .season = unique(season);
217: }
218:
219: /**
220: * Sets the enemyForceType
221: * @param enemyForceType See constants above for valid values.
222: */
223: public void setEnemyForceType(String enemyForceType) {
224: this .enemyForceType = unique(enemyForceType);
225: }
226:
227: public void setHNSPOL(boolean hnsPOL) {
228: this .hnsPOL = hnsPOL;
229: }
230:
231: public void setHNSPOLCapacity(String hnsPOLCap) {
232: this .hnsPOLCap = unique(hnsPOLCap);
233: }
234:
235: public void setHNSForWater(boolean hnsWater) {
236: this .hnsWater = hnsWater;
237: }
238:
239: public void setHNSWaterCapability(String hnsWaterCap) {
240: this .hnsWaterCap = unique(hnsWaterCap);
241: }
242:
243: public void addDFSP(DFSP dfsp) {
244: dfspVector.addElement(dfsp);
245: }//addDFSP
246:
247: Vector getDFSPsV() {
248: return dfspVector;
249: }
250:
251: public Enumeration getDFSPs() {
252: return dfspVector.elements();
253: }//getDFSP
254:
255: public DFSP[] getDFSPArray() {
256: DFSP[] tmp = new DFSP[dfspVector.size()];
257: return (DFSP[]) dfspVector.toArray(tmp);
258: }//getDFSP
259:
260: public String getTheaterID() {
261: return (theaterID);
262: }
263:
264: public String getTerrainType() {
265: return (terrainType);
266: }
267:
268: public String getSeason() {
269: return (season);
270: }
271:
272: public String getEnemyForceType() {
273: return (enemyForceType);
274: }
275:
276: public boolean getHNSPOL() {
277: return (hnsPOL);
278: }
279:
280: public String getHNSPOLCapacity() {
281: return (hnsPOLCap);
282: }
283:
284: public boolean getHNSForWater() {
285: return (hnsWater);
286: }
287:
288: public String getHNSWaterCapability()
289:
290: {
291: return (hnsWaterCap);
292: }
293:
294: /**
295: * Sets the oplan xml filename to be parsed.
296: * @param name Name of the oplan xml file to be parsed.
297: *
298: */
299: public void setXMLFileName(String name) {
300: if (name == null)
301: this .xmlfilename_ = DEFAULT_FILE_NAME;
302: else
303: this .xmlfilename_ = unique(name);
304: }
305:
306: /**
307: * Gets the oplan xml filename to be parsed.
308: * @return The name of the most recently parsed oplan xml file.
309: *
310: */
311: public String getXMLFileName() {
312: return this .xmlfilename_;
313: }
314:
315: /**
316: * Sets the oplan ID. This should not be called by any
317: * subordinate clusters.
318: * @param oplanID The id of the Oplan.
319: */
320: public void setOplanId(String oplanID) {
321: this .oplanID = unique(oplanID);
322: }//setOplanId
323:
324: /**
325: * Sets the oplan UID. This should not be called by any
326: * subordinate clusters.
327: * @param uid The unique id of the Oplan.
328: */
329: public void setOplanUID(UID uid) {
330: setUID(uid);
331: }//setOplanUID
332:
333: /**
334: * Sets the operation name of the oplan. This should
335: * not be called by any subordinate clusters.
336: * @param opName The operation name.
337: *
338: */
339: public void setOperationName(String opName) {
340: this .opName = unique(opName);
341: }// setOperationName
342:
343: /**
344: * Sets the priority of the oplan. This should
345: * not be called by any subordinate clusters. Static
346: * final values will be created for the priority in
347: * the near future.
348: * @param priority The priority.
349: *
350: */
351: public void setPriority(String priority) {
352: this .priority = unique(priority);
353: }//setPriority
354:
355: /**
356: * Sets the CDay of the oplan. This should
357: * not be called by any subordinate clusters.
358: * @param cDay the CDay. Should be in the format mm/dd/yyyy
359: */
360: public void setCday(Date cDay) {
361: this .cDay = cDay;
362: }// setCday
363:
364: /**
365: * Sets the end day of the oplan. This should
366: * not be called by any subordinate clusters.
367: * @param endDay the endDay. Should be in the format mm/dd/yyyy
368: */
369: public void setEndDay(Date endDay) {
370: this .endDay = endDay;
371: }// setCday
372:
373: /**
374: * Infer the end day from all the contributing elements
375: **/
376: public void inferEndDay(Collection oplanContributors) {
377: long maxET = Long.MIN_VALUE;
378: for (Iterator iterator = oplanContributors.iterator(); iterator
379: .hasNext();) {
380: Object e = iterator.next();
381: if (e instanceof OplanContributor) {
382: OplanContributor contrib = (OplanContributor) e;
383: TimeSpan span = contrib.getTimeSpan();
384: if (span != null) {
385: long et = span.getEndTime();
386: if (et != span.MAX_VALUE && et > maxET)
387: maxET = et;
388: }
389: }
390: }
391:
392: if (maxET != Long.MIN_VALUE) {
393: setEndDay(new Date(maxET + INFER_END_DAY_FUDGE));
394: } else {
395: setEndDay(getDefaultEndDay());
396: }
397: }
398:
399: public void incrementVersion() {
400: version = version + 0.00001;
401: }// incrementVersion
402:
403: public double getVersion() {
404: return (version);
405: }//getVersion;
406:
407: /**
408: * Gets the oplanID for the given OPlan.
409: * @return oplanID The unique ID for the Oplan.
410: */
411: public String getOplanId() {
412: return oplanID;
413: }//getOplanId
414:
415: /**
416: * Gets the oplanID for the given OPlan.
417: * @return oplanID The unique ID for the Oplan.
418: */
419: public UID getUID() {
420: return super .getUID();
421: }//getUID
422:
423: /**
424: * Gets the operation name for the Oplan.
425: * @return oplanName The operation name for the Oplan.
426: */
427: public String getOperationName() {
428: return (opName);
429: }// getOperationName
430:
431: /**
432: * Gets the priority for the OPlan.
433: * @return priority The priority for the Oplan. The types
434: * returned are declared as
435: */
436: public String getPriority() {
437: return (priority);
438: }// getPriority
439:
440: /**
441: * Gets the current Cday being used by the Oplan
442: * @return Date The current cDay
443: */
444: public Date getCday() {
445: return (cDay);
446: }// getCday
447:
448: /**
449: * Gets the current end day being used by the Oplan
450: * @return Date The current endDay
451: */
452: public Date getEndDay() {
453: return (endDay);
454: }// getEndDay
455:
456: private Date getDefaultEndDay() {
457: return new Date(cDay.getTime() + DEFAULT_OPLAN_DURATION);
458: }
459:
460: /**
461: * Returns a copy of the Oplan.
462: * @return Object A copy of the Oplan.
463: */
464: public Object clone() {
465: Oplan newOplan = new Oplan(getUID(), oplanID, opName, priority,
466: cDay, endDay);
467: newOplan.setOwner(getOwner());
468: newOplan.setTheaterID(theaterID);
469: newOplan.setTerrainType(terrainType);
470: newOplan.setSeason(season);
471: newOplan.setEnemyForceType(enemyForceType);
472: newOplan.setHNSPOL(hnsPOL);
473: newOplan.setHNSPOLCapacity(hnsPOLCap);
474: newOplan.setHNSWaterCapability(hnsWaterCap);
475: newOplan.setHNSForWater(hnsWater);
476: copyVectorInto(getPODsV(), newOplan.getPODsV());
477: copyVectorInto(getDFSPsV(), newOplan.getDFSPsV());
478: newOplan.setXMLFileName(xmlfilename_);
479: newOplan.setMaxActiveStage(maxActiveStage);
480: newOplan.setMinRequiredStage(minRequiredStage);
481: return newOplan;
482: }//clone
483:
484: // also clones the next level down or we end up sharing structure
485: // after all that!
486: private void copyVectorInto(Vector v, Vector nv) {
487: nv.clear();
488: nv.ensureCapacity(v.size());
489: for (Enumeration e = v.elements(); e.hasMoreElements();) {
490: nv.addElement(((Transferable) e.nextElement()).clone());
491: }
492: }
493:
494: /**
495: * Determines if the given oplan is the same as
496: * the current oplan.
497: * @param other Oplan to compare it to.
498: * @return boolean true - same
499: * false - not same
500: */
501: public boolean same(Transferable other) {
502: if (!(other instanceof Oplan))
503: return false;
504: Oplan otherOplan = (Oplan) other;
505: return getUID().equals(otherOplan.getUID());
506: }//same
507:
508: /**
509: * Determines if the given oplan is the same as
510: * the current oplan.
511: * @param o Oplan to compare it to.
512: * @return boolean true - same
513: * false - not same
514: */
515: public boolean equals(Object o) {
516: if (o instanceof Oplan) {
517: Oplan oplan = (Oplan) o;
518:
519: return matches(getOplanId(), oplan.getOplanId())
520: && matches(getOperationName(), oplan
521: .getOperationName())
522: && matches(getPriority(), oplan.getPriority())
523: && matches(getCday(), oplan.getCday())
524: && matches(getEndDay(), oplan.getEndDay())
525: && matches(getTheaterID(), oplan.getTheaterID())
526: && matches(getTerrainType(), oplan.getTerrainType())
527: && matches(getSeason(), oplan.getSeason())
528: && matches(getEnemyForceType(), oplan
529: .getEnemyForceType())
530: && (getHNSPOL() == oplan.getHNSPOL())
531: && matches(getHNSPOLCapacity(), oplan
532: .getHNSPOLCapacity())
533: && (getHNSForWater() == oplan.getHNSForWater())
534: && matches(getHNSWaterCapability(), oplan
535: .getHNSWaterCapability())
536: && matches(getPODsV(), oplan.getPODsV())
537: && matches(getDFSPsV(), oplan.getDFSPsV())
538: && getMinRequiredStage() == oplan
539: .getMinRequiredStage()
540: && getMaxActiveStage() == oplan.getMaxActiveStage();
541: } else
542: return false;
543: }
544:
545: /**
546: * This methods sets the Oplan contents to all
547: * of the values specified in the given object.
548: * @param other oplan object to set contents to.
549: */
550: public void setAll(Transferable other) {
551: if (!(other instanceof Oplan))
552: throw new IllegalArgumentException("Parameter not Oplan");
553:
554: // assume oplanID and opName don't change
555: Oplan otherOplan = (Oplan) other;
556: setUID(otherOplan.getUID());
557: setOwner(otherOplan.getOwner());
558: theaterID = otherOplan.getTheaterID();
559: terrainType = otherOplan.getTerrainType();
560: season = otherOplan.getSeason();
561: enemyForceType = otherOplan.getEnemyForceType();
562: hnsPOL = otherOplan.getHNSPOL();
563: hnsPOLCap = otherOplan.getHNSPOLCapacity();
564: hnsWaterCap = otherOplan.getHNSWaterCapability();
565: hnsWater = otherOplan.getHNSForWater();
566:
567: pods = new Vector();
568: dfspVector = new Vector();
569:
570: Enumeration en = otherOplan.getDFSPs();
571: while (en.hasMoreElements())
572: dfspVector.addElement(en.nextElement());
573:
574: en = otherOplan.getPODs();
575: while (en.hasMoreElements())
576: pods.addElement(en.nextElement());
577:
578: priority = otherOplan.getPriority();
579: cDay = otherOplan.getCday();
580: endDay = otherOplan.getEndDay();
581: xmlfilename_ = otherOplan.getXMLFileName();
582: maxActiveStage = otherOplan.maxActiveStage;
583: minRequiredStage = otherOplan.minRequiredStage;
584: }// setAll
585:
586: public boolean isActive() {
587: return maxActiveStage >= minRequiredStage;
588: }
589:
590: public void setMaxActiveStage(int newMax) {
591: maxActiveStage = newMax;
592: }
593:
594: public int getMaxActiveStage() {
595: return maxActiveStage;
596: }
597:
598: public void setMinRequiredStage(int newMin) {
599: minRequiredStage = newMin;
600: }
601:
602: public int getMinRequiredStage() {
603: return minRequiredStage;
604: }
605:
606: //dummy PropertyChangeSupport for the Jess Interpreter.
607: protected transient PropertyChangeSupport pcs = new PropertyChangeSupport(
608: this );
609:
610: public void addPropertyChangeListener(PropertyChangeListener pcl) {
611: pcs.addPropertyChangeListener(pcl);
612: }
613:
614: public void removePropertyChangeListener(PropertyChangeListener pcl) {
615: pcs.removePropertyChangeListener(pcl);
616: }
617:
618: /** @return A string Containing the UID and operation name of the Oplan */
619: public String toString() {
620: return getUID().toString() + " " + opName;
621: }
622:
623: public static final String unique(String s) {
624: return (s == null) ? null : (s.intern());
625: }
626:
627: private static boolean matches(Object a, Object b) {
628: if (!(a instanceof Enumeration) || !(b instanceof Enumeration)) {
629: return (a == null) ? (b == null) : (a.equals(b));
630: } else {
631: Enumeration aEnum = (Enumeration) a;
632: Enumeration bEnum = (Enumeration) b;
633:
634: while (aEnum.hasMoreElements() && bEnum.hasMoreElements()) {
635: if (!matches(aEnum.nextElement(), bEnum.nextElement())) {
636: return false;
637: }
638: }
639:
640: return (!aEnum.hasMoreElements())
641: && (!bEnum.hasMoreElements());
642: }
643: }
644: }// OPlan
|