001: /*
002: * <copyright>
003: *
004: * Copyright 1999-2004 Honeywell Inc
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: /* This contains the GenericPlugin class definition. */
028:
029: package org.cougaar.glm.packer;
030:
031: import java.util.ArrayList;
032: import java.util.Collection;
033: import java.util.Enumeration;
034: import java.util.Iterator;
035: import java.util.Vector;
036:
037: import org.cougaar.core.blackboard.IncrementalSubscription;
038: import org.cougaar.core.mts.MessageAddress;
039: import org.cougaar.core.service.LoggingService;
040: import org.cougaar.planning.ldm.PlanningFactory;
041: import org.cougaar.planning.ldm.plan.Aggregation;
042: import org.cougaar.planning.ldm.plan.AllocationResultAggregator;
043: import org.cougaar.planning.ldm.plan.AllocationResultDistributor;
044: import org.cougaar.planning.ldm.plan.Expansion;
045: import org.cougaar.planning.ldm.plan.MPTask;
046: import org.cougaar.planning.ldm.plan.NewComposition;
047: import org.cougaar.planning.ldm.plan.NewMPTask;
048: import org.cougaar.planning.ldm.plan.NewTask;
049: import org.cougaar.planning.ldm.plan.NewWorkflow;
050: import org.cougaar.planning.ldm.plan.Plan;
051: import org.cougaar.planning.ldm.plan.Task;
052: import org.cougaar.planning.plugin.legacy.SimplePlugin;
053: import org.cougaar.planning.plugin.util.PluginHelper;
054: import org.cougaar.util.UnaryPredicate;
055: import org.cougaar.util.log.Logger;
056:
057: /** Main class for the generic plugin.
058: * real work is done by processAddTask, processChangeTask, processRemoveTasks
059: * these methods called at the end of execute().
060: *
061: * The Generic Plugin should have three subscriptions:
062: * <ol>
063: * <li> To all the PlanElements it has created. Changes to these
064: * should be handled by updating their AllocationResults
065: * <li> To tasks based on the predicate defined by getTaskPredicate.
066: * <li> A subscription to all its assets, used to find itself.
067: * </ol>
068: */
069: abstract public class GenericPlugin extends SimplePlugin {
070: public static final int DEFAULT_LOGGING_LEVEL = Logger.INFO;
071: public static final String DEBUG_STRING = "debug";
072: public static final String INFO_STRING = "info";
073: public static final String WARN_STRING = "warn";
074: public static final String ERROR_STRING = "error";
075: public static final String FATAL_STRING = "fatal";
076:
077: private LoggingService myLoggingService;
078:
079: /**
080: * This new Preposition is used to tag tasks that are created through
081: * Packing and that should not trigger subscriptions.
082: */
083: public static String INTERNAL = "INTERNAL";
084:
085: // The subscriptions for this plugin...
086: private IncrementalSubscription myPlanElements;
087:
088: private IncrementalSubscription myAllTasks;
089:
090: /**
091: * Predicate that finds all Tasks, <em>except</em> those explicitly
092: * tagged as INTERNAL. (These are created by the Sizer.)
093: * @see Sizer
094: */
095: private UnaryPredicate myAllTaskPred = new UnaryPredicate() {
096: public boolean execute(Object o) {
097: if (o instanceof Task) {
098: if (((Task) o).getPrepositionalPhrase(INTERNAL) == null) {
099: return true;
100: } else {
101: return false;
102: }
103: }
104: return false;
105: }
106: };
107:
108: /**
109: * Utility method
110: */
111: private Object classForString(String classname) {
112: Class cls = null;
113: Object retval = null;
114: try {
115: cls = Class.forName(classname);
116: } catch (Exception e) {
117: getLoggingService()
118: .error(
119: "GenericPlugin: Class " + classname
120: + " not found.", e);
121: return null;
122: }
123: if (cls != null) {
124: try {
125: retval = cls.newInstance();
126: } catch (Exception e) {
127: getLoggingService().error(
128: "GenericPlugin: Unable to create instance of "
129: + classname, e);
130: return null;
131: }
132: }
133: return retval;
134: }
135:
136: public LoggingService getLoggingService() {
137: return myLoggingService;
138: }
139:
140: /**
141: *
142: *
143: */
144: public void createExpansion(Iterator tasksForWorkflow,
145: Task parentTask) {
146: // this needs to publish the Expansion, all the subtasks and
147: // the workflow
148: if (parentTask.getPlan() == null) {
149: throw (new RuntimeException(
150: "Unable to find plan for expansion - parentTask is "
151: + parentTask.getUID()));
152: }
153:
154: NewWorkflow workflow = getFactory().newWorkflow();
155: workflow.setIsPropagatingToSubtasks(true); // was true, but may lead to dangling unprocessed internal Supply tasks
156: workflow.setParentTask(parentTask);
157:
158: workflow
159: .setAllocationResultAggregator(AllocationResultAggregator.DEFAULT);
160:
161: while (tasksForWorkflow.hasNext()) {
162: NewTask subTask = (NewTask) tasksForWorkflow.next();
163: subTask.setWorkflow(workflow);
164: workflow.addTask(subTask);
165:
166: publishAdd(subTask);
167: }
168:
169: publishAdd(workflow);
170:
171: Expansion expan = getFactory().createExpansion(
172: parentTask.getPlan(), parentTask, workflow, null);
173: publishAdd(expan);
174:
175: return;
176: }
177:
178: /** Creates <em>and publishes</em> aggregations for all of the tasks
179: * in the input argument. For robustness, catches all errors we could
180: * foresee, prints error messages and returns a boolean indicating
181: * success or failure.
182: */
183: public boolean createAggregation(Iterator tasksToAgg,
184: MPTask childTask, Plan plan,
185: AllocationResultDistributor distributor) {
186: // Save into a vector because we want to use the enumeration in multiple
187: // places
188: ArrayList parentTasks = new ArrayList();
189: while (tasksToAgg.hasNext()) {
190: parentTasks.add((Task) tasksToAgg.next());
191: }
192:
193: if (getLoggingService().isDebugEnabled()) {
194: getLoggingService().debug(
195: "GenericPlugin: Top of create Aggregation.");
196: }
197:
198: // Create Composition
199: NewComposition comp = getFactory().newComposition();
200:
201: comp.setCombinedTask(childTask);
202: comp.setDistributor(distributor);
203:
204: if (getLoggingService().isDebugEnabled()) {
205: getLoggingService().debug("GenericPlugin: Created comp.");
206: }
207:
208: Iterator taskIterator = parentTasks.iterator();
209: while (taskIterator.hasNext()) {
210: Task parentTask = (Task) taskIterator.next();
211:
212: if (plan == null) {
213: plan = parentTask.getPlan();
214:
215: if (plan == null) {
216: plan = getFactory().getRealityPlan();
217:
218: if (plan == null) {
219: getLoggingService()
220: .error(
221: "GenericPlugin: Unable to find plan for aggregation.");
222: return false;
223: }
224: }
225: }
226:
227: if (getLoggingService().isDebugEnabled()) {
228: getLoggingService().debug(
229: "GenericPlugin: Top of while loop.");
230: }
231:
232: Aggregation aggregation = getFactory().createAggregation(
233: plan, parentTask, comp, null);
234:
235: if (getLoggingService().isInfoEnabled()) {
236: getLoggingService().info(
237: "GenericPlugin: adding aggregation to "
238: + parentTask.getUID());
239: }
240:
241: if (getLoggingService().isDebugEnabled()) {
242: getLoggingService().debug(
243: "GenericPlugin: built the aggregation.");
244: }
245:
246: publishAdd(aggregation);
247:
248: /* BOZO - Work around for persistence bug - need to publish the
249: * aggregation before adding it to the composition. Should not be
250: * required since this all occurs inside of a single transaction.
251: */
252: comp.addAggregation(aggregation);
253:
254: }
255:
256: if (getLoggingService().isDebugEnabled()) {
257: getLoggingService().debug(
258: "GenericPlugin: After the while loop.");
259: }
260:
261: NewMPTask mpt = (NewMPTask) childTask;
262:
263: mpt.setPlan(plan);
264: mpt.setComposition(comp);
265: //BOZO !!!
266: mpt.setParentTasks(new Vector(parentTasks).elements());
267:
268: publishAdd(childTask);
269:
270: return true;
271: }
272:
273: /** Called from cycle when something has changed or the plugin was triggered.
274: */
275: protected void execute() {
276: // now we handle updates to our plan elements
277: if (myPlanElements != null) {
278: updateAllocationResult(myPlanElements);
279: } else if (getLoggingService().isDebugEnabled()) {
280: getLoggingService()
281: .debug(
282: "GenericPlugin: _myPlanElements subscription is missing!");
283: }
284:
285: processNewTasks(myAllTasks.getAddedList());
286:
287: processChangedTasks(myAllTasks.getChangedList());
288:
289: processRemovedTasks(myAllTasks.getRemovedList());
290: }
291:
292: /**
293: * processNewTasks - called during execute to handle new tasks.
294: * plugins should implement as appropriate.
295: *
296: * @param newTasks Enumeration of new tasks
297: */
298: public abstract void processNewTasks(Enumeration newTasks);
299:
300: /**
301: * processChangedTasks - called during execute to handle changed tasks.
302: * plugins should implement as appropriate.
303: *
304: * @param changedTasks Enumeration of changed tasks
305: */
306: public abstract void processChangedTasks(Enumeration changedTasks);
307:
308: /**
309: * processRemovedTasks - called during execute to handle removed tasks.
310: * plugins should implement as appropriate.
311: *
312: * @param removedTasks Enumeration of removed tasks
313: */
314: public abstract void processRemovedTasks(Enumeration removedTasks);
315:
316: /**
317: * getTaskPredicate - returns task predicate for task subscription
318: * Default implementation subscribes to all non-internal tasks. Derived classes
319: * should probably implement a more specific version.
320: *
321: * @return UnaryPredicate - task predicate to be used.
322: */
323: public UnaryPredicate getTaskPredicate() {
324: return myAllTaskPred;
325: }
326:
327: /**
328: * getPlanElementPredicate - returns predicate which screens for plan
329: * elements which will need to have allocation results set. In this case,
330: * plan elements associated with Ammunition Supply tasks
331: *
332: *
333: * @return UnaryPredicate screens for plan elements which the packer is
334: * reponsible
335: */
336: public abstract UnaryPredicate getPlanElementPredicate();
337:
338: /**
339: * setupSubscriptions - set up subscriptions to assets, tasks, and planElements.
340: * Uses predicates returned by getTaskPredicate() & getPlanElementPredicate
341: */
342: protected void setupSubscriptions() {
343: myLoggingService = (LoggingService) getDelegate()
344: .getServiceBroker().getService(this ,
345: LoggingService.class, null);
346:
347: if (myLoggingService.isDebugEnabled()) {
348: myLoggingService
349: .debug("GenericPlugin: setting up subscriptions for Packer.");
350:
351: myLoggingService
352: .debug("GenericPlugin.setupSubscriptions: didRehydrate() "
353: + didRehydrate()
354: + " _allTasks "
355: + myAllTasks);
356: }
357:
358: myAllTasks = (IncrementalSubscription) subscribe(getTaskPredicate());
359:
360: myPlanElements = (IncrementalSubscription) subscribe(getPlanElementPredicate());
361:
362: }
363:
364: /**
365: * Creates an generic plugin
366: */
367: public GenericPlugin() {
368: }
369:
370: /** Function that tests if the first argument is of a given class
371: */
372: public boolean testInstance(Object arg, String ty) {
373: boolean test = true;
374: try {
375: test = (Class.forName(ty)).isInstance(arg);
376: } catch (ClassNotFoundException e) {
377: getLoggingService().error(e.getMessage(), e);
378: test = false;
379: }
380: return test;
381: }
382:
383: /**
384: * Provides access to a protected method.
385: */
386: public PlanningFactory getGPFactory() {
387: return getFactory();
388: }
389:
390: /**
391: * Provides access to a protected method.
392: */
393: public MessageAddress getGPMessageAddress() {
394: return getMessageAddress();
395: }
396:
397: protected Collection tasksForPred(UnaryPredicate up) {
398: return query(up);
399: }
400:
401: protected void updateAllocationResult(
402: IncrementalSubscription planElements) {
403: PluginHelper.updateAllocationResult(planElements);
404: }
405:
406: protected int getLogLevel(String logging) {
407: logging = logging.toLowerCase();
408:
409: if (logging.equals(DEBUG_STRING)) {
410: return (Logger.DEBUG);
411: } else if (logging.equals(INFO_STRING)) {
412: return (Logger.INFO);
413: } else if (logging.equals(WARN_STRING)) {
414: return (Logger.WARN);
415: } else if (logging.equals(ERROR_STRING)) {
416: return (Logger.ERROR);
417: } else if (logging.equals(FATAL_STRING)) {
418: return (Logger.FATAL);
419: } else {
420: return (DEFAULT_LOGGING_LEVEL);
421: }
422: }
423: }
|