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.mlm.plugin.sample;
028:
029: import java.util.Enumeration;
030: import java.util.HashMap;
031: import java.util.Iterator;
032: import java.util.Map;
033:
034: import org.cougaar.core.agent.service.alarm.Alarm;
035: import org.cougaar.core.blackboard.IncrementalSubscription;
036: import org.cougaar.core.logging.LoggingServiceWithPrefix;
037: import org.cougaar.core.service.LoggingService;
038: import org.cougaar.glm.ldm.Constants;
039: import org.cougaar.planning.ldm.plan.AllocationResult;
040: import org.cougaar.planning.ldm.plan.Disposition;
041: import org.cougaar.planning.ldm.plan.Expansion;
042: import org.cougaar.planning.ldm.plan.Task;
043: import org.cougaar.planning.plugin.legacy.SimplePlugin;
044: import org.cougaar.planning.plugin.util.ExpanderHelper;
045: import org.cougaar.planning.plugin.util.PluginHelper;
046: import org.cougaar.util.UnaryPredicate;
047:
048: public class DetermineRequirementsAbsorberPlugin extends SimplePlugin {
049:
050: /** Subscription to DetermineRequirement Tasks **/
051: protected IncrementalSubscription drTasksSub;
052: protected IncrementalSubscription maintainInventorySub;
053:
054: protected Map timers = new HashMap();
055:
056: private Alarm alarm;
057:
058: private static UnaryPredicate drTasks = new UnaryPredicate() {
059: public boolean execute(Object o) {
060: if (o instanceof Task) {
061: Task t = (Task) o;
062: return Constants.Verb.DetermineRequirements.equals(t
063: .getVerb());
064: }
065: return false;
066: }
067: };
068:
069: private static UnaryPredicate maintainInventoryExpansions = new UnaryPredicate() {
070: public boolean execute(Object o) {
071: if (o instanceof Expansion) {
072: Expansion exp = (Expansion) o;
073: Task t = exp.getTask();
074: return Constants.Verb.MaintainInventory.equals(t
075: .getVerb());
076: }
077: return false;
078: }
079: };
080:
081: /**
082: * Subscribe.
083: */
084: protected void setupSubscriptions() {
085: logger = LoggingServiceWithPrefix.add(logger,
086: getMessageAddress() + ": ");
087:
088: if (logger.isDebugEnabled()) {
089: logger.debug(getClass() + " setting up subscriptions");
090: }
091: drTasksSub = (IncrementalSubscription) subscribe(drTasks);
092: maintainInventorySub = (IncrementalSubscription) subscribe(maintainInventoryExpansions);
093: }
094:
095: protected long checkDRTasks(Enumeration e, long now) {
096: long wakeTime = Long.MAX_VALUE;
097: while (e.hasMoreElements()) {
098: Task drTask = (Task) e.nextElement();
099: if (drTask.getPlanElement() == null) {
100: Long timer = (Long) timers.get(drTask);
101: long expiry = now + 120000;
102: if (timer == null) {
103: if (logger.isInfoEnabled())
104: logger
105: .info("Setting timer for undisposed drTask="
106: + drTask);
107: timers.put(drTask, new Long(expiry));
108: } else {
109: expiry = timer.longValue();
110: if (expiry > now) {
111: if (logger.isDebugEnabled())
112: logger.debug("Still waiting for drTask="
113: + drTask);
114: wakeTime = Math.min(wakeTime, expiry);
115: }
116: }
117: } else {
118: if (timers.remove(drTask) != null) {
119: if (logger.isInfoEnabled())
120: logger.info("Has been disposed drTask="
121: + drTask);
122: }
123: }
124: }
125: return wakeTime;
126: }
127:
128: protected void expireDRTask(Task drTask) {
129: if (drTask.getPlanElement() != null) {
130: if (logger.isDebugEnabled())
131: logger.debug("Has been disposed drTask=" + drTask);
132: return;
133: }
134: if (logger.isDebugEnabled())
135: logger.debug("Expired timer for undisposed drTask="
136: + drTask);
137: AllocationResult ar = PluginHelper
138: .createEstimatedAllocationResult(drTask, theLDMF, 1.0,
139: true);
140: Disposition disposition = theLDMF.createDisposition(drTask
141: .getPlan(), drTask, ar);
142: publishAdd(disposition);
143: String ofType = ExpanderHelper.getOfType(drTask,
144: Constants.Preposition.OFTYPE);
145: logger.shout("Disposed DetermineRequirements OfType " + ofType);
146: }
147:
148: private boolean isUnconfidentEmptyWorkflow(Expansion exp) {
149: if (exp.getWorkflow().getTasks().hasMoreElements())
150: return false;
151: AllocationResult ar = exp.getEstimatedResult();
152: if (ar == null)
153: return true;
154: return !(ar.getConfidenceRating() > .89999);
155: }
156:
157: protected long checkMaintainInventoryExpansions(Enumeration e,
158: long now) {
159: long wakeTime = Long.MAX_VALUE;
160: while (e.hasMoreElements()) {
161: Expansion exp = (Expansion) e.nextElement();
162: if (isUnconfidentEmptyWorkflow(exp)) {
163: Long timer = (Long) timers.get(exp);
164: long expiry = now + 120000;
165: if (timer == null) {
166: if (logger.isInfoEnabled())
167: logger
168: .info("Setting timer for empty MaintainInventory expansion="
169: + exp);
170: timers.put(exp, new Long(expiry));
171: } else {
172: expiry = timer.longValue();
173: if (expiry > now) {
174: if (logger.isDebugEnabled())
175: logger.debug("Still waiting for expansion="
176: + exp);
177: wakeTime = Math.min(wakeTime, expiry);
178: }
179: }
180: } else {
181: if (timers.remove(exp) != null) {
182: if (logger.isInfoEnabled())
183: logger
184: .info("Has subtasks or confident result, expansion="
185: + exp);
186: }
187: }
188: }
189: return wakeTime;
190: }
191:
192: protected void expireMaintainInventoryExpansion(Expansion exp) {
193: if (logger.isDebugEnabled())
194: logger
195: .debug("Expired timer for empty MaintainInventory expansion="
196: + exp);
197: if (isUnconfidentEmptyWorkflow(exp)) {
198: AllocationResult ar = PluginHelper
199: .createEstimatedAllocationResult(exp.getTask(),
200: theLDMF, 1.0, true);
201: exp.setEstimatedResult(ar);
202: publishChange(exp);
203: logger
204: .shout("Changed Estimated Result of MaintainInventory expansion="
205: + exp);
206: } else if (logger.isDebugEnabled()) {
207: AllocationResult ar = exp.getEstimatedResult();
208: if (ar == null) {
209: logger.debug("Acceptable confidence with subtasks");
210: } else {
211: logger.debug("Acceptable confidence="
212: + ar.getConfidenceRating());
213: }
214: }
215: }
216:
217: /**
218: * Execute.
219: */
220: protected void execute() {
221: long now = System.currentTimeMillis();
222: long wakeTime = now + 60000L;
223: if (maintainInventorySub.hasChanged()) {
224: wakeTime = Math.min(wakeTime,
225: checkMaintainInventoryExpansions(
226: maintainInventorySub.getAddedList(), now));
227: wakeTime = Math
228: .min(wakeTime, checkMaintainInventoryExpansions(
229: maintainInventorySub.getChangedList(), now));
230: }
231: if (drTasksSub.hasChanged()) {
232: wakeTime = Math.min(wakeTime, checkDRTasks(drTasksSub
233: .getAddedList(), now));
234: }
235: if (alarm != null && alarm.hasExpired()) {
236: alarm = null;
237: for (Iterator i = timers.entrySet().iterator(); i.hasNext();) {
238: Map.Entry entry = (Map.Entry) i.next();
239: Object key = entry.getKey();
240: Long timer = (Long) entry.getValue();
241: long expiry = timer.longValue();
242: if (expiry <= now) {
243: if (key instanceof Task) {
244: expireDRTask((Task) key);
245: } else if (key instanceof Expansion) {
246: expireMaintainInventoryExpansion((Expansion) key);
247: }
248: i.remove();
249: }
250: }
251: }
252: if (alarm == null) {
253: if (timers.size() > 0) {
254: if (logger.isDebugEnabled())
255: logger.debug("Waiting for " + (wakeTime - now)
256: + " millis");
257: alarm = wakeAtRealTime(wakeTime);
258: } else {
259: if (logger.isInfoEnabled())
260: logger.info("No more timers -- alarm not set");
261: }
262: } else {
263: if (logger.isDebugEnabled())
264: logger.debug("Timer still active");
265: }
266: }
267:
268: /** rely upon load-time introspection to set these services - don't worry about revokation. */
269: public final void setLoggingService(LoggingService logger) {
270: this .logger = logger;
271: }
272:
273: /**
274: * Everybody needs a logger
275: **/
276: protected LoggingService logger;
277: }
|