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.generic;
028:
029: import java.sql.Connection;
030: import java.sql.DriverManager;
031: import java.sql.ResultSet;
032: import java.sql.SQLException;
033: import java.sql.Statement;
034: import java.util.ArrayList;
035: import java.util.Calendar;
036: import java.util.Collection;
037: import java.util.Date;
038: import java.util.Enumeration;
039: import java.util.Iterator;
040: import java.util.Vector;
041:
042: import org.cougaar.core.blackboard.IncrementalSubscription;
043: import org.cougaar.core.component.ServiceRevokedEvent;
044: import org.cougaar.core.component.ServiceRevokedListener;
045: import org.cougaar.core.plugin.ComponentPlugin;
046: import org.cougaar.core.service.DomainService;
047: import org.cougaar.glm.ldm.asset.NewSupplyClassPG;
048: import org.cougaar.planning.ldm.PlanningFactory;
049: import org.cougaar.planning.ldm.asset.Asset;
050: import org.cougaar.planning.ldm.plan.AspectType;
051: import org.cougaar.planning.ldm.plan.AspectValue;
052: import org.cougaar.planning.ldm.plan.Expansion;
053: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
054: import org.cougaar.planning.ldm.plan.NewTask;
055: import org.cougaar.planning.ldm.plan.NewWorkflow;
056: import org.cougaar.planning.ldm.plan.Preference;
057: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
058: import org.cougaar.planning.ldm.plan.ScoringFunction;
059: import org.cougaar.planning.ldm.plan.Task;
060: import org.cougaar.planning.ldm.plan.Verb;
061: import org.cougaar.planning.plugin.util.PluginHelper;
062: import org.cougaar.util.Parameters;
063: import org.cougaar.util.UnaryPredicate;
064:
065: /** ExpanderPlugin that takes arguments of verbs to determine what kinds
066: * of tasks we would like to expand. The plugin also takes an argument that
067: * specifies whether the expansion should be flat 'flat=true' e.g. expand the parent by
068: * creating a workflow of subtasks that are leaf tasks - tasks in between the parent
069: * and the leaves will not be explicitly spelled out in the expansion, although some
070: * of the timing information will be accumulated. If the argument is 'flat=false',
071: * a workflow/expansion will be created for each level of expansion. The default
072: * (if no 'flat=' argument is specified) is flat=true.
073: * The Plugin will access a database that contains information about
074: * how to expand the tasks it is interested in.
075: * Please see glm/docs/UniversalExpanderPlugin.html for database and argument details.
076: **/
077:
078: public class UniversalExpanderPlugin extends ComponentPlugin {
079:
080: private IncrementalSubscription interestingTasks;
081: private IncrementalSubscription myExpansions;
082: private DomainService domainService;
083: private PlanningFactory theFactory;
084: private ArrayList expansionVerbs = new ArrayList();
085: private boolean flat = false;
086:
087: public void load() {
088: super .load();
089: //get a domain service
090: domainService = (DomainService) getServiceBroker().getService(
091: this , DomainService.class,
092: new ServiceRevokedListener() {
093: public void serviceRevoked(ServiceRevokedEvent re) {
094: if (DomainService.class.equals(re.getService())) {
095: domainService = null;
096: }
097: }
098: });
099: // parse the parameters
100: Collection params = getParameters();
101: Iterator param_iter = params.iterator();
102: while (param_iter.hasNext()) {
103: String aParam = (String) param_iter.next();
104: if (aParam.startsWith("flat=")) {
105: // this assumes no spaces ... flat=true or flat=false
106: if (aParam.endsWith("false")) {
107: flat = false;
108: } else if (aParam.endsWith("true")) {
109: flat = true;
110: } else {
111: throw new IllegalArgumentException(
112: "\n UNIVERSALEXPANDERPLUGIN received an "
113: + "illegal plugin argument to flat='value'. "
114: + "The value should either be 'true' or 'false'.");
115: }
116: } else {
117: // assume its a verb
118: expansionVerbs.add(aParam);
119: }
120: }
121: //System.err.println("\n UniversalExpanderPlugin Flat flag is: "+flat);
122: }
123:
124: public void unload() {
125: super .unload();
126: if (domainService != null) {
127: getServiceBroker().releaseService(this ,
128: DomainService.class, domainService);
129: }
130: }
131:
132: public void setupSubscriptions() {
133: //System.out.println("In UniversalExpanderPlugin.setupSubscriptions");
134: interestingTasks = (IncrementalSubscription) getBlackboardService()
135: .subscribe(VerbTasksPredicate(expansionVerbs));
136: myExpansions = (IncrementalSubscription) getBlackboardService()
137: .subscribe(VerbExpansionsPredicate(expansionVerbs));
138:
139: theFactory = ((PlanningFactory) domainService
140: .getFactory("planning"));
141: }
142:
143: public void execute() {
144: //System.out.println("In UniversalExpanderPlugin.execute");
145: if (flat) {
146: for (Enumeration e = interestingTasks.getAddedList(); e
147: .hasMoreElements();) {
148: Task task = (Task) e.nextElement();
149: Collection subtasks = findSubTasks(task);
150: NewWorkflow wf = theFactory.newWorkflow();
151: wf.setParentTask(task);
152: Iterator stiter = subtasks.iterator();
153: while (stiter.hasNext()) {
154: NewTask subtask = (NewTask) stiter.next();
155: subtask.setWorkflow(wf);
156: wf.addTask(subtask);
157: getBlackboardService().publishAdd(subtask);
158: }
159: // create the Expansion ...
160: Expansion newexpansion = theFactory.createExpansion(
161: theFactory.getRealityPlan(), task, wf, null);
162: getBlackboardService().publishAdd(newexpansion);
163: } //end of for
164: } else {
165: Enumeration tree_enum = interestingTasks.getAddedList();
166: while (tree_enum.hasMoreElements()) {
167: Task t = (Task) tree_enum.nextElement();
168: treeExpand(t);
169: }
170: }
171:
172: for (Enumeration exp = myExpansions.getChangedList(); exp
173: .hasMoreElements();) {
174: Expansion myexp = (Expansion) exp.nextElement();
175: if (PluginHelper.updatePlanElement(myexp)) {
176: getBlackboardService().publishChange(myexp);
177: }
178: }
179: } //end of execute
180:
181: /** Gather expansion/subtask information from our database to use
182: * in creating our subtasks and workflow.
183: * @param task The parent task to expand
184: * @return Collection of subtasks
185: **/
186: private Collection findSubTasks(Task task) {
187: Collection subtasks = new ArrayList();
188:
189: try {
190: // Load the driver
191: String rawdb = Parameters
192: .replaceParameters("${generic.database.expander.database}");
193: int colonIndex1 = rawdb.indexOf(':');
194: int colonIndex2 = rawdb.indexOf(':', colonIndex1 + 1);
195: String dbType = rawdb.substring(colonIndex1 + 1,
196: colonIndex2); //WAN added
197: String driverName = Parameters.findParameter("driver."
198: + dbType);
199: Class.forName(driverName);
200: Connection conn = null;
201: ResultSet rset = null;
202:
203: try {
204: // Connect to the database
205: // You must put a database name after the @ sign in the connection URL.
206: // You can use either the fully specified SQL*net syntax or a short cut
207: // syntax as <host>:<port>:<sid>. The example uses the short cut syntax.
208: // get the db info out of the cougaarrc file
209: String dbinfo = Parameters.replaceParameters(rawdb);
210: String rawuser = "${generic.database.expander.user}";
211: String dbuser = Parameters.replaceParameters(rawuser);
212: String rawpasswd = "${generic.database.expander.password}";
213: String dbpasswd = Parameters
214: .replaceParameters(rawpasswd);
215: String exptable = "${generic.database.expander.expansion_table}";
216: String dbexptable = Parameters
217: .replaceParameters(exptable);
218:
219: conn = DriverManager.getConnection(dbinfo, dbuser,
220: dbpasswd);
221: String parentverb = task.getVerb().toString();
222: // Create a Statement
223: Statement stmt = conn.createStatement();
224:
225: //define a base query that we can use
226: StringBuffer basequery = new StringBuffer(
227: "select IS_LEAF_TASK, TIME_OFFSET, SUBTASK_NAME, DURATION, "
228: + "PREPOSITION, PHRASE, DO_CLASS, DO_TYPE_ID, "
229: + "DO_NOMENCLATURE, QUANTITY, SHIPMENTS from "
230: + dbexptable);
231: StringBuffer firstlevelquery = new StringBuffer(
232: basequery + " where ROOT_TASK_NAME = '"
233: + parentverb + "'");
234:
235: //System.out.println("\n About to execute query: "+ firstlevelquery);
236: rset = stmt.executeQuery(firstlevelquery.toString());
237: //check to make sure we get something back from the query - resultset
238: //api show's no easy way to check this - statement api says resultset will
239: //never be null.
240: boolean gotresult = false;
241:
242: while (rset.next()) {
243: gotresult = true;
244: //check to see if we have a leaf task or not and if this is
245: //not a flat expansion only do the initial expansion
246: if ((rset.getInt(1) == 1) || (!flat)) {
247: //System.out.println("\n Got a result set for immediate Leafs!");
248: ArrayList subtasksToAdd = parseRow(task, rset,
249: rset.getInt(2));
250: Iterator substoadd_iter = subtasksToAdd
251: .iterator();
252: while (substoadd_iter.hasNext()) {
253: Task aNewSubTask = (Task) substoadd_iter
254: .next();
255: subtasks.add(aNewSubTask);
256: }
257: } else {
258: //System.out.println("\n Got a result set for NON immediate leafs!");
259: ArrayList outstanding = new ArrayList();
260: ArrayList newoutstanding = new ArrayList();
261: NonLeaf newNonLeaf = new NonLeaf(
262: rset.getInt(2), rset.getString(3));
263: Statement stmt2 = conn.createStatement();
264: outstanding.add(newNonLeaf);
265: while (!outstanding.isEmpty()) {
266: Iterator out_iter = outstanding.iterator();
267: while (out_iter.hasNext()) {
268: boolean foundsub = false;
269: NonLeaf check = (NonLeaf) out_iter
270: .next();
271: //create another statement for more queries so we don't
272: //loose the result set from the first query and statement.
273: StringBuffer anotherquery = new StringBuffer(
274: basequery
275: + " where ROOT_TASK_NAME = '"
276: + check
277: .getSubTaskName()
278: + "'");
279: ResultSet rset2 = stmt2
280: .executeQuery(anotherquery
281: .toString());
282: while (rset2.next()) {
283: foundsub = true;
284: if (rset2.getInt(1) == 1) {
285: //process this row if it is a leaf
286: //get the parent offset to add to each one.
287: int newoffset = check
288: .getOffset()
289: + rset2.getInt(2);
290: ArrayList moreToAdd = parseRow(
291: task, rset2, newoffset);
292: Iterator more_iter = moreToAdd
293: .iterator();
294: while (more_iter.hasNext()) {
295: Task anotherTask = (Task) more_iter
296: .next();
297: subtasks.add(anotherTask);
298: }
299: } else {
300: //if we did not get a leaf again - set up for another
301: //round of queries - but don't forget to accumulate the offsets
302: int anotheroffset = check
303: .getOffset()
304: + rset.getInt(2);
305: NonLeaf anotherNonLeaf = new NonLeaf(
306: anotheroffset, rset2
307: .getString(3));
308: newoutstanding
309: .add(anotherNonLeaf);
310: }
311: } //close the while for rset2
312: if (!foundsub) {
313: System.err
314: .println("\n UNIVERSALEXPANDERPLUGIN COULD NOT FIND A SUBTASK"
315: + " FOR "
316: + check
317: .getSubTaskName()
318: + " IN DB TABLE "
319: + dbexptable
320: + ". PLEASE CHECK THE DB TABLE!!!");
321: Thread.dumpStack();
322: }
323: } //close while outstanding has next
324: //clear out outstanding list and and any new outstanding
325: //entries to it to query again.
326: outstanding.clear();
327: if (!newoutstanding.isEmpty()) {
328: outstanding.addAll(newoutstanding);
329: newoutstanding.clear();
330: }
331: } //close outstanding is empty
332: //close the second+ round of queries
333: stmt2.close();
334: } // close of else
335: } // close of rset.next
336: if ((!gotresult) && (flat)) {
337: //this is only an error for a flat expansion as the tree expansion
338: //is not keeping track of is_leaf_task
339: System.err
340: .println("\n UNIVERSALEXPANDERPLUGIN GOT NO RESULTS FOR THE QUERY: "
341: + firstlevelquery
342: + ". THIS MEANS THE "
343: + parentverb
344: + " TASK CAN NOT BE EXPANDED. PLEASE CEHCK THE DB TABLE.");
345: Thread.dumpStack();
346: }
347: // close the first round of queries
348: stmt.close();
349:
350: } catch (SQLException e) {
351: System.err
352: .println("UNIVERSAL EXPANDER PLUGIN Query failed: "
353: + e);
354: } finally {
355: if (conn != null)
356: conn.close();
357: }
358: } catch (Exception e) {
359: System.err
360: .println("Caught exception while executing a query: "
361: + e);
362: e.printStackTrace();
363: }
364: //System.out.println("\n UniversalExpanderPlugin About to return: " + subtasks.size() + "Subtasks for Workflow");
365: return subtasks;
366: }
367:
368: // parse the row - but take the time offset value as an arg instead of
369: // from the resultset in case it is an accumulated offset from many levels
370: private ArrayList parseRow(Task parent, ResultSet rset,
371: int timeoffset) throws SQLException {
372: ArrayList results = new ArrayList();
373: boolean multipleshipments = false;
374: try {
375: String st_name = rset.getString(3);
376: int duration = rset.getInt(4);
377: NewTask newsubtask = createSubTask(parent, st_name,
378: timeoffset, duration);
379: String preposition = rset.getString(5);
380: if (!rset.wasNull()) {
381: Enumeration newphrases = createPrepositionalPhrase(
382: newsubtask, preposition, rset.getString(6));
383: newsubtask.setPrepositionalPhrases(newphrases);
384: }
385: String do_class = rset.getString(7);
386: if (!rset.wasNull()) {
387: Asset directObject = createDirectObject(do_class, rset
388: .getString(8), rset.getString(9));
389: newsubtask.setDirectObject(directObject);
390: int qty = rset.getInt(10);
391: // create quantity preference
392: AspectValue qtyAV = AspectValue.newAspectValue(
393: AspectType.QUANTITY, qty);
394: ScoringFunction qtySF = ScoringFunction
395: .createPreferredAtValue(qtyAV, 2);
396: Preference qtyPref = theFactory.newPreference(
397: AspectType.QUANTITY, qtySF);
398: newsubtask.addPreference(qtyPref);
399: int shipments = rset.getInt(11);
400: if ((!rset.wasNull()) && (shipments > 1)) {
401: multipleshipments = true;
402: ArrayList newsubtasks = createMultipleShipments(
403: newsubtask, shipments, duration);
404: return newsubtasks;
405: }
406: }
407: results.add(newsubtask);
408:
409: } catch (SQLException se) {
410: throw new SQLException("Exception in parserow..." + se);
411: }
412: return results;
413: }
414:
415: /** Create a simple subtask out of the database
416: * @param parent - parent task
417: * @param st_name - new subtask's verb from db
418: * @param offset new subtask's offset time from parent's start time
419: * @param duration new subtask's duration
420: * @return NewTask - The new subtask
421: **/
422: private NewTask createSubTask(Task parent, String st_verb,
423: int offset, int duration) {
424: NewTask subtask = theFactory.newTask();
425: subtask.setParentTaskUID(parent.getUID());
426: subtask.setVerb(Verb.get(st_verb));
427: subtask.setPlan(parent.getPlan());
428: subtask.setContext(parent.getContext());
429: // pass along parent's prep phrases for now. A new one can be added also.
430: subtask.setPrepositionalPhrases(parent
431: .getPrepositionalPhrases());
432: //set up preferences - first find the start time of the parent task
433: Date childST = null;
434: Date childET = null;
435: Enumeration parentprefs = parent.getPreferences();
436: while (parentprefs.hasMoreElements()) {
437: Preference apref = (Preference) parentprefs.nextElement();
438: if (apref.getAspectType() == AspectType.START_TIME) {
439: Date parentstarttime = new Date((long) apref
440: .getScoringFunction().getBest().getValue());
441: Calendar cal = Calendar.getInstance();
442: cal.setTime(parentstarttime);
443: cal.add(Calendar.DATE, offset);
444: childST = cal.getTime();
445: cal.add(Calendar.DATE, duration);
446: childET = cal.getTime();
447: }
448: break;
449: }
450:
451: Vector prefs = new Vector();
452: //make a start and end as usual - note that for generic purposes
453: //even if this is a supply task, it may end up with a start and end time
454: //pref that are equal
455: AspectValue startAV = AspectValue.newAspectValue(
456: AspectType.START_TIME, childST.getTime());
457: ScoringFunction startSF = ScoringFunction
458: .createPreferredAtValue(startAV, 2);
459: Preference startPref = theFactory.newPreference(
460: AspectType.START_TIME, startSF);
461: prefs.addElement(startPref);
462: AspectValue endAV = AspectValue.newAspectValue(
463: AspectType.END_TIME, childET.getTime());
464: ScoringFunction endSF = ScoringFunction.createPreferredAtValue(
465: endAV, 2);
466: Preference endPref = theFactory.newPreference(
467: AspectType.END_TIME, endSF);
468: prefs.addElement(endPref);
469:
470: subtask.setPreferences(prefs.elements());
471:
472: return subtask;
473: }
474:
475: private Enumeration createPrepositionalPhrase(Task subtask,
476: String preposition, String phrase) {
477: // for now just make the phrase a string.
478: NewPrepositionalPhrase newpp = theFactory
479: .newPrepositionalPhrase();
480: newpp.setPreposition(preposition);
481: newpp.setIndirectObject(phrase);
482: Vector phrases = new Vector();
483: phrases.add(newpp);
484: //keep the phrases from the parent task
485: Enumeration oldpp = subtask.getPrepositionalPhrases();
486: while (oldpp.hasMoreElements()) {
487: PrepositionalPhrase app = (PrepositionalPhrase) oldpp
488: .nextElement();
489: phrases.add(app);
490: }
491: return phrases.elements();
492: }
493:
494: private Asset createDirectObject(String assetclass, String typeid,
495: String nomenclature) {
496: Asset theAsset = null;
497: // try {
498: // theAsset =
499: // (Asset)theFactory.createPrototype(Class.forName(assetclass), typeid, nomenclature);
500: theAsset = (Asset) theFactory.createPrototype(assetclass,
501: typeid, nomenclature);
502: // } catch (ClassNotFoundException cnfe) {
503: // System.err.println("\n UniversalExpanderPlugin Caught exception while trying to create an asset: "+cnfe);
504: // cnfe.printStackTrace();
505: // }
506: //need this for supply tasks...
507: NewSupplyClassPG pg = (NewSupplyClassPG) org.cougaar.glm.ldm.asset.PropertyGroupFactory
508: .newSupplyClassPG();
509: pg.setSupplyClass(assetclass);
510: pg.setSupplyType(assetclass);
511: theAsset.setPropertyGroup(pg);
512:
513: return theAsset;
514: }
515:
516: private ArrayList createMultipleShipments(Task subtask,
517: int shipments, int duration) {
518: //get some starting preference info
519: int shipmentoffset = duration / shipments;
520: Date startofshipments = null;
521: double qtypershipment = 0;
522: Enumeration taskprefs = subtask.getPreferences();
523: while (taskprefs.hasMoreElements()) {
524: Preference asubtaskpref = (Preference) taskprefs
525: .nextElement();
526: if (asubtaskpref.getAspectType() == AspectType.START_TIME) {
527: startofshipments = new Date((long) asubtaskpref
528: .getScoringFunction().getBest().getValue());
529: } else if (asubtaskpref.getAspectType() == AspectType.QUANTITY) {
530: double totalqty = asubtaskpref.getScoringFunction()
531: .getBest().getValue();
532: qtypershipment = totalqty / shipments;
533: }
534: }
535: Calendar shipmentcal = Calendar.getInstance();
536: // set initial time
537: shipmentcal.setTime(startofshipments);
538:
539: //begin creating tasks
540: ArrayList shipmenttasks = new ArrayList();
541: for (int i = 0; i < shipments; i++) {
542: NewTask mstask = theFactory.newTask();
543: mstask.setParentTaskUID(subtask.getParentTaskUID());
544: mstask.setVerb(subtask.getVerb());
545: mstask.setDirectObject(subtask.getDirectObject());
546: mstask.setPrepositionalPhrases(subtask
547: .getPrepositionalPhrases());
548: mstask.setPlan(subtask.getPlan());
549: mstask.setContext(subtask.getContext());
550:
551: //make the preferences for the multiple shipments
552: //note that multiple shipments are assumed to be Supply or similar
553: //tasks for which start time is meaningless. End time should be used
554: //to define when the customer expects the shipment to arrive
555: Date shipmentET = null;
556: //only add in the shipmentoffset if this is not the first shipment
557: if (i != 0) {
558: // for each shipment after the first keep adding the offset
559: // for a cumulative offset affect.
560: shipmentcal.add(Calendar.DATE, shipmentoffset);
561: }
562: shipmentET = shipmentcal.getTime();
563: Vector prefs = new Vector();
564: AspectValue shipmentAV = AspectValue.newAspectValue(
565: AspectType.END_TIME, shipmentET.getTime());
566: ScoringFunction shipmentSF = ScoringFunction
567: .createPreferredAtValue(shipmentAV, 2);
568: Preference shipmentPref = theFactory.newPreference(
569: AspectType.END_TIME, shipmentSF);
570: prefs.addElement(shipmentPref);
571: AspectValue qtyAV = AspectValue.newAspectValue(
572: AspectType.QUANTITY, qtypershipment);
573: ScoringFunction qtySF = ScoringFunction
574: .createPreferredAtValue(qtyAV, 2);
575: Preference qtyPref = theFactory.newPreference(
576: AspectType.QUANTITY, qtySF);
577: prefs.addElement(qtyPref);
578:
579: mstask.setPreferences(prefs.elements());
580: shipmenttasks.add(mstask);
581: }
582: return shipmenttasks;
583: }
584:
585: //expand this as a multi-level expansion instead of a flat(single expansion)
586: private void treeExpand(Task t) {
587: // list to expand
588: ArrayList toexpand = new ArrayList();
589: // add the top level parent
590: toexpand.add(t);
591: //temporary holding list to expand while we recurse
592: ArrayList nexttoexpand = new ArrayList();
593: while (!toexpand.isEmpty()) {
594: Iterator te_iter = toexpand.iterator();
595: while (te_iter.hasNext()) {
596: Task aTask = (Task) te_iter.next();
597: //since the tree expand does not pay attention to is_leaf_task
598: //check to see if this returns an empty collection meaning we are
599: //at the end of the road
600: Collection subs = findSubTasks(aTask);
601: if (!subs.isEmpty()) {
602: NewWorkflow wf = theFactory.newWorkflow();
603: wf.setParentTask(aTask);
604: Iterator siter = subs.iterator();
605: while (siter.hasNext()) {
606: NewTask subtask = (NewTask) siter.next();
607: subtask.setWorkflow(wf);
608: wf.addTask(subtask);
609: //keep this subtask to expand next
610: nexttoexpand.add(subtask);
611: getBlackboardService().publishAdd(subtask);
612: }
613: // create the Expansion ...
614: Expansion newexpansion = theFactory
615: .createExpansion(theFactory
616: .getRealityPlan(), aTask, wf, null);
617: getBlackboardService().publishAdd(newexpansion);
618: }
619: }
620: //clear out toexpand since we've been through the list
621: toexpand.clear();
622: if (!nexttoexpand.isEmpty()) {
623: //move all of the next to expands into to expand
624: toexpand.addAll(nexttoexpand);
625: //reset next to expand
626: nexttoexpand.clear();
627: }
628: }
629:
630: }
631:
632: //
633: // Predicates
634: //
635: protected static UnaryPredicate VerbTasksPredicate(
636: final Collection verbs) {
637: return new UnaryPredicate() {
638: public boolean execute(Object o) {
639: if (o instanceof Task) {
640: Task task = (Task) o;
641: String taskVerb = task.getVerb().toString();
642: Iterator verbs_iter = verbs.iterator();
643: while (verbs_iter.hasNext()) {
644: String interestingVerb = (String) verbs_iter
645: .next();
646: if (interestingVerb.equals(taskVerb)) {
647: return true;
648: }
649: }
650: }
651: return false;
652: }
653: };
654: }
655:
656: protected static UnaryPredicate VerbExpansionsPredicate(
657: final Collection verbs) {
658: return new UnaryPredicate() {
659: public boolean execute(Object o) {
660: if (o instanceof Expansion) {
661: Task task = ((Expansion) o).getTask();
662: String taskVerb = task.getVerb().toString();
663: Iterator verbs_iter = verbs.iterator();
664: while (verbs_iter.hasNext()) {
665: String interestingVerb = (String) verbs_iter
666: .next();
667: if (interestingVerb.equals(taskVerb)) {
668: return true;
669: }
670: }
671: }
672: return false;
673: }
674: };
675: }
676:
677: //
678: //inner classes
679: //
680:
681: // inner class to hold some outstanding non leaf row info
682: public class NonLeaf {
683: private int theOffset;
684: private String theSubTaskName;
685:
686: public NonLeaf(int offset, String subtask) {
687: this .theOffset = offset;
688: this .theSubTaskName = subtask;
689: }
690:
691: public int getOffset() {
692: return theOffset;
693: }
694:
695: public String getSubTaskName() {
696: return theSubTaskName;
697: }
698: }
699:
700: }
|