0001: /*
0002: * <copyright>
0003: *
0004: * Copyright 1997-2004 BBNT Solutions, LLC
0005: * under sponsorship of the Defense Advanced Research Projects
0006: * Agency (DARPA).
0007: *
0008: * You can redistribute this software and/or modify it under the
0009: * terms of the Cougaar Open Source License as published on the
0010: * Cougaar Open Source Website (www.cougaar.org).
0011: *
0012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023: *
0024: * </copyright>
0025: */
0026:
0027: package org.cougaar.mlm.plugin.generic;
0028:
0029: import java.util.ArrayList;
0030: import java.util.Collection;
0031: import java.util.Enumeration;
0032: import java.util.Iterator;
0033: import java.util.Vector;
0034:
0035: import org.cougaar.core.blackboard.AnonymousChangeReport;
0036: import org.cougaar.core.blackboard.ChangeReport;
0037: import org.cougaar.core.blackboard.IncrementalSubscription;
0038: import org.cougaar.core.mts.MessageAddress;
0039: import org.cougaar.core.service.LoggingService;
0040: import org.cougaar.glm.ldm.Constants;
0041: import org.cougaar.glm.ldm.asset.Organization;
0042: import org.cougaar.planning.ldm.PlanningFactory;
0043: import org.cougaar.planning.ldm.asset.Asset;
0044: import org.cougaar.planning.ldm.asset.NewTypeIdentificationPG;
0045: import org.cougaar.planning.ldm.plan.Allocation;
0046: import org.cougaar.planning.ldm.plan.AllocationResult;
0047: import org.cougaar.planning.ldm.plan.Expansion;
0048: import org.cougaar.planning.ldm.plan.HasRelationships;
0049: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
0050: import org.cougaar.planning.ldm.plan.NewTask;
0051: import org.cougaar.planning.ldm.plan.NewWorkflow;
0052: import org.cougaar.planning.ldm.plan.PlanElement;
0053: import org.cougaar.planning.ldm.plan.Predictor;
0054: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
0055: import org.cougaar.planning.ldm.plan.Relationship;
0056: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
0057: import org.cougaar.planning.ldm.plan.Role;
0058: import org.cougaar.planning.ldm.plan.Task;
0059: import org.cougaar.planning.ldm.plan.Verb;
0060: import org.cougaar.planning.plugin.legacy.SimplePlugin;
0061: import org.cougaar.planning.plugin.util.ExpanderHelper;
0062: import org.cougaar.planning.plugin.util.PluginHelper;
0063: import org.cougaar.util.ConfigFinder;
0064: import org.cougaar.util.TimeSpan;
0065: import org.cougaar.util.UnaryPredicate;
0066: import org.w3c.dom.Document;
0067: import org.w3c.dom.Element;
0068: import org.w3c.dom.Node;
0069: import org.w3c.dom.NodeList;
0070:
0071: /**
0072: * For now this plugin only subscribes to tasks from an XMLFile.
0073: * The XMLFile to be read should be passed in as an argument.
0074: * <p>
0075: * Expected DTD is:
0076: * <pre>
0077: * <!ELEMENT commands (command)*>
0078: * <!ELEMENT command (task, (expand|allocate))>
0079: * <!ELEMENT expand (task)*>
0080: * <!ELEMENT allocate (((cluster)|((role)*)),default?)>
0081: * <!ELEMENT default (((cluster)|((role)*)),default?)>
0082: * <!ELEMENT cluster EMPTY>
0083: * <!ATTLIST cluster name CDATA #REQUIRED>
0084: * <!ELEMENT role EMPTY>
0085: * <!ATTLIST role name CDATA #REQUIRED>
0086: * <!ELEMENT task (phrase)?>
0087: * <!ATTLIST task verb CDATA #REQUIRED>
0088: * <!ELEMENT phrase EMPTY>
0089: * <!ATTLIST phrase
0090: * for CDATA #REQUIRED
0091: * oftype CDATA #REQUIRED>
0092: * </pre>
0093: * <p>
0094: * Here is an example. It first tries to allocate all Transport tasks
0095: * to any StrategicTransportProvider. If none of the Organizations match, it then
0096: * tries to allocate all the Transport tasks to any Superior Organization.
0097: * <p>
0098: * <pre>
0099: * <commands>
0100: * <command>
0101: * <task verb="Transport"/>
0102: * <allocate>
0103: * <role name="StrategicTransportationProvider"/>
0104: * <default>
0105: * <role name="Superior"/>
0106: * <default>
0107: * <allocate>
0108: * <command>
0109: * <commands>
0110: * </pre>
0111: */
0112: public class GenericTablePlugin extends SimplePlugin {
0113:
0114: protected CommandInfo[] allCommands;
0115: protected UnaryPredicate[] taskPreds;
0116: protected UnaryPredicate[] allocPreds;
0117:
0118: protected IncrementalSubscription organizationSub;
0119: protected IncrementalSubscription[] tasksSub;
0120: protected IncrementalSubscription[] allocationsSub;
0121:
0122: protected void setupSubscriptions() {
0123: Vector myParams = getParameters();
0124: String xmlFileString = (String) myParams.elementAt(0);
0125: initializeTables(xmlFileString);
0126: initializeSubscriptions();
0127: }
0128:
0129: protected void initializeTables(String xmlFileString) {
0130: readXMLFile(xmlFileString);
0131:
0132: taskPreds = createTaskPredicates(allCommands);
0133: allocPreds = createAllocationPredicates(taskPreds);
0134:
0135: tasksSub = new IncrementalSubscription[taskPreds.length];
0136: allocationsSub = new IncrementalSubscription[allocPreds.length];
0137: }
0138:
0139: protected void initializeSubscriptions() {
0140: makeSubscriptions();
0141: }
0142:
0143: protected void makeSubscriptions() {
0144: for (int i = 0; i < taskPreds.length; i++) {
0145: tasksSub[i] = (IncrementalSubscription) subscribe(taskPreds[i]);
0146: }
0147:
0148: for (int i = 0; i < allocPreds.length; i++) {
0149: allocationsSub[i] = (IncrementalSubscription) subscribe(allocPreds[i]);
0150: }
0151:
0152: organizationSub = (IncrementalSubscription) subscribe(newOrganizationPred());
0153: }
0154:
0155: /** used by subclass **/
0156: protected void cancelSubscriptions() {
0157: for (int i = 0; i < taskPreds.length; i++) {
0158: unsubscribe(tasksSub[i]);
0159: }
0160:
0161: for (int i = 0; i < allocPreds.length; i++) {
0162: unsubscribe(allocationsSub[i]);
0163: }
0164:
0165: unsubscribe(organizationSub);
0166: }
0167:
0168: /** rely upon load-time introspection to set these services - don't worry about revokation. */
0169: public final void setLoggingService(LoggingService logger) {
0170: this .logger = logger;
0171: }
0172:
0173: /**
0174: * Everybody needs a logger
0175: **/
0176: protected LoggingService logger;
0177:
0178: public synchronized void execute() {
0179: boolean checkUnallocated = false;
0180: if (organizationSub.hasChanged()) {
0181: Organization selfOrg = null;
0182:
0183: for (Iterator orgIter = organizationSub.getCollection()
0184: .iterator(); orgIter.hasNext();) {
0185: Organization org = (Organization) orgIter.next();
0186: if (org.isSelf()) {
0187: selfOrg = org;
0188: break;
0189: }
0190: }
0191:
0192: if (selfOrg != null) {
0193: Collection changeReports = organizationSub
0194: .getChangeReports(selfOrg);
0195: if ((changeReports != AnonymousChangeReport.SET)
0196: && (changeReports != null)) {
0197: for (Iterator reportIterator = changeReports
0198: .iterator(); reportIterator.hasNext();) {
0199: ChangeReport report = (ChangeReport) reportIterator
0200: .next();
0201: if (report instanceof RelationshipSchedule.RelationshipScheduleChangeReport) {
0202: checkUnallocated = true;
0203: break;
0204: }
0205: }
0206:
0207: if (checkUnallocated) {
0208: for (int i = 0; i < tasksSub.length; i++) {
0209: CommandInfo c = allCommands[i];
0210: if (c.type_id == CommandInfo.TYPE_ALLOCATE) {
0211: if (logger.isDebugEnabled())
0212: logger
0213: .debug(getAgentIdentifier()
0214: + " had RelatSched change on self org, so re-alloc all allocatable tasks.");
0215: allocate((AllocateCommandInfo) c,
0216: tasksSub[i], i);
0217: }
0218: }
0219: }
0220: }
0221: }
0222: }
0223:
0224: for (int i = 0; i < tasksSub.length; i++) {
0225: if (tasksSub[i].hasChanged()) {
0226: CommandInfo c = allCommands[i];
0227: if (c.type_id == CommandInfo.TYPE_ALLOCATE) {
0228: // If the above block already called allocate on all the tasksSubs,
0229: // then don't call it again.
0230: if (!checkUnallocated) {
0231: if (logger.isDebugEnabled())
0232: logger
0233: .debug(getAgentIdentifier()
0234: + " has changed task supposed to allocate - will alloc all added");
0235: allocate((AllocateCommandInfo) c, tasksSub[i]
0236: .getAddedCollection(), i);
0237: }
0238: } else if (c.type_id == CommandInfo.TYPE_EXPAND) {
0239: // expand
0240: TaskInfo[] toTasks = ((ExpandCommandInfo) c).expandTasks;
0241: for (Iterator iterator = tasksSub[i]
0242: .getAddedCollection().iterator(); iterator
0243: .hasNext();) {
0244: Task task = (Task) iterator.next();
0245: // FIXME FIXME FIXME FIXME: Expansions won't
0246: // Be in this sub on expansions!
0247: // Need new sub to expansions of these tasks,
0248: // And pass in that collection instead
0249: // if (getTaskPlanElement(task, allocationsSub[i]) == null) {
0250: if (task.getPlanElement() == null) {
0251: for (int j = 0; j < toTasks.length; j++) {
0252: if (logger.isDebugEnabled())
0253: logger
0254: .debug(getAgentIdentifier()
0255: + " had un-planned expandable Task added to sub - will expand: "
0256: + task);
0257: doExpansion(toTasks[j], task);
0258: }
0259: }
0260: }
0261: } else {
0262: if (logger.isDebugEnabled()) {
0263: logger
0264: .debug("execute: unrecognized command type - "
0265: + c.type_id
0266: + " - command ignored.");
0267: }
0268: }
0269: }
0270: }
0271:
0272: for (int i = 0; i < allocationsSub.length; i++) {
0273: if (allocationsSub[i].hasChanged()) {
0274: if (logger.isDebugEnabled())
0275: logger
0276: .debug(getAgentIdentifier()
0277: + " had changed Alloc -- will update results.");
0278: updateAllocationResult(allocationsSub[i]);
0279: }
0280: }
0281: }
0282:
0283: protected void doAllocation(Organization org, Task task) {
0284: Predictor allocPred = org.getClusterPG().getPredictor();
0285: AllocationResult allocResult;
0286: if (allocPred != null)
0287: allocResult = allocPred.Predict(task, getDelegate());
0288: else
0289: allocResult = PluginHelper.createEstimatedAllocationResult(
0290: task, getFactory(), 0.0, true);
0291: Allocation myalloc = getFactory().createAllocation(
0292: task.getPlan(), task, org, allocResult, Role.BOGUS);
0293: if (logger.isDebugEnabled())
0294: logger.debug(getAgentIdentifier() + " adding alloc of "
0295: + task + " to "
0296: + org.getClusterPG().getMessageAddress());
0297: publishAdd(myalloc);
0298: }
0299:
0300: /** maybe memoize? **/
0301: protected Organization findCapableOrganization(
0302: AllocateCommandInfo allocC) {
0303: // find ourself first
0304: for (Iterator orgIter = organizationSub.getCollection()
0305: .iterator(); orgIter.hasNext();) {
0306: Organization org = (Organization) orgIter.next();
0307: if (org.isSelf()) {
0308: while (allocC != null) {
0309: // All HasRelationships having all roles
0310: Collection intersection = new ArrayList();
0311: boolean first = true;
0312: RelationshipSchedule schedule = org
0313: .getRelationshipSchedule();
0314:
0315: for (int i = 0; i < allocC.allocateRoles.length; i++) {
0316: Role role = Role
0317: .getRole(allocC.allocateRoles[i]);
0318: Collection orgCollection = schedule
0319: .getMatchingRelationships(role,
0320: TimeSpan.MIN_VALUE,
0321: TimeSpan.MAX_VALUE);
0322: for (Iterator iter = orgCollection.iterator(); iter
0323: .hasNext();) {
0324: HasRelationships other = schedule
0325: .getOther((Relationship) iter
0326: .next());
0327:
0328: if (other instanceof Organization) {
0329: if (first) {
0330: intersection.add(other);
0331: } else {
0332: if (!intersection.contains(other)) {
0333: iter.remove();
0334: }
0335: }
0336: }
0337: }
0338: first = false;
0339: }
0340:
0341: // If we found any matches return one, else try the default
0342: if (intersection.size() > 0) {
0343: return (Organization) intersection.iterator()
0344: .next();
0345: } else {
0346: allocC = allocC.defaultAlloc;
0347: }
0348: }
0349: }
0350: }
0351: return null;
0352: }
0353:
0354: /**
0355: * Ugly debug tool!
0356: */
0357: protected boolean DEBUGisCapable(Organization org, String name,
0358: String[] roles) {
0359: logger.debug("******************************************");
0360: logger
0361: .debug("DEBUG GenericTablePlugin.isCapable for Exceptions!!!");
0362: logger.debug("Cluster: " + getMessageAddress());
0363: logger.debug("Arguments:");
0364: logger.debug(" org: " + org);
0365: if (name != null)
0366: logger.debug(" name: " + name);
0367: if (roles != null)
0368: logger.debug(" roles[" + roles.length + "]: " + roles);
0369: try {
0370: if (name != null) {
0371: // If name is specified, it alone qualifies!
0372: logger.debug("check name:");
0373: logger.debug(" org.getMessageAddress(): ");
0374: logger.debug(" " + org.getMessageAddress());
0375: logger.debug(" .getAddress(): ");
0376: logger.debug(" "
0377: + ((MessageAddress) org.getMessageAddress())
0378: .getAddress());
0379: logger.debug(" .equals(" + name + "): ");
0380: String clustername = ((MessageAddress) org
0381: .getMessageAddress()).getAddress();
0382: logger.debug(" " + clustername.equals(name));
0383: return clustername.equals(name);
0384: }
0385:
0386: boolean direct = true;
0387:
0388: if (roles != null) {
0389: RelationshipSchedule schedule = org
0390: .getRelationshipSchedule();
0391: for (int i = 0; i < roles.length; i++) {
0392: String findRole = roles[i];
0393: logger.debug(" findRole[" + i + " of "
0394: + roles.length + "]: " + findRole);
0395:
0396: Collection orgCollection = schedule
0397: .getMatchingRelationships(Role.getRole(
0398: roles[i]).getConverse(),
0399: TimeSpan.MIN_VALUE,
0400: TimeSpan.MAX_VALUE);
0401: if (orgCollection.size() == 0) {
0402: return false;
0403: }
0404:
0405: logger.debug("Matching relationships: "
0406: + orgCollection);
0407: }
0408: // Good: Org has all the roles
0409: }
0410:
0411: logger.debug(" NO ERRORS???");
0412: logger.debug("******************************************");
0413: return true;
0414: } catch (Exception e) {
0415: logger.error("**** PREVIOUS CAUSED EXCEPTION " + e
0416: + " ****");
0417: e.printStackTrace();
0418: logger.error("******************************************");
0419: return false;
0420: }
0421: }
0422:
0423: protected void doExpansion(TaskInfo toTask, Task parentTask) {
0424: PlanningFactory f = getFactory();
0425: NewWorkflow wf = f.newWorkflow();
0426: wf.setParentTask(parentTask);
0427:
0428: NewTask newTask = f.newTask();
0429: newTask.setParentTask(parentTask);
0430: newTask.setPlan(parentTask.getPlan());
0431: newTask.setDirectObject(parentTask.getDirectObject());
0432: newTask.setPreferences(parentTask.getPreferences());
0433: newTask.setVerb(Verb.get(toTask.verb));
0434:
0435: NewPrepositionalPhrase npp = f.newPrepositionalPhrase();
0436: npp.setPreposition(Constants.Preposition.FOR);
0437: MessageAddress ci = MessageAddress
0438: .getMessageAddress(toTask.taskFor);
0439: npp.setIndirectObject(ci);
0440:
0441: NewPrepositionalPhrase npp1 = f.newPrepositionalPhrase();
0442: npp1.setPreposition(Constants.Preposition.OFTYPE);
0443:
0444: Asset myasset = f.createAsset("Asset");
0445: NewTypeIdentificationPG ti = (NewTypeIdentificationPG) myasset
0446: .getTypeIdentificationPG();
0447: ti.setTypeIdentification(toTask.ofType);
0448:
0449: npp1.setIndirectObject(myasset);
0450:
0451: Vector v = new Vector();
0452: v.addElement(npp);
0453: v.addElement(npp1);
0454:
0455: newTask.setPrepositionalPhrases(v.elements());
0456: newTask.setWorkflow(wf);
0457:
0458: AllocationResult ar = PluginHelper
0459: .createEstimatedAllocationResult(newTask, theLDMF, 0.0,
0460: true);
0461: Expansion exp = f.createExpansion(parentTask.getPlan(),
0462: newTask, wf, ar);
0463: if (logger.isDebugEnabled())
0464: logger.debug(getAgentIdentifier()
0465: + " adding exp of a task!");
0466: publishAdd(exp);
0467: }
0468:
0469: protected void updateAllocationResult(IncrementalSubscription sub) {
0470: Enumeration changedPEs = sub.getChangedList();
0471: while (changedPEs.hasMoreElements()) {
0472: PlanElement pe = (PlanElement) changedPEs.nextElement();
0473: AllocationResult repar;
0474: AllocationResult estar;
0475: if (((repar = pe.getReportedResult()) != null)
0476: && ((estar = pe.getEstimatedResult()) != null) &&
0477: //!repar.isEqual(estar)) <--BROKEN in AllocatorHelper!
0478: (repar != estar)) {
0479: pe.setEstimatedResult(repar);
0480:
0481: // We always force the reported and estimated to be ==
0482: // But only publishChange it if they are not .isEqual
0483: // That is, it is more correct to only require .isEqual, but try to only minimally rock-the-boat for now
0484: if (repar.isEqual(estar)) {
0485: // Turn this down from Warn to DEBUG after ensuring we dont see this with the ReceiveNotificationLP change in place.
0486: if (logger.isDebugEnabled())
0487: logger
0488: .debug(getAgentIdentifier()
0489: + " NOT pubChanging AllocResult due to RepAR.isEqual(EstAR) but not ==. For PE: "
0490: + pe
0491: + ". Rep was != Est. Rep: "
0492: + repar);
0493: } else {
0494: publishChange(pe);
0495: }
0496: }
0497: }
0498: }
0499:
0500: protected void readXMLFile(String xmlFileString) {
0501: try {
0502: Document document = ConfigFinder.getInstance()
0503: .parseXMLConfigFile(xmlFileString);
0504: Element root = document.getDocumentElement();
0505: allCommands = parseCommands(root);
0506: } catch (java.io.IOException ioe) {
0507: ioe.printStackTrace();
0508: }
0509:
0510: }
0511:
0512: protected CommandInfo[] parseCommands(Element root) {
0513: Element[] commandElems = findChildElements(root, "command");
0514: CommandInfo[] commands = new CommandInfo[commandElems.length];
0515:
0516: for (int i = 0; i < commandElems.length; i++) {
0517: Element command = commandElems[i];
0518: Element task = findChildElement(command, "task");
0519: TaskInfo sourceTask = parseTaskInfo(task);
0520: Element commandAction;
0521: if ((commandAction = findChildElement(command, "allocate")) != null) {
0522: commands[i] = parseAllocate(commandAction, sourceTask);
0523: } else if ((commandAction = findChildElement(command,
0524: "expand")) != null) {
0525: commands[i] = parseExpand(commandAction, sourceTask);
0526: }
0527: }
0528:
0529: return commands;
0530: }
0531:
0532: protected TaskInfo parseTaskInfo(Element task) {
0533: String taskVerb = task.getAttribute("verb");
0534: Element taskPhrase = findChildElement(task, "phrase");
0535: if (taskPhrase != null) {
0536: String oftype = taskPhrase.getAttribute("oftype");
0537: if (oftype != null) {
0538: oftype = oftype.trim();
0539: if (oftype.length() <= 0)
0540: oftype = null;
0541: }
0542: String taskfor = taskPhrase.getAttribute("for");
0543: if (taskfor != null) {
0544: taskfor = taskfor.trim();
0545: if (taskfor.length() <= 0)
0546: taskfor = null;
0547: }
0548: return new TaskInfo(taskVerb, oftype, taskfor);
0549: } else {
0550: return new TaskInfo(taskVerb);
0551: }
0552: }
0553:
0554: protected AllocateCommandInfo parseAllocate(Node alloc,
0555: TaskInfo sourceTask) {
0556: AllocateCommandInfo retCom = new AllocateCommandInfo(sourceTask);
0557: Element clusterElem = findChildElement(alloc, "cluster");
0558: String clusterName;
0559: if ((clusterElem != null)
0560: && ((clusterName = clusterElem.getAttribute("name")) != null)) {
0561: // cluster name given
0562: retCom.allocateCluster = clusterName;
0563: } else {
0564: // get (role*)
0565: Element[] roleElems = findChildElements(alloc, "role");
0566: String[] allocateRoles = new String[roleElems.length];
0567: for (int j = 0; j < roleElems.length; j++) {
0568: String r = roleElems[j].getAttribute("name");
0569: allocateRoles[j] = r;
0570: }
0571: retCom.allocateRoles = allocateRoles;
0572: }
0573: Element defaultElem = findChildElement(alloc, "default");
0574: if (defaultElem != null) {
0575: retCom.defaultAlloc = parseAllocate(defaultElem, sourceTask);
0576: }
0577: return retCom;
0578: }
0579:
0580: protected ExpandCommandInfo parseExpand(Node expand,
0581: TaskInfo sourceTask) {
0582: Element[] taskElements = findChildElements(expand, "task");
0583: TaskInfo[] expandTasks = new TaskInfo[taskElements.length];
0584: for (int j = 0; j < taskElements.length; j++)
0585: expandTasks[j] = parseTaskInfo(taskElements[j]);
0586: ExpandCommandInfo retCom = new ExpandCommandInfo(sourceTask);
0587: retCom.expandTasks = expandTasks;
0588: return retCom;
0589: }
0590:
0591: protected UnaryPredicate[] createTaskPredicates(
0592: CommandInfo[] fromCommands) {
0593: int npreds = fromCommands.length;
0594: UnaryPredicate[] tPreds = new UnaryPredicate[npreds];
0595:
0596: for (int i = 0; i < npreds; i++) {
0597: CommandInfo c = fromCommands[i];
0598: TaskInfo st = c.sourceTask;
0599: if ((st.taskFor != null) || (st.ofType != null)) {
0600: tPreds[i] = newTaskPredicate(st.verb, st.taskFor,
0601: st.ofType);
0602: } else {
0603: tPreds[i] = newTaskPredicate(st.verb);
0604: }
0605: }
0606:
0607: return tPreds;
0608: }
0609:
0610: protected UnaryPredicate[] createAllocationPredicates(
0611: UnaryPredicate[] tPreds) {
0612: int npreds = tPreds.length;
0613: UnaryPredicate[] aPreds = new UnaryPredicate[npreds];
0614:
0615: for (int i = 0; i < npreds; i++) {
0616: aPreds[i] = newAllocationPredicate(tPreds[i]);
0617: }
0618:
0619: return aPreds;
0620: }
0621:
0622: protected static UnaryPredicate newTaskPredicate(final String verb) {
0623: return new UnaryPredicate() {
0624: public boolean execute(Object o) {
0625: if (o instanceof Task) {
0626: Task t = (Task) o;
0627: if ((t.getVerb()).equals(verb)) {
0628: return true;
0629: }
0630: }
0631: return false;
0632: }
0633: };
0634: }
0635:
0636: protected UnaryPredicate newTaskPredicate(final String verb,
0637: final String tfor, final String oftype) {
0638: return new UnaryPredicate() {
0639: public boolean execute(Object o) {
0640: if (o instanceof Task) {
0641: Task t = (Task) o;
0642: if ((t.getVerb()).equals(verb)) {
0643: if (checkForOfType(t, tfor, oftype)) {
0644: return true;
0645: }
0646: }
0647: }
0648: return false;
0649: }
0650: };
0651: }
0652:
0653: protected UnaryPredicate newAllocationPredicate(
0654: final UnaryPredicate taskPred) {
0655: return new UnaryPredicate() {
0656: public boolean execute(Object o) {
0657: if (o instanceof Allocation)
0658: return taskPred.execute(((Allocation) o).getTask());
0659: return false;
0660: }
0661: };
0662: }
0663:
0664: protected Element findChildElement(Node parent, String childname) {
0665: NodeList nlist = parent.getChildNodes();
0666: int nlength = nlist.getLength();
0667: for (int i = 0; i < nlength; i++) {
0668: Node tnode = (Node) nlist.item(i);
0669: if ((tnode.getNodeType() == Node.ELEMENT_NODE)
0670: && (tnode.getNodeName().equals(childname))) {
0671: return (Element) tnode;
0672: }
0673: }
0674: return null;
0675: }
0676:
0677: protected Element[] findChildElements(Node parent, String childname) {
0678: NodeList nlist = parent.getChildNodes();
0679: int nlength = nlist.getLength();
0680: Element[] sparseChildren = new Element[nlength];
0681: int nChildren = 0;
0682: for (int i = 0; i < nlength; i++) {
0683: Node tnode = (Node) nlist.item(i);
0684: if ((tnode.getNodeType() == Node.ELEMENT_NODE)
0685: && (tnode.getNodeName().equals(childname))) {
0686: sparseChildren[nChildren++] = (Element) tnode;
0687: }
0688: }
0689: Element[] fullChildren = new Element[nChildren];
0690: System.arraycopy(sparseChildren, 0, fullChildren, 0, nChildren);
0691: return fullChildren;
0692: }
0693:
0694: protected boolean checkForOfType(Task t, String pfor, String oftype) {
0695: if (oftype != null) {
0696: if (!(ExpanderHelper.isOfType(t,
0697: Constants.Preposition.OFTYPE, oftype)))
0698: return false;
0699: }
0700: if (pfor != null) {
0701: PrepositionalPhrase p = (PrepositionalPhrase) t
0702: .getPrepositionalPhrase(Constants.Preposition.FOR);
0703: if (p == null)
0704: return false;
0705: String hasFor;
0706: Object indObj = p.getIndirectObject();
0707: if (indObj instanceof MessageAddress)
0708: hasFor = ((MessageAddress) indObj).toString();
0709: else if (indObj instanceof Organization)
0710: hasFor = ((Organization) indObj).getMessageAddress()
0711: .toString();
0712: else
0713: hasFor = null;
0714: if (!(pfor.equals(hasFor)))
0715: return false;
0716: }
0717: return true;
0718: }
0719:
0720: // Search a single collection of allocations for one that allocates the given task
0721: protected PlanElement getTaskPlanElement(Task t, Collection allocs) {
0722: PlanElement tpe = null;
0723: Collection bPEs = null;
0724: if (logger.isInfoEnabled()) {
0725: tpe = t.getPlanElement();
0726: final Task pt = t;
0727: bPEs = query(new UnaryPredicate() {
0728: public boolean execute(Object o) {
0729: if (o instanceof Allocation) {
0730: Allocation a = (Allocation) o;
0731: return (a.getTask() == pt);
0732: }
0733: return false;
0734: }
0735: });
0736: }
0737:
0738: Iterator iter = allocs.iterator();
0739: while (iter.hasNext()) {
0740: PlanElement pe = (PlanElement) iter.next();
0741: if (pe.getTask().equals(t)) {
0742: if (logger.isInfoEnabled()) {
0743: boolean bboardHasPE = true;
0744: boolean bboardHasTPE = true;
0745:
0746: if (bPEs != null) {
0747: bboardHasPE = bPEs.contains(pe);
0748: bboardHasTPE = bPEs.contains(tpe);
0749: bPEs.remove(pe);
0750: bPEs.remove(tpe);
0751: if (!bPEs.isEmpty()) {
0752: logger
0753: .info("Blackboard has "
0754: + bPEs.size()
0755: + " Allocs of the task other than the one on GTPI sub or pointed to by the task: "
0756: + t);
0757:
0758: Iterator biter = bPEs.iterator();
0759: while (biter.hasNext()) {
0760: Allocation ba = (Allocation) biter
0761: .next();
0762: logger.info("GTPI found BBoard Alloc "
0763: + ba.getUID() + ":" + ba);
0764: }
0765: }
0766: }
0767:
0768: if (tpe == null) {
0769: logger.info("GTPI found Alloc on sub "
0770: + (bboardHasPE ? "also on blackboard"
0771: : "BUT NOT on blackboard")
0772: + " but task has NONE. Task: " + t
0773: + ", Sub Alloc: " + pe.getUID() + ":"
0774: + pe);
0775: } else if (tpe != pe) {
0776: boolean there = allocs.contains(tpe);
0777: // Does removed list contain the task's pe?
0778: boolean onRemoved = ((IncrementalSubscription) allocs)
0779: .getRemovedCollection().contains(tpe);
0780:
0781: logger
0782: .info("GTPI found one Alloc on sub for task, but task lists another"
0783: + (there ? " that is ALSO on the sub"
0784: : " that is NOT on the sub")
0785: + (onRemoved ? ", and IS on the Sub's Removed list"
0786: : "")
0787: + ". My Sub's Alloc "
0788: + (bboardHasPE ? "IS"
0789: : "is NOT")
0790: + "on the blackboard. The Task's PE "
0791: + (bboardHasTPE ? "IS"
0792: : "is NOT")
0793: + "on the blackboard. Task: "
0794: + t
0795: + ", Tasks pe: "
0796: + tpe.getUID()
0797: + ":"
0798: + tpe
0799: + ", Sub's PE: "
0800: + pe.getUID()
0801: + ":" + pe);
0802: } else {
0803: // Task and sub match
0804: if (!bboardHasPE)
0805: logger
0806: .info("GTPI found Alloc on sub also on Task, but it's not on the BBoard! Task: "
0807: + t
0808: + ", PE: "
0809: + pe.getUID() + ":" + pe);
0810: }
0811:
0812: // Does removed list contain this pe?
0813: boolean onRemoved = ((IncrementalSubscription) allocs)
0814: .getRemovedCollection().contains(pe);
0815: if (onRemoved) {
0816: logger
0817: .info("GTPI found alloc of task on sub, but the alloc is also on my Removed list! "
0818: + (bboardHasPE ? "Blackboard has the alloc!"
0819: : "(Blackboard also doesn't have the alloc.)")
0820: + " Task: "
0821: + t
0822: + ", found PE: "
0823: + pe.getUID()
0824: + ":" + pe);
0825: }
0826: } // end of Info logging
0827: return pe;
0828: } // end of block to handle found PE
0829: } // end of while loop over subscription
0830:
0831: // Found no Alloc on sub - will allocate the task
0832:
0833: if (logger.isInfoEnabled()) {
0834: if (tpe != null) {
0835: boolean tPBB = (bPEs != null && bPEs.contains(tpe));
0836: boolean onRemoved = ((IncrementalSubscription) allocs)
0837: .getRemovedCollection().contains(tpe);
0838: logger
0839: .info("No Alloc on GTPIs sub for a task, but the task lists a PE"
0840: + (onRemoved ? " which is on my sub's removed list"
0841: : "")
0842: + (tPBB ? " which IS on the blackboard"
0843: : " which is NOT on the blackboard")
0844: + ". Task: "
0845: + t
0846: + ", Task's PE: "
0847: + tpe.getUID() + ":" + tpe);
0848: }
0849:
0850: // Found no PE on sub
0851: if (bPEs != null && !bPEs.isEmpty()) {
0852: logger
0853: .info("No Alloc on GTPIs sub for a task, but blackboard has "
0854: + bPEs.size()
0855: + " allocs for the task: " + t);
0856: // Print out the PEs we did find!
0857: Iterator biter = bPEs.iterator();
0858: while (biter.hasNext()) {
0859: Allocation ba = (Allocation) biter.next();
0860: logger.info("GTPI found BBoard Alloc "
0861: + ba.getUID() + ":" + ba);
0862: }
0863: }
0864:
0865: } // end of info logging
0866:
0867: return null;
0868: }
0869:
0870: protected void allocate(AllocateCommandInfo commandInfo,
0871: Collection tasks, int subNum) {
0872: Organization capableOrg = null;
0873: for (Iterator iterator = tasks.iterator(); iterator.hasNext();) {
0874: Task task = (Task) iterator.next();
0875: if (getTaskPlanElement(task, allocationsSub[subNum]) == null) {
0876: if (capableOrg == null) {
0877: capableOrg = findCapableOrganization(commandInfo);
0878: if (capableOrg == null) {
0879: // no capable org found!
0880: if (logger.isDebugEnabled()) {
0881: logger
0882: .debug("allocate: Unable to find provider for "
0883: + commandInfo.allocateRoles);
0884: }
0885: break;
0886: }
0887: }
0888: doAllocation(capableOrg, task);
0889: } else {
0890: // sub has PE for this task
0891:
0892: }
0893: }
0894: }
0895:
0896: protected static UnaryPredicate newOrganizationPred() {
0897: return new UnaryPredicate() {
0898: public boolean execute(Object o) {
0899: return (o instanceof Organization);
0900: }
0901: };
0902: }
0903:
0904: protected static class TaskInfo {
0905: public String verb;
0906: public String ofType;
0907: public String taskFor;
0908:
0909: TaskInfo(String verb) {
0910: this .verb = verb;
0911: }
0912:
0913: TaskInfo(String verb, String ofType, String taskFor) {
0914: this .verb = verb;
0915: this .ofType = ofType;
0916: if (taskFor != null) {
0917: if (!(taskFor.startsWith("<")))
0918: taskFor = "<" + taskFor;
0919: if (!(taskFor.endsWith(">")))
0920: taskFor = taskFor + ">";
0921: }
0922: this .taskFor = taskFor;
0923: }
0924:
0925: public String toString() {
0926: String s = "verb: {" + verb + "}";
0927: if (ofType != null)
0928: s += " ofType: {" + ofType + "}";
0929: if (taskFor != null)
0930: s += " for: {" + taskFor + "}";
0931: return s;
0932: }
0933: }
0934:
0935: protected static class CommandInfo {
0936: public TaskInfo sourceTask;
0937: public int type_id;
0938:
0939: public static final int TYPE_NONE = -1;
0940: public static final int TYPE_ALLOCATE = 0;
0941: public static final int TYPE_EXPAND = 1;
0942:
0943: private CommandInfo() {
0944: type_id = TYPE_NONE;
0945: }
0946:
0947: public CommandInfo(TaskInfo sourceTask) {
0948: this ();
0949: this .sourceTask = sourceTask;
0950: }
0951:
0952: public String toString() {
0953: String s = "Command\n";
0954: s += " source: {" + sourceTask + "}\n";
0955: s += " type: {";
0956: switch (type_id) {
0957: default:
0958: case TYPE_NONE:
0959: s += "none";
0960: break;
0961: case TYPE_ALLOCATE:
0962: s += "allocate";
0963: break;
0964: case TYPE_EXPAND:
0965: s += "expand";
0966: break;
0967: }
0968: s += "}\n";
0969: return s;
0970: }
0971: }
0972:
0973: protected static class ExpandCommandInfo extends CommandInfo {
0974: public TaskInfo[] expandTasks;
0975:
0976: public ExpandCommandInfo(TaskInfo sourceTask) {
0977: super (sourceTask);
0978: type_id = TYPE_EXPAND;
0979: }
0980:
0981: public String toString() {
0982: String s = super .toString();
0983: s += " Expand\n";
0984: if (expandTasks != null) {
0985: s += " expand[" + expandTasks.length + "]: {\n";
0986: for (int i = 0; i < expandTasks.length; i++)
0987: s += " {" + expandTasks[i] + "}\n";
0988: s += " }.\n";
0989: }
0990: return s;
0991: }
0992: }
0993:
0994: protected static class AllocateCommandInfo extends CommandInfo {
0995: public String allocateCluster;
0996: public String[] allocateRoles;
0997: public AllocateCommandInfo defaultAlloc;
0998:
0999: public AllocateCommandInfo(TaskInfo sourceTask) {
1000: super (sourceTask);
1001: type_id = TYPE_ALLOCATE;
1002: }
1003:
1004: public String toString() {
1005: String s = super .toString();
1006: s += " Allocate\n";
1007: if (allocateCluster != null)
1008: s += " cluster: {" + allocateCluster + "}.\n";
1009: else {
1010: if (allocateRoles != null) {
1011: s += " roles[" + allocateRoles.length + "]: {\n";
1012: for (int i = 0; i < allocateRoles.length; i++)
1013: s += " {" + allocateRoles[i] + "}\n";
1014: s += " }.\n";
1015: }
1016: }
1017: if (defaultAlloc != null)
1018: s += "DEFAULT: {\n" + defaultAlloc + "}\n";
1019: return s;
1020: }
1021: }
1022:
1023: }
|