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 java.io.IOException;
030: import java.io.ObjectInputStream;
031: import java.io.Serializable;
032: import java.util.ArrayList;
033: import java.util.Arrays;
034: import java.util.Collection;
035: import java.util.Date;
036: import java.util.Enumeration;
037: import java.util.Iterator;
038: import java.util.List;
039:
040: /**
041: * The "result" of allocating a task.
042: **/
043:
044: public class AllocationResult implements AspectType,
045: AuxiliaryQueryType, Serializable, Cloneable {
046:
047: // Final and cloned, so these can be accessed outside a lock:
048: private final boolean isSuccess;
049: private final float confrating;
050: private final AspectValue[] avResults;
051: private final ArrayList phasedavrs; // A List of AspectValue[], null if not phased
052:
053: // Mutable auxqueries array, typically null.
054: // Locked by "avResults", since it's non-null.
055: // We make this copy-on-write, to reduce cloning and locking
056: // overhead, since we expect far more readers than writers.
057: private String[] auxqueries;
058:
059: // Mutable memoized variables.
060: // Locked by "avResults", since it's non-null.
061: //
062: // Must call "clearMemos()" at end of "readObject", since
063: // transient initializers are not called in deserialization.
064: // To make things consistent, we use an explicit "clearMemos()"
065: // at the end of all constructors.
066: private transient int[] _ats;// Array of aspect types
067: private transient int _lasttype; // Type of last type to index conversion
068: private transient int _lastindex; // Index of last type to index conversion
069:
070: /** Constructor that takes a result in the form of AspectValues (NON-PHASED).
071: * Subclasses of AspectValue, such as TypedQuantityAspectValue are allowed.
072: * @param rating The confidence rating of this result.
073: * @param success Whether the allocationresult violated any preferences.
074: * @param aspectvalues The AspectValues(can be aspectvalue subclasses) that represent the results.
075: * @note Prior to Cougaar 10.0, there was a similar constructor which took an int[] and double[] instead of
076: * the current AspectValue[]. This change is required because most ApectValue types
077: * are not longer represented by int/double pairs. This constructor may be made
078: * private at some point in the future.
079: */
080: public AllocationResult(double rating, boolean success,
081: AspectValue[] aspectvalues) {
082: isSuccess = success;
083: confrating = (float) rating;
084: avResults = cloneAndCheckAVV(aspectvalues);
085: phasedavrs = null;
086: clearMemos();
087: }
088:
089: /** Factory that takes a result in the form of AspectValues (NON-PHASED).
090: * Subclasses of AspectValue, such as TypedQuantityAspectValue are allowed.
091: * @param rating The confidence rating of this result.
092: * @param success Whether the allocationresult violated any preferences.
093: * @param avs The AspectValues(can be aspectvalue subclasses) that represent the results.
094: */
095: public static AllocationResult newAllocationResult(double rating,
096: boolean success, AspectValue[] avs) {
097: return new AllocationResult(rating, success, avs);
098: }
099:
100: /** @deprecated Use #AllocationResult(double,boolean,AspectValue[]) instead because
101: * AspectValues are not all describable by double values.
102: **/
103: public AllocationResult(double rating, boolean success, int[] keys,
104: double[] values) {
105: this (rating, success, convertToAVA(keys, values));
106: }
107:
108: /** Simple Constructor for a PHASED result
109: * @param rating The confidence rating of this result.
110: * @param success Whether the allocationresult violated any preferences.
111: * @param rollupavs The Summary (or rolled up) AspectValues that represent the results.
112: * @param allresults An Enumeration of either AspectValue[]s or Collection<AspectValue>s.
113: * @note Prior to Cougaar 10.0, this constructor took an int[] and double[] instead of
114: * the current AspectValue[]. This change is required because most ApectValue types
115: * are not longer represented by int/double pairs.
116: * @deprecated Use #AllocationResult(double, boolean, AspectValue[], Collection) instead.
117: */
118: public AllocationResult(double rating, boolean success,
119: AspectValue[] rollupavs, Enumeration allresults) {
120: isSuccess = success;
121: confrating = (float) rating;
122: avResults = cloneAndCheckAVV(rollupavs);
123: phasedavrs = copyPhasedResults(allresults);
124: clearMemos();
125: }
126:
127: /** @deprecated Use #AllocationResult(double,boolean,AspectValue[],Collection) instead because
128: * AspectValues are not all describable by double values.
129: **/
130: public AllocationResult(double rating, boolean success, int[] keys,
131: double[] values, Enumeration allresults) {
132: this (rating, success, convertToAVA(keys, values), allresults);
133: }
134:
135: /** Constructor that takes a PHASED result in the form of AspectValues.
136: * Subclasses of AspectValue, such as TypedQuantityAspectValue are allowed.
137: * @param rating The confidence rating of this result.
138: * @param success Whether the allocationresult violated any preferences.
139: * @param rollupavs The Summary (or rolled up) AspectValues that represent the results.
140: * @param phasedresults A Collections of the phased results. The Collection should contain
141: * one Collection or AspectValue[] of AspectValues for each phase of the results.
142: * @note The associated factory is preferred as the constructor may be made private in
143: * a future version.
144: */
145: public AllocationResult(double rating, boolean success,
146: AspectValue[] rollupavs, Collection phasedresults) {
147: isSuccess = success;
148: confrating = (float) rating;
149: avResults = cloneAndCheckAVV(rollupavs);
150: phasedavrs = copyPhasedResults(phasedresults);
151: clearMemos();
152: }
153:
154: /** AllocationResult factory that takes a PHASED result in the form of AspectValues.
155: * Subclasses of AspectValue, such as TypedQuantityAspectValue are allowed.
156: * @param rating The confidence rating of this result.
157: * @param success Whether the allocationresult violated any preferences.
158: * @param rollupavs The Summary (or rolled up) AspectValues that represent the results.
159: * @param phasedresults A Collections of the phased results. The Collection should contain
160: * one Collection or AspectValue[] of AspectValues for each phase of the results.
161: */
162: public static AllocationResult newAllocationResult(double rating,
163: boolean success, AspectValue[] rollupavs,
164: Collection phasedresults) {
165: return new AllocationResult(rating, success, rollupavs,
166: phasedresults);
167: }
168:
169: /**
170: * Construct a merged AllocationResult containing AspectValues from
171: * two AllocationResults. If both arguments have the same aspects,
172: * the values from the first (dominant) result are used. The result
173: * is never phased.
174: * @note The associated factory is preferred as the constructor may be made private in
175: * a future version.
176: **/
177: public AllocationResult(AllocationResult ar1, AllocationResult ar2) {
178: assert isAVVValid(ar1.avResults);
179: assert isAVVValid(ar2.avResults);
180:
181: int len1 = ar1.avResults.length;
182: int len2 = ar2.avResults.length;
183: List mergedavs = new ArrayList(len1 + len2);
184: outer: for (int i = 0; i < len2; i++) {
185: AspectValue av2 = ar2.avResults[i];
186: int aspectType = av2.getAspectType();
187: for (int j = 0; j < len1; j++) {
188: if (aspectType == ar1.avResults[j].getAspectType()) {
189: continue outer; // Already have this AspectType
190: }
191: }
192: mergedavs.add(av2);
193: }
194: mergedavs.addAll(Arrays.asList(ar1.avResults));
195: int nAspects = mergedavs.size();
196: avResults = (AspectValue[]) mergedavs
197: .toArray(new AspectValue[nAspects]);
198: confrating = (ar1.confrating * len1 + ar2.confrating
199: * (nAspects - len1))
200: / nAspects;
201: phasedavrs = null;
202:
203: String[] ar1_auxqueries = ar1.currentAuxQueries();
204: boolean is_shared = false;
205: if (ar1_auxqueries != null) {
206: auxqueries = ar1_auxqueries;
207: is_shared = true;
208: }
209: String[] ar2_auxqueries = ar2.currentAuxQueries();
210: if (ar2_auxqueries != null) {
211: if (auxqueries == null) {
212: auxqueries = new String[AQTYPE_COUNT];
213: }
214: for (int i = 0; i < AQTYPE_COUNT; i++) {
215: if (auxqueries[i] == null && ar2_auxqueries[i] != null) {
216: if (is_shared) {
217: // copy-on-write, so we must clone ar1_auxqueries
218: // before modifying it
219: auxqueries = (String[]) auxqueries.clone();
220: is_shared = false;
221: }
222: auxqueries[i] = ar2_auxqueries[i];
223: }
224: }
225: }
226: isSuccess = ar1.isSuccess() || ar2.isSuccess();
227: clearMemos();
228: }
229:
230: /**
231: * Construct a merged AllocationResult containing AspectValues from
232: * two AllocationResults. If both arguments have the same aspects,
233: * the values from the first (dominant) result are used. The result
234: * is never phased.
235: **/
236: public static AllocationResult newAllocationResult(
237: AllocationResult ar1, AllocationResult ar2) {
238: return new AllocationResult(ar1, ar2);
239: }
240:
241: public Object clone() {
242: return new AllocationResult(this );
243: }
244:
245: private AllocationResult(AllocationResult ar) {
246: confrating = ar.confrating;
247: isSuccess = ar.isSuccess;
248: avResults = (AspectValue[]) ar.avResults.clone();
249: if (ar.phasedavrs == null) {
250: phasedavrs = null;
251: } else {
252: phasedavrs = new ArrayList(ar.phasedavrs.size());
253: for (Iterator i = ar.phasedavrs.iterator(); i.hasNext();) {
254: AspectValue[] av = (AspectValue[]) i.next();
255: phasedavrs.add(av.clone());
256: }
257: }
258: auxqueries = ar.currentAuxQueries();
259: clearMemos();
260: }
261:
262: private int getIndexOfType(int aspectType) {
263: assert Thread.holdsLock(avResults);
264: if (aspectType == _lasttype)
265: return _lastindex; // Use memoized value
266: for (int i = 0; i < avResults.length; i++) {
267: if (avResults[i].getAspectType() == aspectType)
268: return i;
269: }
270: return -1;
271: }
272:
273: //AllocationResult interface implementation.
274:
275: /** Get the result with respect to a given AspectType.
276: * If the AllocationResult is phased, this method will return
277: * the summary value of the given AspectType.
278: * <P> Warning!!! Not all AspectValues can be simply represented as
279: * a double. Use of this method with such AspectValues is undefined.
280: * @param aspectType
281: * @return double The result of a given dimension. For example,
282: * getValue(AspectType.START_TIME) returns the Task start time.
283: * Note : results are not required to contain data in each dimension -
284: * check the array of defined aspecttypes or ask if a specific
285: * dimension is defined. If there is a request for a value of an
286: * undefined aspect, an IllegalArgumentException will be thrown.
287: * @see org.cougaar.planning.ldm.plan.AspectType
288: */
289: public double getValue(int aspectType) {
290: synchronized (avResults) {
291: if (_lasttype == aspectType)
292: return avResults[_lastindex].getValue(); // return memoized value
293: int i = getIndexOfType(aspectType);
294: if (i >= 0)
295: return avResults[i].getValue();
296: }
297: // didn't find it.
298: throw new IllegalArgumentException(
299: "AllocationResult.getValue(int "
300: + aspectType
301: + ") - The AspectType is not defined by this Result.");
302: }
303:
304: /** Get the AspectValue of the result with the specified type **/
305: public AspectValue getAspectValue(int aspectType) {
306: synchronized (avResults) {
307: if (_lasttype == aspectType)
308: return avResults[_lastindex];
309: int i = getIndexOfType(aspectType);
310: if (i >= 0)
311: return avResults[i];
312: }
313: // didn't find it.
314: throw new IllegalArgumentException(
315: "AllocationResult.getAspectValue(int "
316: + aspectType
317: + ") - The AspectType is not defined by this Result.");
318: }
319:
320: /** Quick check to see if one aspect is defined as opposed to
321: * looking through the AspectType array.
322: * @param aspectType The aspect you are checking
323: * @return boolean Represents whether this aspect is defined
324: * @see org.cougaar.planning.ldm.plan.AspectType
325: */
326: public boolean isDefined(int aspectType) {
327: synchronized (avResults) {
328: int i = getIndexOfType(aspectType);
329: if (i >= 0) {
330: _lasttype = aspectType;
331: _lastindex = i; // memoize lookup
332: return true;
333: }
334: }
335: return false;
336: }
337:
338: /** @return boolean Represents whether or not the allocation
339: * was a success. If any Constraints were violated by the
340: * allocation, then the isSuccess() method returns false
341: * and the Plugin that created the subtask should
342: * recognize this event. The Expander may re-expand, change the
343: * Constraints or Preferences, or indicate failure to its superior.
344: * The AspectValues of a failed allocation may be set by the Allocator
345: * with values that would be more likely to be successful.
346: * The Expander can use these new values as suggestions when
347: * resetting the Preferences
348: */
349: public boolean isSuccess() {
350: return isSuccess;
351: }
352:
353: /** @return boolean Represents whether or not the allocation
354: * result is phased.
355: */
356: public boolean isPhased() {
357: return phasedavrs != null;
358: }
359:
360: private void clearMemos() {
361: synchronized (avResults) {
362: _ats = null;
363: _lasttype = -1;
364: _lastindex = -1;
365: }
366: }
367:
368: /** A Collection of AspectTypes representative of the type and
369: * order of the aspects in each the result.
370: * @return int[] The array of AspectTypes
371: * @see org.cougaar.planning.ldm.plan.AspectType
372: */
373: public int[] getAspectTypes() {
374: synchronized (avResults) {
375: if (_ats != null)
376: return _ats;
377: _ats = new int[avResults.length];
378: for (int i = 0; i < avResults.length; i++) {
379: _ats[i] = avResults[i].getAspectType();
380: }
381: return _ats;
382: }
383: }
384:
385: /** A collection of doubles that represent the result for each
386: * AspectType. If the result is phased, the results are
387: * summarized.
388: * <P> Warning!!! Not all AspectValues can be simply represented as
389: * a double. Use of this method with such AspectValues is undefined.
390: * @return double[]
391: */
392: public double[] getResult() {
393: return convertToDouble(avResults);
394: }
395:
396: private double[] convertToDouble(AspectValue[] avs) {
397: double[] result = new double[avs.length];
398: for (int i = 0; i < avs.length; i++) {
399: result[i] = avs[i].getValue();
400: }
401: return result;
402: }
403:
404: /** A collection of AspectValues that represent the result for each
405: * preference. Note that subclasses of AspectValue such as
406: * TypedQuantityAspectValue may be used. If this was not
407: * defined through a constructor, one will be built from the result
408: * and aspecttype arrays. In this case only true AspectValue
409: * objects will be build (no subclasses of AspectValues).
410: * The AspectValues of a failed allocation may be set by the Allocator
411: * with values that would be more likely to be successful.
412: * The Expander can use these new values as suggestions when
413: * resetting the Preferences.
414: * @note Will always return a new AspectValue[]
415: **/
416: public AspectValue[] getAspectValueResults() {
417: return (AspectValue[]) avResults.clone();
418: }
419:
420: /** A collection of arrays that represents each phased result.
421: * If the result is not phased, use AllocationResult.getResult()
422: * <P> Warning!!! Not all AspectValues can be simply represented as
423: * a double. Use of this method with such AspectValues is undefined.
424: * @return Enumeration<AspectValue[]>
425: */
426: public Enumeration getPhasedResults() {
427: if (!isPhased())
428: throw new IllegalArgumentException("Not phased");
429: return new Enumeration() {
430: Iterator iter = phasedavrs.iterator();
431:
432: public boolean hasMoreElements() {
433: return iter.hasNext();
434: }
435:
436: public Object nextElement() {
437: AspectValue[] avs = (AspectValue[]) iter.next();
438: return convertToDouble(avs);
439: }
440: };
441: }
442:
443: /** A List of Lists that represent each phased result in the form
444: * of AspectValues.
445: * If the result is not phased, use getAspectValueResults()
446: * @return A List<AspectValue[]>. If the AllocationResult is not phased, will return null.
447: */
448: public List getPhasedAspectValueResults() {
449: if (phasedavrs == null) {
450: return null;
451: } else {
452: return new ArrayList(phasedavrs);
453: }
454: }
455:
456: /** @return double The confidence rating of this result. */
457: public double getConfidenceRating() {
458: return confrating;
459: }
460:
461: /** Return the String representing the auxilliary piece of data that
462: * matches the query type given in the argument.
463: * @param aqtype The AuxiliaryQueryType you want the data for.
464: * @return String The string representing the data matching the type requested
465: * Note: may return null if nothing was defined
466: * @see org.cougaar.planning.ldm.plan.AuxiliaryQueryType
467: * @throws IllegalArgumentException if the int passed in as an argument is not a defined
468: * AuxiliaryQueryType
469: **/
470: public String auxiliaryQuery(int aqtype) {
471: if ((aqtype < 0) || (aqtype > LAST_AQTYPE)) {
472: throw new IllegalArgumentException(
473: "AllocationResult.auxiliaryQuery(int) expects an int "
474: + "that is represented in org.cougaar.planning.ldm.plan.AuxiliaryQueryType");
475: }
476: synchronized (avResults) {
477: return (auxqueries == null ? null : auxqueries[aqtype]);
478: }
479: }
480:
481: //NewAllocationResult interface implementations
482:
483: /** Set a single AuxiliaryQueryType and its data (String).
484: * @param aqtype The AuxiliaryQueryType
485: * @param data The string associated with the AuxiliaryQueryType
486: * @see org.cougaar.planning.ldm.plan.AuxiliaryQueryType
487: **/
488: public void addAuxiliaryQueryInfo(int aqtype, String data) {
489: if ((aqtype < 0) || (aqtype > LAST_AQTYPE)) {
490: throw new IllegalArgumentException(
491: "AllocationResult.addAuxiliaryQueryInfo(int, String) expects an int "
492: + "that is represented in org.cougaar.planning.ldm.plan.AuxiliaryQueryType");
493: }
494: synchronized (avResults) {
495: if (auxqueries == null) {
496: auxqueries = new String[AQTYPE_COUNT];
497: } else {
498: // copy-on-write, to avoid cloning and minimize locking
499: // overheads, assuming readers far outweight writers
500: auxqueries = (String[]) auxqueries.clone();
501: }
502: auxqueries[aqtype] = data;
503: }
504: }
505:
506: /** get the current (immutable) shapshot of the auxqueries */
507: private String[] currentAuxQueries() {
508: synchronized (avResults) {
509: return auxqueries;
510: }
511: }
512:
513: /** clone the array and filteri out nulls. */
514: private static AspectValue[] cloneAndCheckAVV(
515: AspectValue[] aspectvalues) {
516: AspectValue[] ret = (AspectValue[]) aspectvalues.clone();
517: assert isAVVValid(ret);
518: // must clearMemos()
519: return ret;
520: }
521:
522: private static boolean isAVVValid(AspectValue[] av) {
523: for (int i = 0; i < av.length; i++) {
524: if (av[i] == null)
525: return false;
526: }
527: return true;
528: }
529:
530: /** copy the phased results in an Enumeration of AspectValue[] */
531: private static ArrayList copyPhasedResults(Enumeration theResults) {
532: ArrayList ret = new ArrayList();
533: while (theResults.hasMoreElements()) {
534: ret.add(convertAVO(theResults.nextElement()));
535: }
536: ret.trimToSize();
537: return ret;
538: }
539:
540: /**
541: * copy the results in a collection of AspectValue[] representing
542: * each phase of the result
543: */
544: private static ArrayList copyPhasedResults(Collection theResults) {
545: int n = theResults.size();
546: ArrayList ret = new ArrayList(n);
547: if (theResults instanceof List) {
548: List trl = (List) theResults;
549: for (int i = 0; i < n; i++) {
550: ret.add(convertAVO(trl.get(i)));
551: }
552: } else {
553: for (Iterator it = theResults.iterator(); it.hasNext();) {
554: ret.add(convertAVO(it.next()));
555: }
556: }
557: return ret;
558: }
559:
560: /** Convert an logical array of AspectValues to an actual AspectValue[], if needed **/
561: // fixes bug 1968
562: private static AspectValue[] convertAVO(Object o) {
563: if (o instanceof AspectValue[]) {
564: return (AspectValue[]) o;
565: } else if (o instanceof Collection) {
566: return (AspectValue[]) ((Collection) o)
567: .toArray(new AspectValue[((Collection) o).size()]);
568: } else {
569: throw new IllegalArgumentException(
570: "Each element of a PhaseResult must be in the form of an AspectValue[] or a Collection of AspectValues, but got: "
571: + o);
572: }
573: }
574:
575: /** checks to see if the AllocationResult is equal to this one.
576: */
577: public boolean isEqual(AllocationResult that) {
578: if (this == that)
579: return true; // quick success
580: if (that == null)
581: return false; // quick fail
582: if (!(this .isSuccess() == that.isSuccess()
583: && this .isPhased() == that.isPhased() && this
584: .getConfidenceRating() == that.getConfidenceRating())) {
585: return false;
586: }
587:
588: //check the real stuff now!
589: //check the aspect types
590: //check the summary results
591: if (!AspectValue.nearlyEquals(this .avResults, that.avResults))
592: return false;
593: // check the phased results
594: if (isPhased()) {
595: Iterator i1 = that.phasedavrs.iterator();
596: Iterator i2 = this .phasedavrs.iterator();
597: while (i1.hasNext()) {
598: if (!i2.hasNext())
599: return false;
600: if (!AspectValue.nearlyEquals(
601: (AspectValue[]) i1.next(), (AspectValue[]) i2
602: .next()))
603: return false;
604: }
605: if (i2.hasNext())
606: return false;
607: }
608:
609: // check the aux queries
610:
611: String[] taux = that.currentAuxQueries();
612: synchronized (avResults) {
613: if (auxqueries != taux) {
614: if (!Arrays.equals(taux, auxqueries))
615: return false;
616: }
617: }
618:
619: // must be equals...
620: return true;
621: }
622:
623: // added to support AllocationResultBeanInfo
624:
625: public String[] getAspectTypesAsArray() {
626: String[] ret = new String[avResults.length];
627: for (int i = 0; i < ret.length; i++)
628: ret[i] = AspectValue.aspectTypeToString(avResults[i]
629: .getAspectType());
630: return ret;
631: }
632:
633: public String getAspectTypeFromArray(int i) {
634: if (i < 0 || i >= avResults.length)
635: throw new IllegalArgumentException(
636: "AllocationResult.getAspectType(int " + i
637: + " not defined.");
638: return AspectValue.aspectTypeToString(avResults[i]
639: .getAspectType());
640: }
641:
642: public String[] getResultsAsArray() {
643: String[] resultStrings = new String[avResults.length];
644: for (int i = 0; i < resultStrings.length; i++) {
645: resultStrings[i] = getResultFromArray(i);
646: }
647: return resultStrings;
648: }
649:
650: public String getResultFromArray(int i) {
651: if (i < 0 || i >= avResults.length)
652: throw new IllegalArgumentException(
653: "AllocationResult.getAspectType(int " + i
654: + " not defined.");
655: int type = avResults[i].getAspectType();
656: double value = avResults[i].getValue();
657: if (type == AspectType.START_TIME
658: || type == AspectType.END_TIME) {
659: Date d = new Date((long) value);
660: return d.toString();
661: } else {
662: return String.valueOf(value);
663: }
664: }
665:
666: /**
667: * Return phased results.
668: * <P> Warning!!! Not all AspectValues can be simply represented as
669: * a double. Use of this method with such AspectValues is undefined.
670: * @return an array of an array of doubles
671: **/
672: public double[][] getPhasedResultsAsArray() {
673: int len = (isPhased() ? phasedavrs.size() : 0);
674: double[][] d = new double[len][];
675: for (int i = 0; i < len; i++) {
676: AspectValue[] avs = (AspectValue[]) phasedavrs.get(i);
677: d[i] = convertToDouble(avs);
678: }
679: return d;
680: }
681:
682: /**
683: * Return a particular phase of a phased result as an array of doubles.
684: * <P> Warning!!! Not all AspectValues can be simply represented as
685: * a double. Use of this method with such AspectValues is undefined.
686: * @return the i-th phase as double[]
687: **/
688: public double[] getPhasedResultsFromArray(int i) {
689: if (!isPhased())
690: return null;
691: if (i < 0 || i >= phasedavrs.size())
692: return null;
693: return convertToDouble((AspectValue[]) phasedavrs.get(i));
694: }
695:
696: private void appendAVS(StringBuffer buf, AspectValue[] avs) {
697: buf.append('[');
698: for (int i = 0; i < avs.length; i++) {
699: if (i > 0)
700: buf.append(",");
701: buf.append(avs[i]);
702: }
703: buf.append(']');
704: }
705:
706: public String toString() {
707: StringBuffer buf = new StringBuffer();
708: buf.append("AllocationResult[isSuccess=");
709: buf.append(isSuccess);
710: buf.append(", confrating=");
711: buf.append(confrating);
712: appendAVS(buf, avResults);
713: if (isPhased()) {
714: for (int i = 0, n = phasedavrs.size(); i < n; i++) {
715: buf.append("Phase ");
716: buf.append(i);
717: buf.append("=");
718: appendAVS(buf, (AspectValue[]) phasedavrs.get(i));
719: }
720: }
721: buf.append("]");
722: return buf.toString();
723: }
724:
725: /*
726: * The AspectValues of a failed allocation may be set by the Allocator
727: * with values that would be more likely to be successful.
728: * The Expander can use these new values as suggestions when
729: * resetting the Preferences. This method tells which AspectValues
730: * have been changed or added by the Allocator.
731: *
732: * @param prefs the preference from the task corresponding to this allocation
733: * @return the aspect values in the allocation that are different
734: * from the the preference.
735: */
736: public AspectValue[] difference(Preference[] prefs) {
737: AspectValue[] diffs = new AspectValue[avResults.length];
738: int diffCount = 0;
739:
740: for (int i = 0; i < avResults.length; i++) {
741: boolean found = false;
742: AspectValue prefAV = null;
743:
744: for (int j = 0; j < prefs.length; j++) {
745: prefAV = prefs[j].getScoringFunction().getBest()
746: .getAspectValue();
747: if (prefAV.getAspectType() == avResults[i]
748: .getAspectType()) {
749: found = true;
750: break;
751: }
752: }
753: if (!found) {
754: diffs[diffCount++] = avResults[i];
755: } else if (prefAV.getValue() != avResults[i].getValue()) {
756: diffs[diffCount++] = avResults[i];
757: }
758: }
759:
760: AspectValue[] returnDiff = new AspectValue[diffCount];
761: for (int i = 0; i < diffCount; i++) {
762: returnDiff[i] = diffs[i];
763: }
764:
765: return returnDiff;
766: }
767:
768: /** Utility method to help conversion of old code to new usage
769: **/
770: public static AspectValue[] convertToAVA(int[] types,
771: double[] values) {
772: int l = types.length;
773: AspectValue[] ava = new AspectValue[l];
774: for (int i = 0; i < l; i++) {
775: ava[i] = AspectValue.newAspectValue(types[i], values[i]);
776: }
777: return ava;
778: }
779:
780: private void readObject(ObjectInputStream ois) throws IOException,
781: ClassNotFoundException {
782: ois.defaultReadObject();
783: clearMemos();
784: }
785: }
|