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.organization;
028:
029: import java.util.Collection;
030: import java.util.Enumeration;
031: import java.util.HashMap;
032: import java.util.HashSet;
033: import java.util.Iterator;
034: import java.util.Vector;
035:
036: import org.cougaar.core.blackboard.IncrementalSubscription;
037: import org.cougaar.glm.ldm.Constants;
038: import org.cougaar.glm.ldm.asset.Organization;
039: import org.cougaar.planning.ldm.asset.Asset;
040: import org.cougaar.planning.ldm.plan.Allocation;
041: import org.cougaar.planning.ldm.plan.AllocationResult;
042: import org.cougaar.planning.ldm.plan.Expansion;
043: import org.cougaar.planning.ldm.plan.HasRelationships;
044: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
045: import org.cougaar.planning.ldm.plan.NewTask;
046: import org.cougaar.planning.ldm.plan.NewWorkflow;
047: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
048: import org.cougaar.planning.ldm.plan.Relationship;
049: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
050: import org.cougaar.planning.ldm.plan.Role;
051: import org.cougaar.planning.ldm.plan.Task;
052: import org.cougaar.planning.ldm.plan.Workflow;
053: import org.cougaar.planning.plugin.legacy.SimplePlugin;
054: import org.cougaar.planning.plugin.util.PluginHelper;
055: import org.cougaar.util.Enumerator;
056: import org.cougaar.util.TimeSpan;
057: import org.cougaar.util.UnaryPredicate;
058:
059: /**
060: * Version of GLSAllocator without SD support, for use with minitestconfig, eg.
061: * Handles GLS for subordinates tasks. We expand such tasks into
062: * subtasks, one per subordinate. As our subordinates changes we
063: * revise the expansion to follow.
064: **/
065: public class GLSMiniAllocatorPlugin extends SimplePlugin {
066:
067: private IncrementalSubscription allocatableGLSTask = null;
068: private IncrementalSubscription orgAssets;
069: private IncrementalSubscription myAllocations;
070: private IncrementalSubscription myExpansions;
071: private String me = null;
072: private HashMap mySubs = new HashMap();
073:
074: //Override the setupSubscriptions() in the SimplePlugin.
075: protected void setupSubscriptions() {
076: me = getAgentIdentifier().getAddress();
077:
078: // subscribe for GLS tasks for subordinates
079: allocatableGLSTask = (IncrementalSubscription) subscribe(allocGLSPred);
080:
081: //subscribe for assets to allocate against
082: orgAssets = (IncrementalSubscription) subscribe(orgPred);
083:
084: // subscribe to my allocations and expansions in order to catch changes in the
085: // allocationresults from the notification process
086: myAllocations = (IncrementalSubscription) subscribe(myAllocsPred);
087: myExpansions = (IncrementalSubscription) subscribe(myExpsPred);
088:
089: if (didRehydrate()) {
090: Collection subs = retrieveSubOrgs(orgAssets.getCollection());
091: for (Iterator iterator = subs.iterator(); iterator
092: .hasNext();) {
093: Organization org = (Organization) iterator.next();
094: mySubs.put(org.getUID(), org);
095: }
096: }
097: }
098:
099: /**
100: * Process new tasks and subordinates as follows: New tasks are
101: * expanded to subtasks for each known subordinate. New
102: * subordinates have tasks appended to known expansions.
103: * Duplication is avoided when new tasks and new subordinates arrive
104: * together because the expansions for the new tasks don't yet
105: * exist.
106: **/
107: public synchronized void execute() {
108: if (allocatableGLSTask.hasChanged()) {
109: Enumeration tasks = allocatableGLSTask.getAddedList();
110:
111: Collection subs = retrieveSubOrgs(orgAssets.getCollection());
112: while (tasks.hasMoreElements()) {
113: Task task = (Task) tasks.nextElement();
114: expandGLS(task, new Enumerator(subs));
115: }
116: }
117:
118: // check the asset container for new Subordinates
119: if (orgAssets.hasChanged()) {
120: /**
121: * When a new subordinate appears we must modify the existing
122: * expansions to include the new subordinate.
123: **/
124: Collection newSubs = retrieveSubOrgs(orgAssets
125: .getCollection());
126:
127: for (Iterator iterator = newSubs.iterator(); iterator
128: .hasNext();) {
129: Organization org = (Organization) iterator.next();
130:
131: // Remove from set if we already know about it
132: if (mySubs.get(org.getUID()) != null) {
133: iterator.remove();
134: } else {
135: mySubs.put(org.getUID(), org);
136: }
137: }
138:
139: for (Enumeration expansions = myExpansions.elements(); expansions
140: .hasMoreElements();) {
141: Expansion exp = (Expansion) expansions.nextElement();
142:
143: augmentExpansion(exp, new Enumerator(newSubs));
144: }
145: /** Should handle removed assets, too **/
146: }
147:
148: if (myAllocations.hasChanged()) {
149: PluginHelper.updateAllocationResult(myAllocations);
150: }
151:
152: if (myExpansions.hasChanged()) {
153: PluginHelper.updateAllocationResult(myExpansions);
154: }
155: } // end of execute
156:
157: /**
158: * Allocate the unallocated subtasks of a workflow
159: **/
160: private void allocateGLS(Workflow wf) {
161: Enumeration tasks = wf.getTasks();
162: while (tasks.hasMoreElements()) {
163: Task t = (Task) tasks.nextElement();
164: if (t.getPlanElement() != null)
165: continue; // Already allocated
166: Enumeration pp = t.getPrepositionalPhrases();
167: while (pp.hasMoreElements()) {
168: PrepositionalPhrase p = (PrepositionalPhrase) pp
169: .nextElement();
170: if (p.getPreposition()
171: .equals(Constants.Preposition.FOR)) {
172: if (p.getIndirectObject() instanceof Organization) {
173: Asset a = (Asset) p.getIndirectObject();
174: AllocationResult estimatedresult = PluginHelper
175: .createEstimatedAllocationResult(t,
176: theLDMF, 0.0, true);
177: Allocation alloc = theLDMF.createAllocation(
178: theLDMF.getRealityPlan(), t, a,
179: estimatedresult, Role.BOGUS);
180: publishAdd(alloc);
181: break; // Terminate processing of prep phrases
182: }
183: }
184: }
185: }
186: }
187:
188: /**
189: * Expand a new GLS task to include the given subordinates.
190: **/
191: private void expandGLS(Task t, Enumeration esubs) {
192: NewWorkflow wf = theLDMF.newWorkflow();
193: //wf.setIsPropagatingToSubtasks();
194: wf.setParentTask(t);
195:
196: // Add tasks to workflow but do not publish them. Done later in the call
197: // to PluginHelper.publishAddExpansion();
198: augmentWorkflow(wf, esubs, false);
199: // package up the workflow in an expansion
200: AllocationResult estAR = null;
201: if (!esubs.hasMoreElements()) {
202: estAR = PluginHelper.createEstimatedAllocationResult(t,
203: theLDMF, 1.0, true);
204: }
205: Expansion exp = theLDMF.createExpansion(theLDMF
206: .getRealityPlan(), t, wf, estAR);
207: //publish the Expansion and the workflow tasks all in one
208: PluginHelper.publishAddExpansion(getSubscriber(), exp);
209: //now allocate the tasks in the new workflow
210: allocateGLS(wf);
211: }
212:
213: private void augmentWorkflow(NewWorkflow wf, Enumeration esubs,
214: boolean publishInPlace) {
215: while (esubs.hasMoreElements()) {
216: Asset orga = (Asset) esubs.nextElement();
217: NewTask newTask = createSubTask(wf.getParentTask(), orga);
218: newTask.setWorkflow(wf);
219: wf.addTask(newTask);
220: if (publishInPlace) {
221: publishAdd(newTask);
222: }
223: }
224: }
225:
226: static final Role cinc = Role.getRole("CINC");
227:
228: private synchronized void augmentExpansion(Expansion exp,
229: Enumeration esubs) {
230: if (esubs.hasMoreElements()) {
231: NewWorkflow wf = (NewWorkflow) exp.getWorkflow();
232:
233: // Add tasks to workflow and publish new tasks
234: augmentWorkflow(wf, esubs, true);
235:
236: publishChange(wf);
237: allocateGLS(wf);
238: }
239: }
240:
241: /**
242: * Create a subtask that matches the given Task plus a FOR
243: * Organization phrase.
244: **/
245: private NewTask createSubTask(Task t, Asset subasset) {
246: Vector prepphrases = new Vector();
247:
248: NewTask subtask = theLDMF.newTask();
249:
250: // Create copy of parent Task
251: subtask.setParentTask(t);
252: if (t.getDirectObject() != null) {
253: subtask.setDirectObject(theLDMF.cloneInstance(t
254: .getDirectObject()));
255: } else {
256: subtask.setDirectObject(null);
257: }
258:
259: // Code removed because oplan is in context
260: // pull out the "with OPlan" prep phrase and store for later
261: Enumeration origpp = t.getPrepositionalPhrases();
262: while (origpp.hasMoreElements()) {
263: PrepositionalPhrase theorigpp = (PrepositionalPhrase) origpp
264: .nextElement();
265: if (theorigpp.getPreposition().equals("WithC0")) {
266: prepphrases.addElement(theorigpp);
267: }
268: }
269:
270: NewPrepositionalPhrase newpp = theLDMF.newPrepositionalPhrase();
271: newpp.setPreposition(Constants.Preposition.FOR);
272: newpp.setIndirectObject(theLDMF.cloneInstance(subasset));
273: prepphrases.addElement(newpp);
274: subtask.setPrepositionalPhrases(prepphrases.elements());
275:
276: subtask.setVerb(t.getVerb());
277: subtask.setPlan(t.getPlan());
278: // for now set the preferences the same as the parent task's
279: // in a real expander you would want to distribute the parents preferences
280: // across the subtasks.
281: subtask.setPreferences(t.getPreferences());
282: subtask.setSource(this .getAgentIdentifier());
283:
284: return subtask;
285:
286: }
287:
288: /**
289: * Select Tasks that are GETLOGSUPPORT FOR Asset where the Asset is
290: * identified as "Subordinates"
291: **/
292: public static UnaryPredicate allocGLSPred = new UnaryPredicate() {
293: public boolean execute(Object o) {
294: if (o instanceof Task) {
295: Task t = (Task) o;
296: if (t.getVerb().equals(Constants.Verb.GetLogSupport)) {
297: PrepositionalPhrase app = t
298: .getPrepositionalPhrase(Constants.Preposition.FOR);
299: if (app != null) {
300: Object indObject = app.getIndirectObject();
301: if (indObject instanceof Asset) {
302: Asset asset = (Asset) indObject;
303: try {
304: return asset.getTypeIdentificationPG()
305: .getTypeIdentification()
306: .equals("Subordinates");
307: } catch (Exception e) {
308: System.out
309: .println("GLSMiniAlloc error while trying to get the TypeIdentification of an asset");
310: e.printStackTrace();
311: }
312: }
313: }
314: }
315: }
316: return false;
317: }
318: };
319:
320: /**
321: * Select all Organization assets
322: **/
323: public static UnaryPredicate orgPred = new UnaryPredicate() {
324: public boolean execute(Object o) {
325: if (o instanceof Organization) {
326: return true;
327: } else {
328: return false;
329: }
330: }
331: };
332:
333: public static Collection retrieveSubOrgs(Collection orgs) {
334: HashSet subs = new HashSet(3);
335:
336: Iterator iterator = orgs.iterator();
337: while (iterator.hasNext()) {
338: Organization org = (Organization) iterator.next();
339:
340: if (org.isSelf()) {
341: RelationshipSchedule schedule = org
342: .getRelationshipSchedule();
343: Collection orgCollection = org.getSubordinates(
344: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
345:
346: if (orgCollection.size() > 0) {
347: for (Iterator relIterator = orgCollection
348: .iterator(); relIterator.hasNext();) {
349: Relationship relationship = (Relationship) relIterator
350: .next();
351: HasRelationships sub = schedule
352: .getOther(relationship);
353:
354: if (!subs.contains(sub)) {
355: subs.add(sub);
356: }
357: }
358: }
359:
360: /** BOZO - how would this relationship ever get created?
361: **/
362: orgCollection = schedule.getMatchingRelationships(cinc
363: .getConverse(), TimeSpan.MIN_VALUE,
364: TimeSpan.MAX_VALUE);
365: if (orgCollection.size() > 0) {
366: for (Iterator relIterator = orgCollection
367: .iterator(); relIterator.hasNext();) {
368: Relationship relationship = (Relationship) relIterator
369: .next();
370: HasRelationships sub = schedule
371: .getOther(relationship);
372:
373: if (!subs.contains(sub)) {
374: subs.add(sub);
375: }
376: }
377: }
378: }
379: }
380: return subs;
381: }
382:
383: /**
384: * Select all the allocations we create. These are allocations of
385: * GETLOGSUPPORT tasks whose parent task is selected by the
386: * allocGLSPred
387: **/
388: public static UnaryPredicate myAllocsPred = new UnaryPredicate() {
389: public boolean execute(Object o) {
390: if (o instanceof Allocation) {
391: Task t = ((Allocation) o).getTask();
392: if (t.getVerb().equals(Constants.Verb.GETLOGSUPPORT)) {
393: // return allocGLSPred.execute(t.getParentTask());
394: return true;
395: }
396: }
397: return false;
398: }
399: };
400:
401: /**
402: * Select the expansions we create. These are expansions of the
403: * tasks selected by allocGLSPred.
404: **/
405: public static UnaryPredicate myExpsPred = new UnaryPredicate() {
406: public boolean execute(Object o) {
407: if (o instanceof Expansion) {
408: return allocGLSPred.execute(((Expansion) o).getTask());
409: }
410: return false;
411: }
412: };
413: }
|