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.awt.LayoutManager;
030: import java.awt.event.ActionEvent;
031: import java.awt.event.ActionListener;
032: import java.text.DateFormat;
033: import java.text.SimpleDateFormat;
034: import java.util.ArrayList;
035: import java.util.Date;
036: import java.util.Enumeration;
037:
038: import javax.swing.JButton;
039: import javax.swing.JComboBox;
040: import javax.swing.JFrame;
041: import javax.swing.JLabel;
042: import javax.swing.JPanel;
043:
044: import org.cougaar.core.blackboard.IncrementalSubscription;
045: import org.cougaar.core.mts.MessageAddress;
046: import org.cougaar.core.util.UID;
047: import org.cougaar.glm.ldm.Constants;
048: import org.cougaar.glm.ldm.asset.Organization;
049: import org.cougaar.glm.ldm.oplan.Oplan;
050: import org.cougaar.mlm.plugin.UICoordinator;
051: import org.cougaar.planning.ldm.plan.ContextOfUIDs;
052: import org.cougaar.planning.ldm.plan.Task;
053: import org.cougaar.planning.plugin.legacy.SimplePlugin;
054: import org.cougaar.util.UnaryPredicate;
055:
056: /**
057: * The GLSGUIBasePlugin supports both init and rescind plugins by
058: * providing the basic oplan tracking and management. For each Oplan,
059: * the combobox of the gui is augmented with the additional oplan.
060: * When the selected oplan is changed, methods are invoked in the
061: * subclasses to allow labels to be updated.
062: *
063: **/
064: public abstract class GLSGUIBasePlugin extends SimplePlugin {
065: private static String EXIT_ON_CLOSE_PROP = "org.cougaar.mlm.plugin.organization.GLSGUIBasePlugin.exitOnClose";
066: private static boolean exitOnClose = System.getProperty(
067: EXIT_ON_CLOSE_PROP, "false").equals("true");
068:
069: /** frame for 1-button UI **/
070: private JFrame frame;
071:
072: /** for knowing when we get our self org asset **/
073: protected Organization selfOrgAsset = null;
074:
075: /** for feedback to user on whether root GLS was successful **/
076: private JLabel glsLabel = new JLabel(" ");
077:
078: /** A button to push to kick things off **/
079: protected JButton glsButton = new JButton("Send GLS root");
080:
081: /** A combo box for selecting the Oplan **/
082: protected JComboBox oplanCombo = new JComboBox();
083:
084: /** A panel to hold the GUI **/
085: JPanel panel = new JPanel((LayoutManager) null);
086:
087: private IncrementalSubscription myorgassets;
088: private IncrementalSubscription oplanSubscription;
089: private IncrementalSubscription taskSubscription;
090: protected boolean canSend = true;
091:
092: private static final String forRoot = "ForRoot".intern();
093:
094: private static UnaryPredicate orgAssetPred = new UnaryPredicate() {
095: public boolean execute(Object o) {
096: return (o instanceof Organization);
097: }
098: };
099:
100: private static UnaryPredicate oplanPred = new UnaryPredicate() {
101: public boolean execute(Object o) {
102: return (o instanceof Oplan);
103: }
104: };
105:
106: /**
107: * This predicate selects for root tasks injected by the GLSGUIInitPlugin
108: **/
109: private UnaryPredicate taskPred() {
110: return new UnaryPredicate() {
111: public boolean execute(Object o) {
112: if (!(o instanceof Task))
113: return false;
114: Task task = (Task) o;
115: if (!task.getSource().equals(getTheMessageAddress()))
116: return false;
117: if (!task.getDestination().equals(
118: getTheMessageAddress()))
119: return false;
120: if (!task.getVerb()
121: .equals(Constants.Verb.GETLOGSUPPORT))
122: return false;
123: return (task.getPrepositionalPhrase(forRoot) != null);
124: }
125: };
126: }
127:
128: /**
129: * Wrap an oplan to implement toString for the combobox
130: **/
131: protected static class OplanWrapper {
132: public Oplan oplan;
133: public ArrayList tasks = new ArrayList(1);
134:
135: public OplanWrapper(Oplan oplan) {
136: this .oplan = oplan;
137: }
138:
139: public String toString() {
140: return oplan.getOperationName();
141: }
142:
143: public void addTask(Task t) {
144: tasks.add(t);
145: }
146:
147: public void removeTask(Task t) {
148: tasks.remove(t);
149: }
150: }
151:
152: private OplanWrapper findOplanWrapper(Task t) {
153: ContextOfUIDs context = (ContextOfUIDs) t.getContext();
154: UID oplanUID = context.get(0);
155: OplanWrapper wrapper = null;
156: for (int i = 0, n = oplanCombo.getItemCount(); i < n; i++) {
157: wrapper = (OplanWrapper) oplanCombo.getItemAt(i);
158: if (wrapper.oplan.getUID().equals(oplanUID))
159: return wrapper;
160: }
161: // There should be no way for a root task with no corresponding oplan to exist
162: return null;
163: }
164:
165: // Have to provide these on this plugin class, else the inner class
166: // below will not be able to find them
167: public void openTheTransaction() {
168: openTransaction();
169: }
170:
171: public void closeTheTransaction(boolean b) {
172: closeTransaction(b);
173: }
174:
175: public MessageAddress getTheMessageAddress() {
176: return getMessageAddress();
177: }
178:
179: private void createGUI() {
180: frame = new JFrame(getGUITitle());
181: if (exitOnClose)
182: frame.setDefaultCloseOperation(3);
183: frame.setLocation(0, 0);
184: // Create the button
185: // Register a listener for the radio buttons
186: glsButton.setText(getButtonText());
187: glsButton.setEnabled(false); // Leave this disabled until we have oplans
188: glsButton.addActionListener(new ActionListener() {
189: public void actionPerformed(ActionEvent e) {
190: OplanWrapper wrapper = (OplanWrapper) oplanCombo
191: .getSelectedItem();
192: if (wrapper != null)
193: buttonPushed(wrapper);
194: }
195: });
196: oplanCombo.addActionListener(new ActionListener() {
197: public void actionPerformed(ActionEvent e) {
198: checkButtonEnable();
199: }
200: });
201: UICoordinator.layoutButtonAndLabel(panel, glsButton, glsLabel);
202: frame.getRootPane().setDefaultButton(glsButton); // hitting return sends GLS
203: JLabel oplanComboLabel = new JLabel("Select Oplan");
204: UICoordinator.layoutButtonAndLabel(panel, oplanCombo,
205: oplanComboLabel);
206: frame.setContentPane(panel);
207: frame.pack();
208: UICoordinator.setBounds(frame);
209: frame.setVisible(true);
210: }
211:
212: public void unload() {
213: super .unload();
214: frame.dispose();
215: }
216:
217: /**
218: * Overrides the setupSubscriptions() in the SimplifiedPlugin.
219: * Should be further overridden in subclasses which must call
220: * super.setupSubscriptions().
221: **/
222: protected final void setupSubscriptions() {
223: // Create a simple UI button for kicking off root GLS for testing
224: createGUI();
225:
226: myorgassets = (IncrementalSubscription) subscribe(orgAssetPred);
227: oplanSubscription = (IncrementalSubscription) subscribe(oplanPred);
228: taskSubscription = (IncrementalSubscription) subscribe(taskPred());
229: createSubscriptions(); // Give the subclass a chance to create subscriptions
230:
231: if (!didRehydrate()) {
232: createPrivateState(); // Create private state if any
233: } else {
234: //Initialize gui state based on existing info
235: restorePrivateState(); // Restore private state from logplan
236:
237: handleOplan(oplanSubscription.elements());
238: handleMyOrgAssets(myorgassets.elements());
239: handleAddedTasks(taskSubscription.elements());
240: checkButtonEnable();
241: }
242: }
243:
244: /* This will be called every time a new task matches the above predicate */
245:
246: public final void execute() {
247: additionalExecute();
248: handlePrivateState();
249:
250: if (myorgassets.hasChanged()) {
251: handleMyOrgAssets(myorgassets.getAddedList());
252: }
253:
254: if (oplanSubscription.hasChanged()) {
255: handleOplan(oplanSubscription.getAddedList());
256: }
257:
258: if (taskSubscription.hasChanged()) {
259: handleAddedTasks(taskSubscription.getAddedList());
260: handleRemovedTasks(taskSubscription.getRemovedList());
261: }
262: checkButtonEnable();
263: }
264:
265: protected void handleAddedTasks(Enumeration tasks) {
266: while (tasks.hasMoreElements()) {
267: Task t = (Task) tasks.nextElement();
268: OplanWrapper wrapper = findOplanWrapper(t);
269: if (wrapper != null)
270: wrapper.addTask(t);
271: }
272: }
273:
274: protected void handleRemovedTasks(Enumeration tasks) {
275: while (tasks.hasMoreElements()) {
276: Task t = (Task) tasks.nextElement();
277: OplanWrapper wrapper = findOplanWrapper(t);
278: if (wrapper != null)
279: wrapper.removeTask(t);
280: }
281: }
282:
283: protected abstract void createSubscriptions();
284:
285: protected abstract void handlePrivateState();
286:
287: protected abstract void createPrivateState();
288:
289: protected abstract void restorePrivateState();
290:
291: protected abstract boolean isPrivateStateOk();
292:
293: protected abstract String getGUITitle();
294:
295: protected abstract String getButtonText();
296:
297: protected abstract String getGLSLabelText(int nTasks);
298:
299: protected abstract void buttonPushed(OplanWrapper wrapper);
300:
301: protected abstract void additionalExecute();
302:
303: private void handleMyOrgAssets(Enumeration e) {
304: while (e.hasMoreElements()) {
305: Organization org = (Organization) e.nextElement();
306:
307: // Pick up self org
308: if (org.isSelf()) {
309: selfOrgAsset = org;
310: checkButtonEnable();
311: }
312: }
313: }
314:
315: /** New oplan received, add to combobox. **/
316: private void handleOplan(Enumeration e) {
317: while (e.hasMoreElements()) {
318: Oplan oplan = (Oplan) e.nextElement();
319: checkButtonEnable();
320: oplanCombo.addItem(new OplanWrapper(oplan));
321: }
322: }
323:
324: protected void checkButtonEnable() {
325: boolean privateStateOK = isPrivateStateOk();
326: glsButton.setEnabled(privateStateOK && selfOrgAsset != null
327: && oplanCombo.getSelectedItem() != null);
328: if (!privateStateOK) {
329: glsLabel.setText("Waiting for private state");
330: } else if (selfOrgAsset == null) {
331: glsLabel.setText("Waiting for Self");
332: } else {
333: OplanWrapper wrapper = (OplanWrapper) oplanCombo
334: .getSelectedItem();
335: if (wrapper == null) {
336: glsLabel.setText("Waiting for Oplan(s)");
337: } else {
338: glsLabel.setText(getGLSLabelText(wrapper.tasks.size()));
339: }
340: }
341: }
342:
343: protected static DateFormat logTimeFormat = new SimpleDateFormat(
344: "yyyy/MM/dd HH:mm:ss.SSS");
345:
346: protected static String formatDate(long when) {
347: return logTimeFormat.format(new Date(when));
348: }
349:
350: }
|