001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 TASC
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: package org.cougaar.glm.plugins.multiplesuppliers;
027:
028: import java.util.Collection;
029: import java.util.Enumeration;
030: import java.util.Iterator;
031: import java.util.Vector;
032:
033: import org.cougaar.glm.ldm.Constants;
034: import org.cougaar.glm.ldm.asset.Organization;
035: import org.cougaar.glm.ldm.asset.OrganizationPG;
036: import org.cougaar.planning.ldm.PlanningFactory;
037: import org.cougaar.planning.ldm.asset.Asset;
038: import org.cougaar.planning.ldm.plan.Allocation;
039: import org.cougaar.planning.ldm.plan.AllocationResult;
040: import org.cougaar.planning.ldm.plan.AspectType;
041: import org.cougaar.planning.ldm.plan.Disposition;
042: import org.cougaar.planning.ldm.plan.HasRelationships;
043: import org.cougaar.planning.ldm.plan.NewPrepositionalPhrase;
044: import org.cougaar.planning.ldm.plan.NewTask;
045: import org.cougaar.planning.ldm.plan.Preference;
046: import org.cougaar.planning.ldm.plan.PrepositionalPhrase;
047: import org.cougaar.planning.ldm.plan.Relationship;
048: import org.cougaar.planning.ldm.plan.RelationshipSchedule;
049: import org.cougaar.planning.ldm.plan.Role;
050: import org.cougaar.planning.ldm.plan.Task;
051: import org.cougaar.planning.ldm.plan.Workflow;
052: import org.cougaar.util.TimeSpan;
053:
054: /**
055: * This Utility class consists of "public final static" methods that perform various useful Cougaar tasks.
056: * In particular, this class contains methods for cloning tasks, creating subtasks, allocation results and failed allocations.
057: * There are also methods that return specific Organization assets with desired capabilities, roles or even by name.
058: */
059: public final class Utility {
060:
061: /**
062: * Obtain reference to last subtask in a workflow. Useful if you need to add a new task to a workflow
063: * with aspects of the new task based on that last task or its allocation results.
064: *
065: * @param workflow to find last subtask of.
066: * @return the last task in the workflow
067: */
068: public final static Task getLastSubtaskInWorkflow(Workflow workflow) {
069: Enumeration subtasks = workflow.getTasks();
070: Task lastSubtask = null;
071: while (subtasks.hasMoreElements()) {
072: lastSubtask = (Task) subtasks.nextElement();
073: }
074: return lastSubtask;
075: }
076:
077: /**
078: * Create a new subtask using the grammatical elements of the input task,
079: * further establishing the input task as the parent of the new subtask.
080: *
081: * @param factory reference to cluster's PlanningFactory
082: * @param task the task whose grammatical elements will be used
083: * to create a new Task object.
084: * @return A newly created Task patterned from an input task.
085: */
086: public final static NewTask createSubtaskFromTask(
087: PlanningFactory factory, Task task) {
088: return createSubtaskFromTask(factory, task, null);
089: }
090:
091: /**
092: * Create a new subtask using the grammatical elements of the input task,
093: * further establishing the input task as the parent of the new subtask.
094: *
095: * @param factory reference to cluster's PlanningFactory
096: * @param task the task whose grammatical elements will be used
097: * to create a new Task object.
098: * @param prepositionsToExclude a list of prepositional phrases that should not be copied from
099: * the original task to the new task.
100: * @return A newly created Task patterned from an input task.
101: */
102: public final static NewTask createSubtaskFromTask(
103: PlanningFactory factory, Task task,
104: String[] prepositionsToExclude) {
105: NewTask subtask = cloneTask(factory, task,
106: prepositionsToExclude);
107: subtask.setParentTaskUID(task.getUID());
108: subtask.setWorkflow(null);
109: return subtask;
110: }
111:
112: /**
113: * Create a new Task object using the grammatical elements of the input task.
114: * For prepositional phrases with indirect objects that are instances of Vector,
115: * a new Vector is created for the clone. The contents of the original Vector are
116: * copied by reference to the new Vector. This way, the new Vector's content can
117: * be changed without effecting the original Vector.
118: *
119: * @param factory reference to cluster's PlanningFactory
120: * @param task the task whose grammatical elements will be used
121: * to create a new Task object.
122: * @return A newly created Task patterned from an input task.
123: */
124: public final static NewTask cloneTask(PlanningFactory factory,
125: Task task) {
126: return cloneTask(factory, task, null);
127: }
128:
129: /**
130: * Create a new Task object using the grammatical elements of the input task.
131: * For prepositional phrases with indirect objects that are instances of Vector,
132: * a new Vector is created for the clone. The contents of the original Vector are
133: * copied by reference to the new Vector. This way, the new Vector's content can
134: * be changed without effecting the original Vector.
135: *
136: * @param factory reference to cluster's PlanningFactory
137: * @param task the task whose grammatical elements will be used
138: * to create a new Task object.
139: * @param prepositionsToExclude a list of prepositional phrases that should not be copied from
140: * the original task to the new task.
141: * @return A newly created Task patterned from an input task.
142: */
143: public final static NewTask cloneTask(PlanningFactory factory,
144: Task task, String[] prepositionsToExclude) {
145: Enumeration en = null;
146: NewTask subtask = factory.newTask();
147: subtask.setContext(task.getContext());
148: subtask.setPlan(task.getPlan());
149: subtask.setParentTaskUID(task.getParentTaskUID());
150: subtask.setVerb(task.getVerb());
151: subtask.setDirectObject(task.getDirectObject());
152: subtask.setWorkflow(task.getWorkflow());
153:
154: en = task.getPrepositionalPhrases();
155: if (en != null) {
156: Vector pPhrases = new Vector();
157: NewPrepositionalPhrase clonePhrase;
158: while (en.hasMoreElements()) {
159: PrepositionalPhrase pPhrase = (PrepositionalPhrase) en
160: .nextElement();
161:
162: // Don't include prepositional phrases in the new task that are listed in prepositionsToExclude.
163: if (prepositionsToExclude != null) {
164: boolean skipPreposition = false;
165: String preposition = pPhrase.getPreposition();
166: for (int i = 0; i < prepositionsToExclude.length
167: && !skipPreposition; i++) {
168: String tmpPreposition = (String) prepositionsToExclude[i];
169: if (tmpPreposition != null
170: && tmpPreposition.equals(preposition)) {
171: skipPreposition = true;
172: }
173: }
174: if (skipPreposition) {
175: continue;
176: }
177: }
178:
179: clonePhrase = factory.newPrepositionalPhrase();
180: clonePhrase.setPreposition(pPhrase.getPreposition());
181: Object object = pPhrase.getIndirectObject();
182: if (object instanceof Vector) {
183: Vector orgVector = (Vector) object;
184: Class vectorClass = object.getClass();
185: Vector newVector = null;
186: try {
187: newVector = (Vector) vectorClass.newInstance();
188: } catch (Exception ex) {
189: System.out
190: .println("PlanElements.cloneTask: unable to create newVector instance");
191: return null;
192: }
193: Enumeration tmpEn = orgVector.elements();
194: while (tmpEn.hasMoreElements()) {
195: newVector.add(tmpEn.nextElement());
196: }
197: clonePhrase.setIndirectObject(newVector);
198: } else {
199: clonePhrase.setIndirectObject(object);
200: }
201: pPhrases.addElement(clonePhrase);
202: }
203: subtask.setPrepositionalPhrases(pPhrases.elements());
204: }
205:
206: en = task.getPreferences();
207: if (en != null) {
208: Vector preferences = new Vector();
209: Preference clonePreference;
210: while (en.hasMoreElements()) {
211: Preference preference = (Preference) en.nextElement();
212: clonePreference = factory.newPreference(preference
213: .getAspectType(), preference
214: .getScoringFunction());
215: preferences.addElement(clonePreference);
216: }
217: subtask.setPreferences(preferences.elements());
218: }
219:
220: return subtask;
221: }
222:
223: /**
224: * Create an Failed Disposition object associated with a task.
225: *
226: * @param factory reference to cluster's PlanningFactory
227: * @param task the task to be associated with the Disposition.
228: * @return a Failed Disposition object associated with the task
229: */
230: public final static Disposition makeFailedDisposition(
231: PlanningFactory factory, Task task) {
232: AllocationResult failedAR = createAllocationResult(factory,
233: false, task.getPreferredValue(AspectType.START_TIME),
234: task.getPreferredValue(AspectType.END_TIME), 0, 0);
235: Disposition falloc = factory.createFailedDisposition(task
236: .getPlan(), task, failedAR);
237: return falloc;
238: }
239:
240: /**
241: * Create an Allocation object (incorporating COST, QUANTITY and SCHEDULE).
242: *
243: * @param factory reference to cluster's PlanningFactory
244: * @param task the task being disposed of by this Allocation.
245: * @param asset used to perform the task
246: * @param cost the value to set the COST aspect value to
247: * @param quantity the value to set the QUANTITY aspect value to
248: *
249: * @return an Allocation object which is the disposition of the input task
250: */
251: public final static Allocation createAllocation(
252: PlanningFactory factory, Task task, Asset asset,
253: double cost, double quantity) {
254: return createAllocation(factory, task, asset, cost, quantity,
255: null);
256: }
257:
258: /**
259: * Create an Allocation object (incorporating COST, QUANTITY, SCHEDULE, and associated Role).
260: *
261: * @param factory reference to cluster's PlanningFactory
262: * @param task the task being disposed of by this Allocation.
263: * @param asset used to perform the task
264: * @param cost the value to set the COST aspect value to
265: * @param quantity the value to set the QUANTITY aspect value to
266: * @param roleOfAsset the role of the asset performing this task. If roleOfAsset is null,
267: * Role.BOGUS will be used.
268: * @return an Allocation object which is the disposition of the input task
269: */
270: public final static Allocation createAllocation(
271: PlanningFactory factory, Task task, Asset asset,
272: double cost, double quantity, Role roleOfAsset) {
273: AllocationResult estAllocResult = null;
274: if (!(asset instanceof Organization)
275: || task.getVerb().toString().equals(
276: Constants.Verb.INFORM)) {
277: double startTime = task
278: .getPreferredValue(AspectType.START_TIME);
279: double endTime = task
280: .getPreferredValue(AspectType.END_TIME);
281: estAllocResult = createAllocationResult(factory, true,
282: startTime, endTime, cost, quantity);
283: }
284:
285: Role role = roleOfAsset;
286: if (role == null) {
287: role = Role.BOGUS;
288: }
289: Allocation allocation = factory.createAllocation(factory
290: .getRealityPlan(), task, asset, estAllocResult, role);
291: return allocation;
292: }
293:
294: /**
295: * Create an AllocationResult object (incorporating START_TIME, END_TIME, COST and QUANTITY).
296: * This method sets confidence rating to 1.0.
297: *
298: * @param factory reference to cluster's PlanningFactory
299: * @param successFlag success value to associate with this allocation result.
300: * @param startTime of this allocation
301: * @param endTime of this allocation
302: * @param cost the value to set the COST aspect value to
303: * @param quantity the value to set the QUANTITY aspect value to
304: * @return an AllocationResult object with aspect set to input values
305: */
306: public final static AllocationResult createAllocationResult(
307: PlanningFactory factory, boolean successFlag,
308: double startTime, double endTime, double cost,
309: double quantity) {
310: double[] resultsarray = new double[4];
311:
312: resultsarray[0] = startTime;
313: resultsarray[1] = endTime;
314: resultsarray[2] = cost;
315: resultsarray[3] = quantity;
316: return factory.newAllocationResult(1.0, successFlag,
317: AspectType.CommonAspects, resultsarray);
318: }
319:
320: /**
321: * Return Task with the given UID.
322: *
323: * @param tasks list of Tasks to choose from.
324: * @param uid the UID of the desired Task.
325: * @return Task with given UID.
326: */
327: public final static Task getTaskWithUID(Enumeration tasks,
328: String uid) {
329: Task retTask = null;
330: while (tasks.hasMoreElements() && retTask == null) {
331: Task tmpTask = (Task) tasks.nextElement();
332: if (tmpTask.getUID().toString().equals(uid)) {
333: retTask = tmpTask;
334: }
335: }
336: return retTask;
337: }
338:
339: /**
340: * Return Organization with the given name.
341: *
342: * @param organizationName the name of the desired organization.
343: * @param organizationAssets list of Organizations to choose from.
344: * @return Organization with given name.
345: */
346: public final static Organization findNamedOrganization(
347: String organizationName, Enumeration organizationAssets) {
348: Organization retOrganization = null;
349: while (retOrganization == null
350: && organizationAssets.hasMoreElements()) {
351: Organization org = (Organization) organizationAssets
352: .nextElement();
353: if (org.getItemIdentificationPG().getNomenclature().equals(
354: organizationName)) {
355: retOrganization = org;
356: }
357: }
358: return retOrganization;
359: }
360:
361: /**
362: * Return Collection of Organization's roles.
363: *
364: * @param organization the Organization to find Roles for.
365: * @return list of Roles associated with input Organization.
366: */
367: public final static Collection getOrganizationRoles(
368: Organization organization) {
369: OrganizationPG organizationPG = organization
370: .getOrganizationPG();
371: if (organizationPG != null) {
372: return organizationPG.getRoles();
373: }
374: return null;
375: }
376:
377: /**
378: * Does the input Organization have the desired Role?
379: *
380: * @param organization the Organization to test for desired Role.
381: * @param testrole the desired Role to test for.
382: * @return true/false - Does the input Organization have the desired Role?
383: */
384: public final static boolean testCapableRole(
385: Organization organization, String testrole) {
386: Collection caproles = getOrganizationRoles(organization);
387: if (caproles != null
388: && caproles.contains(Role.getRole(testrole))) {
389: return true;
390: }
391: return false;
392: }
393:
394: /**
395: * Obtain a list or Organizations with a particular Role.
396: *
397: * @param testCapableRole the Role to find matching Organizations for.
398: * @param organizationAssets list of Organizations to choose from.
399: * @return list or Organizations with a desired Role.
400: */
401: public final static Enumeration findOrgsWithCapability(
402: String testCapableRole, Enumeration organizationAssets) {
403: Vector orgsWithCapableRole = new Vector();
404: while (organizationAssets.hasMoreElements()) {
405: Organization org = (Organization) organizationAssets
406: .nextElement();
407: if (testCapableRole(org, testCapableRole) == true) {
408: orgsWithCapableRole.add(org);
409: }
410: }
411: return orgsWithCapableRole.elements();
412: }
413:
414: /**
415: * Obtain list of Administrative Subordinates for an organization.
416: *
417: * @param org whose Administrative Subordinates to find
418: * @return the list of Administrative Subordinates
419: */
420: public final static Enumeration getAdministrativeSubordinates(
421: Organization org) {
422: Vector subs = new Vector();
423:
424: RelationshipSchedule schedule = org.getRelationshipSchedule();
425: Collection orgCollection = schedule.getMatchingRelationships(
426: Constants.Role.ADMINISTRATIVESUBORDINATE,
427: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
428:
429: if (orgCollection.size() > 0) {
430: for (Iterator relIterator = orgCollection.iterator(); relIterator
431: .hasNext();) {
432: Relationship relationship = (Relationship) relIterator
433: .next();
434: HasRelationships sub = schedule.getOther(relationship);
435: if (!subs.contains(sub)) {
436: subs.add(sub);
437: }
438: }
439: }
440: return subs.elements();
441: }
442:
443: /**
444: * Obtain list of Administrative Superiors for an organization.
445: *
446: * @param org whose Administrative Superiors to find
447: * @return the list of Administrative Superiors
448: */
449: public final static Enumeration getAdministrativeSuperiors(
450: Organization org) {
451: Vector subs = new Vector();
452:
453: RelationshipSchedule schedule = org.getRelationshipSchedule();
454: Collection orgCollection = schedule.getMatchingRelationships(
455: Constants.Role.ADMINISTRATIVESUPERIOR,
456: TimeSpan.MIN_VALUE, TimeSpan.MAX_VALUE);
457:
458: if (orgCollection.size() > 0) {
459: for (Iterator relIterator = orgCollection.iterator(); relIterator
460: .hasNext();) {
461: Relationship relationship = (Relationship) relIterator
462: .next();
463: HasRelationships sub = schedule.getOther(relationship);
464: if (!subs.contains(sub)) {
465: subs.add(sub);
466: }
467: }
468: }
469: return subs.elements();
470: }
471:
472: /**
473: * Determine if two AllocationResult objects are equal by comparing
474: * START_TIME, END_TIME, COST and QUNATITY.
475: *
476: * @param ar1 1st AllocationResult in comparison.
477: * @param ar2 2nd AllocationResult in comparison.
478: * @return true/false are the AllocationResults equals?
479: */
480: public final static boolean equalResults(AllocationResult ar1,
481: AllocationResult ar2) {
482: if (ar1 == null && ar2 == null) {
483: return true;
484: } else if (ar1 == null && ar2 != null || ar1 != null
485: && ar2 == null) {
486: return false;
487: }
488:
489: int[] aspects = ar1.getAspectTypes();
490: for (int i = 0; i < aspects.length; i++) {
491: if (ar1.isDefined(AspectType.START_TIME)) {
492: if (ar2.isDefined(AspectType.START_TIME)) {
493: if (ar1.getValue(AspectType.START_TIME) != ar2
494: .getValue(AspectType.START_TIME)) {
495: return false;
496: }
497: } else {
498: return false;
499: }
500: }
501: if (ar1.isDefined(AspectType.END_TIME)) {
502: if (ar2.isDefined(AspectType.END_TIME)) {
503: if (ar1.getValue(AspectType.END_TIME) != ar2
504: .getValue(AspectType.END_TIME)) {
505: return false;
506: }
507: } else {
508: return false;
509: }
510: }
511: if (ar1.isDefined(AspectType.QUANTITY)) {
512: if (ar2.isDefined(AspectType.QUANTITY)) {
513: if (ar1.getValue(AspectType.QUANTITY) != ar2
514: .getValue(AspectType.QUANTITY)) {
515: return false;
516: }
517: } else {
518: return false;
519: }
520: }
521: if (ar1.isDefined(AspectType.COST)) {
522: if (ar2.isDefined(AspectType.COST)) {
523: if (ar1.getValue(AspectType.COST) != ar2
524: .getValue(AspectType.COST)) {
525: return false;
526: }
527: } else {
528: return false;
529: }
530: }
531: }
532: return true;
533: }
534: }
|