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.planning.ldm.plan.*;
030: import java.io.IOException;
031: import java.io.ObjectInputStream;
032: import java.io.ObjectOutputStream;
033: import java.io.Serializable;
034:
035: /**
036: * Constraint implementation
037: * A Constraint is part of a Workflow.
038: * Constraints provide pair-wise precedence
039: * relationship information about the Tasks
040: * contained in the Workflow. Each Task can have
041: * more than one applicable Constraint.
042: **/
043:
044: public class ConstraintImpl implements Constraint, NewConstraint,
045: Cloneable, Serializable {
046:
047: private int theConstraintOrder;
048: private double theConstraintOffset = 0.0;
049: private int theConstrainingAspect, theConstrainedAspect;
050: private double theConstrainingValue = 0.0;
051: private boolean isAbsolute;
052: private Task theConstrainingTask, theConstrainedTask;
053:
054: private static final double EPSILON = 1.0; // Maybe this should be 0.0
055:
056: /**
057: * ConstraintEvent Objects for constraining and constrained Tasks.
058: * These are created the first time they are needed and are
059: * redundant w.r.t. theConstrainedTask, theConstrainedAspect,
060: * theConstrainingTask, and theConstrainingAspect
061: **/
062: private transient ConstraintEvent theConstrainingEvent = null;
063: private transient ConstraintEvent theConstrainedEvent = null;
064:
065: /** no-arg constructor*/
066: public ConstraintImpl() {
067: super ();
068: }
069:
070: /** Constructor for new constraint API **/
071: public ConstraintImpl(Task aConstrainedTask,
072: int aConstrainedAspect, Task aConstrainingTask,
073: int aConstrainingAspect, double anOffset, int anOrder) {
074: theConstraintOrder = anOrder;
075: theConstraintOffset = anOffset;
076: theConstrainingAspect = aConstrainingAspect;
077: theConstrainingTask = aConstrainingTask;
078: theConstrainedAspect = aConstrainedAspect;
079: theConstrainedTask = aConstrainedTask;
080: isAbsolute = false;
081: }
082:
083: /**
084: * Create a constraint against an absolute value on a task
085: **/
086: public ConstraintImpl(Task aConstrainedTask,
087: int aConstrainedAspect, double aConstrainingValue,
088: int anOrder) {
089: theConstraintOrder = anOrder;
090: theConstrainingValue = aConstrainingValue;
091: theConstrainedTask = aConstrainedTask;
092: theConstrainedAspect = aConstrainedAspect;
093: theConstrainingAspect = theConstrainedAspect; // In case anyone asks
094: isAbsolute = true;
095: }
096:
097: public void setConstrainingTask(Task task) {
098: if (task == null) {
099: if (theConstrainingTask == null)
100: throw new RuntimeException(
101: "Constraining task already null");
102: } else {
103: if (isAbsolute)
104: throw new RuntimeException("Constraint is absolute");
105: if (theConstrainingTask != null)
106: throw new RuntimeException(
107: "Constraining task already set");
108: }
109: theConstrainingTask = task;
110: }
111:
112: public void setConstrainingAspect(int aspect) {
113: theConstrainingAspect = aspect;
114: }
115:
116: /**
117: * <PRE> Task mytask = myconstraint.getConstrainingTask(); </PRE>
118: * @return Task Returns the Task which is constraining another event or Task.
119: **/
120:
121: public Task getConstrainingTask() {
122: return theConstrainingTask;
123: }
124:
125: /** returns the aspect type of the constraining task
126: **/
127: public int getConstrainingAspect() {
128: return theConstrainingAspect;
129: }
130:
131: /** Return the ConstraintEvent object for the constraining task **/
132: public ConstraintEvent getConstrainingEventObject() {
133: if (theConstrainingEvent == null) {
134: if (isAbsolute) {
135: theConstrainingEvent = new AbsoluteConstraintEvent(
136: theConstrainingAspect, theConstrainingValue);
137: } else {
138: if (theConstrainingTask == null) {
139: throw new RuntimeException(
140: "The constraining task is not set");
141: }
142: theConstrainingEvent = new TaskConstraintEvent.Constraining(
143: (NewTask) theConstrainingTask,
144: theConstrainingAspect);
145: }
146: }
147: return theConstrainingEvent;
148: }
149:
150: public void setConstrainedTask(Task task) {
151: if (task == null) {
152: if (theConstrainedTask == null)
153: throw new RuntimeException(
154: "Constrained task already set");
155: } else {
156: if (theConstrainedTask != null)
157: throw new RuntimeException(
158: "Constrained task already set");
159: }
160: theConstrainedTask = task;
161: }
162:
163: public void setConstrainedAspect(int aspect) {
164: theConstrainedAspect = aspect;
165: }
166:
167: /**
168: * <PRE> Task mytask = myconstraint.getConstrainedTask(); </PRE>
169: * @return Task Returns a Task which is constrained by another event or Task.
170: **/
171:
172: public Task getConstrainedTask() {
173: if (theConstrainedTask == null)
174: throw new RuntimeException("Constrained task is null");
175: return theConstrainedTask;
176: }
177:
178: /** returns the aspect type of the constrained task
179: **/
180:
181: public int getConstrainedAspect() {
182: return theConstrainedAspect;
183: }
184:
185: /** Return the ConstraintEvent object for the constraining task **/
186:
187: public ConstraintEvent getConstrainedEventObject() {
188: if (theConstrainedEvent == null) {
189: if (theConstrainedTask == null) {
190: throw new RuntimeException("Constrained task is null");
191: } else {
192: theConstrainedEvent = new TaskConstraintEvent.Constrained(
193: (NewTask) theConstrainedTask,
194: theConstrainedAspect);
195: }
196: }
197: return theConstrainedEvent;
198: }
199:
200: /**
201: * Returns an int which represents the
202: * order of the Constraint.
203: * <PRE> int myorder = myconstraint.getConstraintOrder(); </PRE>
204: * @return int The int value
205: * will be equal to "0" (COINCIDENT), "-1" (BEFORE) or "1" (AFTER).
206: * There are also order analogues for constraints on non-temporal aspects.
207: * These are "1" (GREATERTHAN), "-1" (LESSTHAN) or "0" (EQUALTO).
208: **/
209:
210: public int getConstraintOrder() {
211: return theConstraintOrder;
212: }
213:
214: /**
215: * Returns a double which represents the offset
216: * of the Constraint.
217: * @return the value to be added to the constraining value before
218: * comparing to the constrained value.
219: **/
220:
221: public double getOffsetOfConstraint() {
222: return theConstraintOffset;
223: }
224:
225: public void setAbsoluteConstrainingValue(double value) {
226: if (theConstrainingTask != null) {
227: throw new RuntimeException(
228: "Constraining task has already been set");
229: }
230: theConstrainingValue = value;
231: isAbsolute = true;
232: }
233:
234: /** setConstraintOrder allows you to set the order.
235: * The order should be COINCIDENT, BEFORE, or AFTER.
236: * <PRE> mynewconstraint.setConstraintOrder(BEFORE); </PRE>
237: * @param order Should be COINCIDENT, BEFORE or AFTER only.
238: **/
239:
240: public void setConstraintOrder(int order) {
241: theConstraintOrder = order;
242: }
243:
244: /** setOffsetofConstraint allows you to set the time
245: * offset of the Constraint. If it is + than the offset
246: * is in the future, if it is - than the offset is in the
247: * past.
248: * <PRE> mynewconstraint.setOffsetofConstraint(-2000); </PRE>
249: * @param offset - offset of constraint
250: **/
251:
252: public void setOffsetOfConstraint(double offset) {
253: theConstraintOffset = offset;
254: }
255:
256: /** Computes a value from constraining, offset, and order to
257: * satisfy constraint
258: * Note that the current implementation only computes for temporal
259: * constraint aspects.
260: **/
261:
262: public double computeValidConstrainedValue() {
263: double constVal = getConstrainingEventObject().getValue()
264: + getOffsetOfConstraint();
265: switch (getConstraintOrder()) {
266: case Constraint.BEFORE: // Same as LESSTHAN
267: return constVal + EPSILON;
268: case Constraint.COINCIDENT: // Same as EQUALTO
269: return constVal;
270: case Constraint.AFTER:
271: return constVal - EPSILON;
272: }
273: return constVal;
274: }
275:
276: public ConstraintImpl copy() {
277: try {
278: return (ConstraintImpl) clone();
279: } catch (CloneNotSupportedException cnse) {
280: return null;
281: }
282: }
283:
284: private void writeObject(ObjectOutputStream stream)
285: throws IOException {
286: stream.defaultWriteObject();
287: }
288:
289: private void readObject(ObjectInputStream stream)
290: throws ClassNotFoundException, IOException {
291: stream.defaultReadObject();
292: }
293:
294: }
|