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