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: package org.cougaar.planning.ldm.plan;
028:
029: import org.cougaar.util.LRUCache;
030:
031: import java.text.SimpleDateFormat;
032: import java.util.Date;
033: import java.util.Map;
034: import java.util.HashMap;
035: import java.util.BitSet;
036:
037: /** An AspectValue implementation which stores a time.
038: */
039:
040: public abstract class TimeAspectValue extends AspectValue {
041: // 0 = LRU
042: // 1 = hashmap
043: private static final int CACHE_STYLE_DEFAULT = 0;
044: private static final int CACHE_STYLE = Integer.getInteger(
045: "org.cougaar.planning.ldm.plan.timeAV.cacheStyle",
046: CACHE_STYLE_DEFAULT).intValue();
047:
048: private static final int CACHE_SIZE_DEFAULT = 256;
049: private static final int CACHE_SIZE = Integer.getInteger(
050: "org.cougaar.planning.ldm.plan.timeAV.cacheSize",
051: CACHE_SIZE_DEFAULT).intValue();
052:
053: // blank final!
054: protected final long value;
055:
056: protected TimeAspectValue(long l) {
057: this .value = l;
058: }
059:
060: public final double doubleValue() {
061: return (double) value;
062: }
063:
064: public final long longValue() {
065: return value;
066: }
067:
068: public final float floatValue() {
069: return (float) value;
070: }
071:
072: public final int intValue() {
073: return (int) value;
074: }
075:
076: public Date dateValue() {
077: return new Date(longValue());
078: }
079:
080: public long timeValue() {
081: return longValue();
082: }
083:
084: // ignore type because they shouldn't coexist anyway
085: public boolean equals(Object v) {
086: return (v instanceof TimeAspectValue)
087: && ((TimeAspectValue) v).value == value;
088: }
089:
090: public final int hashCode() {
091: return (int) value;
092: }
093:
094: public static AspectValue create(int type, Object o) {
095: long l;
096: if (o instanceof Date) {
097: l = ((Date) o).getTime();
098: } else if (o instanceof Number) {
099: l = ((Number) o).longValue();
100: } else {
101: throw new IllegalArgumentException(
102: "Cannot create a TimeAspectValue from " + o);
103: }
104:
105: return create(type, l);
106: }
107:
108: // not thrilled with this...
109: private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
110: "MM/dd/yy HH:mm:ss.SSS z");
111: private static Date formatDate = new Date();
112:
113: public String toString() {
114: synchronized (formatDate) {
115: formatDate.setTime(longValue());
116: return dateTimeFormat.format(formatDate) + "[" + getType()
117: + "]";
118: }
119: }
120:
121: //
122: // unoptimized TAV
123: //
124: public static class TypedTimeAspectValue extends TimeAspectValue {
125: private int type;
126:
127: protected TypedTimeAspectValue(int type, long value) {
128: super (value);
129: this .type = type;
130: }
131:
132: public final int getType() {
133: return type;
134: }
135: }
136:
137: //
138: // optimized time AVs
139: //
140:
141: /** Base class for optimized time-based Aspect Values
142: **/
143:
144: public static abstract class OptimizedTimeAspectValue extends
145: TimeAspectValue {
146: protected OptimizedTimeAspectValue(long value) {
147: super (value);
148: }
149:
150: // always go via the factories on reads
151: private Object readResolve() {
152: return create(getType(), value);
153: }
154:
155: }
156:
157: public static final class StartTAV extends OptimizedTimeAspectValue {
158: public final int getType() {
159: return AspectType.START_TIME;
160: }
161:
162: public StartTAV(long l) {
163: super (l);
164: }
165: }
166:
167: public static final class EndTAV extends OptimizedTimeAspectValue {
168: public final int getType() {
169: return AspectType.END_TIME;
170: }
171:
172: public EndTAV(long l) {
173: super (l);
174: }
175: }
176:
177: public static final class DurationTAV extends
178: OptimizedTimeAspectValue {
179: public final int getType() {
180: return AspectType.DURATION;
181: }
182:
183: public DurationTAV(long l) {
184: super (l);
185: }
186: }
187:
188: public static final class IntervalTAV extends
189: OptimizedTimeAspectValue {
190: public final int getType() {
191: return AspectType.INTERVAL;
192: }
193:
194: public IntervalTAV(long l) {
195: super (l);
196: }
197: }
198:
199: public static final class PodTAV extends OptimizedTimeAspectValue {
200: public final int getType() {
201: return AspectType.POD_DATE;
202: }
203:
204: public PodTAV(long l) {
205: super (l);
206: }
207: }
208:
209: private static abstract class OTF {
210: /** actually create a new instance **/
211: public abstract AspectValue create(long l);
212:
213: private final Map cache;
214:
215: public OTF() {
216: if (CACHE_STYLE == 1) {
217: cache = new HashMap(CACHE_SIZE);
218: } else {
219: cache = new LRUCache(CACHE_SIZE);
220: }
221: }
222:
223: /** Find or create an aspect value **/
224: public AspectValue get(long l) {
225: // this is nominally faster than using AVs as keys
226: Long key = new Long(l);
227: synchronized (cache) {
228: AspectValue oav = (AspectValue) cache.get(key);
229: if (oav != null) {
230: return oav;
231: } else {
232: AspectValue av = create(l);
233: cache.put(key, av);
234: return av;
235: }
236: }
237: }
238: }
239:
240: private static final int OTFL = AspectType.N_CORE_ASPECTS;
241: private static final OTF[] factory = new OTF[OTFL];
242:
243: static {
244: factory[AspectType.START_TIME] = new OTF() {
245: public AspectValue create(long l) {
246: return new StartTAV(l);
247: }
248: };
249: factory[AspectType.END_TIME] = new OTF() {
250: public AspectValue create(long l) {
251: return new EndTAV(l);
252: }
253: };
254: factory[AspectType.DURATION] = new OTF() {
255: public AspectValue create(long l) {
256: return new DurationTAV(l);
257: }
258: };
259: factory[AspectType.INTERVAL] = new OTF() {
260: public AspectValue create(long l) {
261: return new IntervalTAV(l);
262: }
263: };
264: factory[AspectType.POD_DATE] = new OTF() {
265: public AspectValue create(long l) {
266: return new PodTAV(l);
267: }
268: };
269: }
270:
271: public static AspectValue create(int type, long value) {
272: if (type >= 0 && type < OTFL) {
273: OTF f = factory[type];
274: if (f != null) {
275: return f.get(value);
276: }
277: }
278: return new TypedTimeAspectValue(type, value);
279: }
280:
281: // current tested times on my machine are:
282: // secs/ (128 invokes)
283: // 0.011657 create(t,v) without using factory
284: // 0.063640 create(t,v) with factory (including LRU lookup) (5.46x)
285: // 0.035438 create(t,v) with factory (using hashmap) (3.04x)
286: }
|