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: package org.cougaar.glm.execution.eg;
027:
028: import org.cougaar.planning.ldm.plan.AspectType;
029: import org.cougaar.core.util.UID;
030: import org.cougaar.util.OptionPane;
031: import java.io.IOException;
032: import java.util.ArrayList;
033: import java.util.Collection;
034: import java.util.HashMap;
035: import java.util.HashSet;
036: import java.util.Iterator;
037: import java.util.SortedSet;
038: import java.util.TreeSet;
039: import javax.swing.JComponent;
040: import javax.swing.table.TableModel;
041: import org.cougaar.glm.execution.common.*;
042:
043: /**
044: * Keeps track of the TaskEventReports and decide if/when to
045: * generate a report.
046: **/
047: public class TaskEventReportManager extends ManagerBase implements
048: ScheduleManager {
049: public TaskEventReportManager(EventGenerator anEventGenerator) {
050: super (anEventGenerator);
051: }
052:
053: protected String getLogFileName(String prefix) {
054: return prefix + "TaskEvents" + LOGFILE_SUFFIX;
055: }
056:
057: public String getGUITitle() {
058: return "TaskEvent Reports";
059: }
060:
061: public FilterGUI createFilterGUI(EventGenerator anEventGenerator) {
062: return new TaskEventFilterGUI(anEventGenerator);
063: }
064:
065: public Object[] getHandlers() {
066: return new Object[] { new EGTaskEventReportHandler(this ), };
067: }
068:
069: protected Class getPluginInterface() {
070: return TaskEventPlugin.class;
071: }
072:
073: protected Class getDefaultPluginClass() {
074: return TaskEventDefaultPlugin.class;
075: }
076:
077: private void applyPlugins(TimedTaskEventReport tter) {
078: long theExecutionTime = theEventGenerator.getExecutionTime();
079: for (Iterator i = getEnabledPlugins(); i.hasNext();) {
080: TaskEventPlugin thePlugin = (TaskEventPlugin) i.next();
081: if (thePlugin.apply(tter, theExecutionTime))
082: return;
083: }
084: }
085:
086: public void receiveTaskEventReports(String source,
087: TaskEventReport[] taskEventReports) {
088: long executionTime = theEventGenerator.getExecutionTime();
089: Collection taskUIDs = new HashSet();
090: for (int i = 0; i < taskEventReports.length; i++) {
091: TaskEventReport ter = taskEventReports[i];
092: taskUIDs.add(ter.theTaskEventId.theTaskUID);
093: Object key = TimedTaskEventReport.getKey(source, ter);
094: TimedTaskEventReport tter = (TimedTaskEventReport) map
095: .get(key);
096: if (tter != null) {
097: removeFromSchedule(tter);
098: }
099: if (!ter.isRescind()) {
100: if (tter != null) {
101: tter.theTaskEventReport = ter;
102: } else {
103: tter = new TimedTaskEventReport(source, ter, this );
104: }
105: applyPlugins(tter);
106: addToSchedule(tter);
107: }
108: }
109: finishScheduleUpdate();
110: try {
111: sendTaskConstraintRequest(source, taskUIDs);
112: } catch (IOException ioe) {
113: ioe.printStackTrace();
114: }
115: }
116:
117: protected void removeFromSchedule(Timed timed) {
118: TimedTaskEventReport tter = (TimedTaskEventReport) timed;
119: changeEventGroup(tter, null);
120: super .removeFromSchedule(timed);
121: }
122:
123: public void sendTaskEventReport(String source,
124: TaskEventReport aTaskEventReport) throws IOException {
125: Object[] handlers = {}; // There is no response
126: EventMonitorListener l = theEventGenerator
127: .createEventMonitorListener(source, handlers,
128: aTaskEventReport);
129: if (l != null) {
130: theEventGenerator.addListener(l);
131: theEventGenerator.startListener(l);
132: }
133: }
134:
135: /**
136: * Process a new set of inter-event constraints. For each element,
137: * find the task events named by the task event ids and their
138: * current groups, if any. If the groups are both null, create a new
139: * group and assign both task events to it. If one group is null and
140: * the other isn't assign the task event that is not yet in a group
141: * to the group of the other task event. If both groups are non-null
142: * and identical, do nothing. If both groups are non-null and
143: * different reassign all task events of one group to the other.
144: **/
145: public synchronized void receiveConstraintElements(String source,
146: ConstraintElement[] constraints) {
147: for (int i = 0; i < constraints.length; i++) {
148: ConstraintElement e = constraints[i];
149: TimedTaskEventReport this TTER = (TimedTaskEventReport) map
150: .get(e.this EventId);
151: if (this TTER == null)
152: continue; // Haven't received this yet
153: TimedTaskEventReport thatTTER = (TimedTaskEventReport) map
154: .get(e.thatEventId);
155: if (thatTTER == null)
156: continue; // Haven't received that yet
157: if (this TTER.theEventGroup == null) {
158: if (thatTTER.theEventGroup == null) {
159: // Neither event has a group yet; create a new group for both
160: EventGroup newEventGroup = new EventGroup(
161: this TTER.theTaskEventReport.theTaskEventId);
162: changeEventGroup(this TTER, newEventGroup);
163: changeEventGroup(thatTTER, newEventGroup);
164: // System.out.println("New event group " + newEventGroup);
165: } else {
166: // thatEventGroup exists; add thisTTER to it
167: changeEventGroup(this TTER, thatTTER.theEventGroup);
168: // System.out.println("Add to event group " + thatEventGroup);
169: }
170: } else {
171: if (thatTTER.theEventGroup == null) {
172: // thisEventGroup exists; add thatTTER to it
173: changeEventGroup(thatTTER, this TTER.theEventGroup);
174: // System.out.println("Add to event group " + thisEventGroup);
175: } else if (this TTER.theEventGroup != thatTTER.theEventGroup) {
176: // Both groups exist and are different; merge thatEventGroup with thisEventGroup
177: for (Iterator iter = thatTTER.theEventGroup
178: .iterator(); iter.hasNext();) {
179: TimedTaskEventReport tter = (TimedTaskEventReport) iter
180: .next();
181: tter.theEventGroup = null; // Prevent trying to remove from the iterator base
182: changeEventGroup(tter, this TTER.theEventGroup);
183: }
184: System.out.println("Merge to event group "
185: + this TTER.theEventGroup);
186: }
187: }
188: }
189: finishScheduleUpdate();
190: }
191:
192: private void changeEventGroup(TimedTaskEventReport tter,
193: EventGroup newEventGroup) {
194: super .removeFromSchedule(tter); // We are changing the sort order,
195: // must not be in the sorted set while
196: // we do so
197: if (tter.theEventGroup != null) {
198: tter.theEventGroup.remove(tter);
199: tter.theEventGroup = null;
200: }
201: if (newEventGroup != null) {
202: tter.theEventGroup = newEventGroup;
203: newEventGroup.add(tter);
204: }
205: super .addToSchedule(tter);
206: }
207:
208: public void sendTaskConstraintRequest(String source,
209: Collection taskUIDs) throws IOException {
210: Object[] handlers = { new EGConstraintElementHandler(this ) };
211: TaskConstraintsRequest request = new TaskConstraintsRequest(
212: (UID[]) taskUIDs.toArray(new UID[taskUIDs.size()]));
213: ConstraintElementListener l = theEventGenerator
214: .createConstraintElementListener(source, handlers,
215: request);
216: if (l != null) {
217: theEventGenerator.addListener(l);
218: theEventGenerator.startListener(l);
219: }
220: }
221:
222: protected ManagerTableModel createTableModel() {
223: return new TaskEventReportTableModel();
224: }
225:
226: private class TaskEventReportTableModel extends ManagerTableModel {
227: private static final int ENABLE_COLUMN = 0;
228: private static final int CLUSTER_COLUMN = 1;
229: private static final int RECEIVE_TIME_COLUMN = 2;
230: private static final int REPORT_TIME_COLUMN = 3;
231: private static final int GROUP_ID_COLUMN = 4;
232: private static final int TASK_UID_COLUMN = 5;
233: private static final int DESC_COLUMN = 6;
234: private static final int ASPECT_TYPE_COLUMN = 7;
235: private static final int ASPECT_VALUE_COLUMN = 8;
236: private static final int ANNOTATION_COLUMN = 9;
237: private static final int NCOLUMNS = 10;
238: private/*ns*/final int ASPECT_TYPE_WIDTH = getCellWidth("TOTAL_SHIPMENTS");
239: private/*ns*/final int TASK_UID_WIDTH = CLUSTER_WIDTH
240: + getCellWidth("/XXXXXXXXXXXXX");
241: private/*ns*/final int DESC_WIDTH = getCellWidth("XXXXXXXXXXXXXXXXXXXXXXXXX");
242:
243: private EventGroup markedEventGroup = null;
244:
245: public TaskEventReportTableModel() {
246: logColumns = new int[] { ENABLE_COLUMN, CLUSTER_COLUMN,
247: RECEIVE_TIME_COLUMN, REPORT_TIME_COLUMN,
248: GROUP_ID_COLUMN, TASK_UID_COLUMN, DESC_COLUMN,
249: ASPECT_TYPE_COLUMN, ASPECT_VALUE_COLUMN,
250: ANNOTATION_COLUMN, };
251: }
252:
253: public void cellSelectionChanged(int row, int col) {
254: col = GROUP_ID_COLUMN;
255: EventGroup newEventGroup = null;
256: TimedTaskEventReport tter = (TimedTaskEventReport) getRowObject(row);
257: if (tter != null) {
258: newEventGroup = tter.theEventGroup;
259: }
260: if (newEventGroup != markedEventGroup) {
261: markedEventGroup = newEventGroup;
262: fireTableDataChanged();
263: }
264: }
265:
266: public boolean cellIsMarked(int row, int col) {
267: if (true || col == GROUP_ID_COLUMN) {
268: if (markedEventGroup != null) {
269: TimedTaskEventReport tter = (TimedTaskEventReport) getRowObject(row);
270: return markedEventGroup == tter.theEventGroup;
271: }
272: }
273: return false;
274: }
275:
276: public int getColumnCount() {
277: return NCOLUMNS;
278: }
279:
280: public int getPreferredColumnWidth(int col) {
281: switch (col) {
282: case ENABLE_COLUMN:
283: return SEND_WIDTH;
284: case CLUSTER_COLUMN:
285: return CLUSTER_WIDTH;
286: case RECEIVE_TIME_COLUMN:
287: return DATE_WIDTH;
288: case REPORT_TIME_COLUMN:
289: return DATE_WIDTH;
290: case GROUP_ID_COLUMN:
291: return TASK_UID_WIDTH;
292: case TASK_UID_COLUMN:
293: return TASK_UID_WIDTH;
294: case DESC_COLUMN:
295: return DESC_WIDTH;
296: case ASPECT_TYPE_COLUMN:
297: return ASPECT_TYPE_WIDTH;
298: case ASPECT_VALUE_COLUMN:
299: return DATE_WIDTH;
300: case ANNOTATION_COLUMN:
301: return ANNOTATION_WIDTH;
302: }
303: return 75;
304: }
305:
306: public int getMinColumnWidth(int col) {
307: switch (col) {
308: case ENABLE_COLUMN:
309: return SEND_WIDTH;
310: case CLUSTER_COLUMN:
311: return CLUSTER_WIDTH / 2;
312: case RECEIVE_TIME_COLUMN:
313: return DATE_WIDTH;
314: case REPORT_TIME_COLUMN:
315: return DATE_WIDTH;
316: case GROUP_ID_COLUMN:
317: return TASK_UID_WIDTH / 2;
318: case TASK_UID_COLUMN:
319: return TASK_UID_WIDTH / 2;
320: case DESC_COLUMN:
321: return DESC_WIDTH / 4;
322: case ASPECT_TYPE_COLUMN:
323: return 75;
324: case ASPECT_VALUE_COLUMN:
325: return 75;
326: case ANNOTATION_COLUMN:
327: return ANNOTATION_WIDTH / 2;
328: }
329: return 75;
330: }
331:
332: public int getMaxColumnWidth(int col) {
333: switch (col) {
334: case ENABLE_COLUMN:
335: return SEND_WIDTH;
336: case CLUSTER_COLUMN:
337: return CLUSTER_WIDTH;
338: case RECEIVE_TIME_COLUMN:
339: return DATE_WIDTH;
340: case REPORT_TIME_COLUMN:
341: return DATE_WIDTH;
342: case GROUP_ID_COLUMN:
343: return Integer.MAX_VALUE;
344: case TASK_UID_COLUMN:
345: return Integer.MAX_VALUE;
346: case DESC_COLUMN:
347: return Integer.MAX_VALUE;
348: case ASPECT_TYPE_COLUMN:
349: return Integer.MAX_VALUE;
350: case ASPECT_VALUE_COLUMN:
351: return Integer.MAX_VALUE;
352: case ANNOTATION_COLUMN:
353: return Integer.MAX_VALUE;
354: }
355: return 75;
356: }
357:
358: public String getColumnName(int col) {
359: switch (col) {
360: case ENABLE_COLUMN:
361: return "Send";
362: case CLUSTER_COLUMN:
363: return "Cluster";
364: case RECEIVE_TIME_COLUMN:
365: return "Receive Date";
366: case REPORT_TIME_COLUMN:
367: return "Report Date";
368: case GROUP_ID_COLUMN:
369: return "Group Id";
370: case TASK_UID_COLUMN:
371: return "Task Id";
372: case DESC_COLUMN:
373: return "Description";
374: case ASPECT_TYPE_COLUMN:
375: return "Aspect Type";
376: case ASPECT_VALUE_COLUMN:
377: return "Aspect Value";
378: case ANNOTATION_COLUMN:
379: return "Comment";
380: }
381: return null;
382: }
383:
384: public Class getColumnClass(int col) {
385: switch (col) {
386: case ENABLE_COLUMN:
387: return Boolean.class;
388: case CLUSTER_COLUMN:
389: return String.class;
390: case RECEIVE_TIME_COLUMN:
391: return String.class;
392: case REPORT_TIME_COLUMN:
393: return String.class;
394: case GROUP_ID_COLUMN:
395: return String.class;
396: case TASK_UID_COLUMN:
397: return String.class;
398: case DESC_COLUMN:
399: return String.class;
400: case ASPECT_TYPE_COLUMN:
401: return String.class;
402: case ASPECT_VALUE_COLUMN:
403: return Object.class;
404: case ANNOTATION_COLUMN:
405: return Object.class;
406: }
407: return null;
408: }
409:
410: public boolean isCellEditable(int row, int col) {
411: TimedTaskEventReport ter = (TimedTaskEventReport) getRowObject(row);
412: if (ter == null)
413: return false;
414: theEventGenerator.setPaused(true);
415: switch (col) {
416: case ENABLE_COLUMN:
417: return true;
418: case CLUSTER_COLUMN:
419: return false;
420: case RECEIVE_TIME_COLUMN:
421: return true;
422: case REPORT_TIME_COLUMN:
423: return true;
424: case GROUP_ID_COLUMN:
425: return false;
426: case TASK_UID_COLUMN:
427: return false;
428: case DESC_COLUMN:
429: return false;
430: case ASPECT_TYPE_COLUMN:
431: return false;
432: case ASPECT_VALUE_COLUMN:
433: switch (ter.theTaskEventReport.theTaskEventId.theAspectType) {
434: case AspectType.START_TIME:
435: case AspectType.END_TIME:
436: case AspectType.QUANTITY:
437: return true;
438: }
439: }
440: return false;
441: }
442:
443: public boolean cellHasBeenEdited(int row, int col) {
444: TimedTaskEventReport ter = (TimedTaskEventReport) getRowObject(row);
445: if (ter == null)
446: return false;
447: if (ter.theOriginalTaskEventReport == null)
448: return false;
449: switch (col) {
450: case ENABLE_COLUMN:
451: return false;
452: case RECEIVE_TIME_COLUMN:
453: return ter.theTaskEventReport.theReceivedDate != ter.theOriginalTaskEventReport.theReceivedDate;
454: case REPORT_TIME_COLUMN:
455: return ter.theTaskEventReport.theReportDate != ter.theOriginalTaskEventReport.theReportDate;
456: case GROUP_ID_COLUMN:
457: return false;
458: case TASK_UID_COLUMN:
459: return false;
460: case DESC_COLUMN:
461: return false;
462: case ASPECT_TYPE_COLUMN:
463: return false;
464: case ASPECT_VALUE_COLUMN:
465: return ter.theTaskEventReport.theAspectValue != ter.theOriginalTaskEventReport.theAspectValue;
466: }
467: return false;
468: }
469:
470: public void setValueAt(Object newValue, int row, int col) {
471: TimedTaskEventReport ter = (TimedTaskEventReport) getRowObject(row);
472: if (ter == null)
473: return;
474: if (ter.theEventGroup != null) {
475: int answer = OptionPane
476: .showOptionDialog(
477: getGUI(),
478: "Do you want to modify all constrained values?",
479: "Change Constrained Values",
480: OptionPane.YES_NO_CANCEL_OPTION,
481: OptionPane.QUESTION_MESSAGE, null,
482: null, null);
483: switch (answer) {
484: default:
485: return;
486: case OptionPane.YES_OPTION:
487: for (Iterator i = ter.theEventGroup.iterator(); i
488: .hasNext();) {
489: setValue(newValue, (TimedTaskEventReport) i
490: .next(), col);
491: }
492: fireTableDataChanged();
493: break;
494: case OptionPane.NO_OPTION:
495: setValue(newValue, ter, col);
496: break;
497: }
498: } else {
499: setValue(newValue, ter, col);
500: }
501: }
502:
503: private void setValue(Object newValue,
504: TimedTaskEventReport ter, int col) {
505: String stringValue = "";
506: if (newValue instanceof String)
507: stringValue = (String) newValue;
508: switch (col) {
509: case ENABLE_COLUMN:
510: ter.setEnabled(((Boolean) newValue).booleanValue());
511: break;
512: case RECEIVE_TIME_COLUMN:
513: assureEditCopy(ter);
514: TaskEventReportManager.super .removeFromSchedule(ter);
515: if (stringValue.equals("")) {
516: ter.theTaskEventReport.theReceivedDate = ter.theOriginalTaskEventReport.theReceivedDate;
517: } else {
518: ter.theTaskEventReport.theReceivedDate = new EGDate(
519: stringValue).getTime();
520: }
521: TaskEventReportManager.super .addToSchedule(ter);
522: break;
523: case REPORT_TIME_COLUMN:
524: assureEditCopy(ter);
525: if (stringValue.equals("")) {
526: ter.theTaskEventReport.theReportDate = ter.theOriginalTaskEventReport.theReportDate;
527: } else {
528: ter.theTaskEventReport.theReportDate = new EGDate(
529: stringValue).getTime();
530: }
531: break;
532: case GROUP_ID_COLUMN:
533: break;
534: case TASK_UID_COLUMN:
535: break;
536: case DESC_COLUMN:
537: break;
538: case ASPECT_TYPE_COLUMN:
539: break;
540: case ASPECT_VALUE_COLUMN:
541: assureEditCopy(ter);
542: switch (ter.theTaskEventReport.theTaskEventId.theAspectType) {
543: case AspectType.START_TIME:
544: case AspectType.END_TIME:
545: if (stringValue.equals("")) {
546: ter.theTaskEventReport.theAspectValue = ter.theOriginalTaskEventReport.theAspectValue;
547: } else {
548: ter.theTaskEventReport.theAspectValue = (double) new EGDate(
549: stringValue).getTime();
550: }
551: break;
552: case AspectType.QUANTITY:
553: assureEditCopy(ter);
554: try {
555: if (stringValue.equals("")) {
556: ter.theTaskEventReport.theAspectValue = ter.theOriginalTaskEventReport.theAspectValue;
557: } else {
558: ter.theTaskEventReport.theAspectValue = Double
559: .parseDouble(stringValue);
560: }
561: } catch (NumberFormatException nfe) {
562: postErrorMessage("Value must be numeric");
563: }
564: break;
565: }
566: break;
567: }
568: }
569:
570: private void assureEditCopy(TimedTaskEventReport ter) {
571: ter.getModifiableTaskEventReport();
572: }
573:
574: public Object getValue(int col, Object rowObject) {
575: TimedTaskEventReport ter = (TimedTaskEventReport) rowObject;
576: if (ter == null)
577: return null;
578: switch (col) {
579: case ENABLE_COLUMN:
580: return new Boolean(ter.isEnabled());
581: case CLUSTER_COLUMN:
582: return ter.theSource;
583: case RECEIVE_TIME_COLUMN:
584: return new EGDate(
585: ter.theTaskEventReport.theReceivedDate);
586: case REPORT_TIME_COLUMN:
587: return new EGDate(ter.theTaskEventReport.theReportDate);
588: case GROUP_ID_COLUMN:
589: return ter.theEventGroup == null ? null
590: : ter.theEventGroup.theGroupId;
591: case TASK_UID_COLUMN:
592: return ter.theTaskEventReport.theTaskEventId.theTaskUID;
593: case DESC_COLUMN:
594: return ter.theTaskEventReport.theShortDescription;
595: case ASPECT_TYPE_COLUMN:
596: switch (ter.theTaskEventReport.theTaskEventId.theAspectType) {
597: case AspectType.START_TIME:
598: return "START_TIME";
599: case AspectType.END_TIME:
600: return "END_TIME";
601: case AspectType.QUANTITY:
602: return "QUANTITY";
603: }
604: return "ASPECT_TYPE "
605: + ter.theTaskEventReport.theTaskEventId.theAspectType;
606: case ASPECT_VALUE_COLUMN:
607: switch (ter.theTaskEventReport.theTaskEventId.theAspectType) {
608: case AspectType.START_TIME:
609: return new EGDate(
610: (long) ter.theTaskEventReport.theAspectValue)
611: .toString();
612: case AspectType.END_TIME:
613: return new EGDate(
614: (long) ter.theTaskEventReport.theAspectValue)
615: .toString();
616: case AspectType.QUANTITY:
617: return new Double(
618: ter.theTaskEventReport.theAspectValue);
619: }
620: return new Double(ter.theTaskEventReport.theAspectValue);
621: case ANNOTATION_COLUMN:
622: return ter.getAnnotation();
623: }
624: return null;
625: }
626:
627: public String getToolTipText(int row, int column) {
628: Timed object = getRowObject(row);
629: if (object instanceof TimedTaskEventReport) {
630: return ((TimedTaskEventReport) object).theTaskEventReport.theFullDescription;
631: }
632: return null;
633: }
634: }
635: }
|