001: /*
002: * <copyright>
003: *
004: * Copyright 2000-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.tools.csmart.ui.viewer;
028:
029: import org.cougaar.tools.csmart.core.db.ExperimentDB;
030: import org.cougaar.util.log.Logger;
031:
032: import javax.swing.*;
033: import javax.swing.border.LineBorder;
034: import java.awt.*;
035: import java.awt.event.ActionEvent;
036: import java.awt.event.ActionListener;
037: import java.awt.event.WindowAdapter;
038: import java.awt.event.WindowEvent;
039: import java.util.ArrayList;
040: import java.util.Map;
041: import java.util.Set;
042:
043: /**
044: * For loading experiments based on CMT assemblies, select the
045: * threads of supply to include, possibly regenerating the CMT
046: * assembly if necessary.
047: */
048: public class CMTDialog extends JDialog {
049: // thread names displayed for user
050: private static final String[] ULThreads = {
051: "Subsistence (Class 1)", "Fuel (Class 3)",
052: "Construction Material (Class 4)", "Ammunition (Class 5)",
053: "Spare Parts (Class 9)" };
054: // thread names passed to database
055: private static final String[] ULDBThreads = { "CLASS-1", "CLASS-3",
056: "CLASS-4", "CLASS-5", "CLASS-9" };
057: private String experimentId;
058: private String experimentName;
059: private boolean cloned = false;
060: private String trialId;
061: private String[] groupNames;
062: private JCheckBox forceRecomputeBox;
063: private ArrayList groupCheckBoxes = new ArrayList();
064: private ArrayList ULThreadCheckBoxes = new ArrayList();
065: private ArrayList multiplierFields = new ArrayList();
066: private ArrayList originalThreadSelected = new ArrayList();
067: private ArrayList originalGroupSelected = new ArrayList();
068: private ArrayList originalGroupMultiplier = new ArrayList();
069: private Organizer organizer;
070: private boolean cancelled = false;
071:
072: private transient Logger log;
073:
074: /**
075: * Creates a new <code>CMTDialog</code> instance. Will always show the UI.
076: *
077: * @param parent a <code>JFrame</code> to locate this window
078: * @param organizer an <code>Organizer</code> to load into
079: * @param experimentName a <code>String</code> experiment name to laod
080: * @param experimentId a <code>String</code> experiment ID to load
081: */
082: public CMTDialog(JFrame parent, Organizer organizer,
083: String experimentName, String experimentId) {
084: this (parent, organizer, experimentName, experimentId, false);
085: }
086:
087: /**
088: * Creates a new <code>CMTDialog</code> instance.
089: *
090: * @param parent a <code>JFrame</code> to locate this window
091: * @param organizer an <code>Organizer</code> to load into
092: * @param experimentName a <code>String</code> experiment name to laod
093: * @param experimentId a <code>String</code> experiment ID to load
094: * @param noShow a <code>boolean</code> indicating whether to actually show the UI, or just take the existing selection
095: */
096: public CMTDialog(JFrame parent, Organizer organizer,
097: String experimentName, String experimentId, boolean noShow) {
098: super (parent, "Threads and Groups", true); // modal dialog
099: createLogger();
100: this .organizer = organizer; // to get unique names
101: this .experimentName = experimentName;
102: this .experimentId = experimentId;
103: this .trialId = ExperimentDB.getTrialId(experimentId);
104: JPanel panel = new JPanel(new BorderLayout());
105:
106: // Panel for threads
107: JPanel bottomPanel = new JPanel(new GridBagLayout());
108: bottomPanel.setBorder(LineBorder.createGrayLineBorder());
109: int x = 0;
110: int y = 0;
111: int leftIndent = 0;
112: bottomPanel.add(new JLabel("Select Threads:"),
113: new GridBagConstraints(x, y++, 1, 1, 0.0, 0.0,
114: GridBagConstraints.WEST,
115: GridBagConstraints.NONE, new Insets(0,
116: leftIndent, 5, 0), 0, 0));
117: leftIndent = leftIndent + 5;
118: for (int i = 0; i < ULThreads.length; i++) {
119: JCheckBox cb = new JCheckBox(ULThreads[i]);
120:
121: // Class 4 is disabled this year
122: if (ULThreads[i].indexOf('4') != -1)
123: cb.setEnabled(false);
124:
125: // if (DBUtils.isMySQL())
126: // cb.setEnabled(false); // MySQL DB
127:
128: ULThreadCheckBoxes.add(cb);
129: boolean sel = ExperimentDB.isULThreadSelected(trialId,
130: ULDBThreads[i]);
131: cb.setSelected(sel);
132: originalThreadSelected.add(new Boolean(sel));
133: //if (i == (ULThreads.length-1))
134: // cb.setEnabled(false); // spare parts
135: bottomPanel.add(cb, new GridBagConstraints(x, y++, 1, 1,
136: 0.0, 0.0, GridBagConstraints.WEST,
137: GridBagConstraints.NONE, new Insets(0, leftIndent,
138: 5, 0), 0, 0));
139: }
140:
141: /////////////////////////
142: // Now the multiplier groups
143:
144: Map groupNameToId = ExperimentDB
145: .getOrganizationGroups(experimentId);
146: Set groups = groupNameToId.keySet();
147: groupNames = (String[]) groups
148: .toArray(new String[groups.size()]);
149: int nGroupNames = groupNames.length;
150:
151: // Only bother if there are any groups
152: if (nGroupNames > 0) {
153: leftIndent = leftIndent - 5;
154: bottomPanel.add(new JLabel("Select Organization Groups:"),
155: new GridBagConstraints(x, y++, 1, 1, 0.0, 0.0,
156: GridBagConstraints.WEST,
157: GridBagConstraints.NONE, new Insets(0,
158: leftIndent, 0, 0), 0, 0));
159: leftIndent = leftIndent + 5;
160: for (int i = 0; i < nGroupNames; i++) {
161: String groupName = (String) groupNames[i];
162: JCheckBox groupCB = new JCheckBox(groupName);
163:
164: // if (DBUtils.isMySQL())
165: // groupCB.setEnabled(false); // MySQL DB
166:
167: boolean sel = ExperimentDB.isGroupSelected(trialId,
168: groupName);
169: groupCheckBoxes.add(groupCB);
170: originalGroupSelected.add(new Boolean(sel));
171: groupCB.setSelected(sel);
172: bottomPanel.add(groupCB, new GridBagConstraints(x++, y,
173: 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
174: GridBagConstraints.NONE, new Insets(0,
175: leftIndent, 5, 0), 0, 0));
176: bottomPanel.add(new JLabel("Number of Copies:"),
177: new GridBagConstraints(x++, y, 1, 1, 0.0, 0.0,
178: GridBagConstraints.WEST,
179: GridBagConstraints.NONE, new Insets(0,
180: 0, 5, 5), 0, 0));
181: JTextField multiplierField = new JTextField(4);
182: multiplierFields.add(multiplierField);
183: int multiplier = ExperimentDB.getMultiplier(trialId,
184: groupName);
185: multiplierField.setText(String.valueOf(multiplier));
186: originalGroupMultiplier.add(new Integer(multiplier));
187: bottomPanel.add(multiplierField,
188: new GridBagConstraints(x++, y, 1, 1, 0.0, 0.0,
189: GridBagConstraints.WEST,
190: GridBagConstraints.NONE, new Insets(0,
191: 0, 5, 5), 0, 0));
192: bottomPanel.add(new JLabel("Members:"),
193: new GridBagConstraints(x++, y, 1, 1, 0.0, 0.0,
194: GridBagConstraints.WEST,
195: GridBagConstraints.NONE, new Insets(0,
196: 0, 5, 5), 0, 0));
197: Set members = ExperimentDB.getOrganizationsInGroup(
198: experimentId, (String) groupNameToId
199: .get(groupName));
200: JList membersList = new JList(members.toArray());
201: membersList.setVisibleRowCount(4);
202: bottomPanel.add(new JScrollPane(membersList),
203: new GridBagConstraints(x++, y++, 1, 1, 0.0,
204: 0.0, GridBagConstraints.WEST,
205: GridBagConstraints.NONE, new Insets(0,
206: 0, 5, 5), 0, 0));
207: x = 0;
208: } // loop over groups
209: }
210:
211: //////////////////////
212: // Now the other items
213:
214: leftIndent = leftIndent - 5;
215: // FIXME: (bug 1888) better label?
216: bottomPanel.add(new JLabel("Society:"), new GridBagConstraints(
217: x, y++, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
218: GridBagConstraints.NONE,
219: new Insets(0, leftIndent, 0, 0), 0, 0));
220: leftIndent = leftIndent + 5;
221:
222: forceRecomputeBox = new JCheckBox("Force Recompute");
223: bottomPanel.add(forceRecomputeBox, new GridBagConstraints(x,
224: y + 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
225: GridBagConstraints.NONE,
226: new Insets(0, leftIndent, 5, 5), 0, 0));
227:
228: panel.add(bottomPanel, BorderLayout.CENTER);
229:
230: // Buttons panel
231: JPanel buttonPanel = new JPanel();
232: JButton okButton = new JButton("OK");
233: okButton.addActionListener(new ActionListener() {
234: public void actionPerformed(ActionEvent e) {
235: ok_actionPerformed();
236: }
237: });
238: JButton cancelButton = new JButton("Cancel");
239: cancelButton.addActionListener(new ActionListener() {
240: public void actionPerformed(ActionEvent e) {
241: cancel_actionPerformed();
242: }
243: });
244:
245: addWindowListener(new WindowAdapter() {
246: public void windowClosing(WindowEvent e) {
247: cancel_actionPerformed();
248: }
249: });
250:
251: buttonPanel.add(okButton);
252: buttonPanel.add(cancelButton);
253: panel.add(buttonPanel, BorderLayout.SOUTH);
254: getContentPane().add(panel);
255: pack();
256: // make dialog display over the middle of the caller's frame
257: Point p = parent.getLocation();
258: Dimension d = parent.getSize();
259: int centerX = p.x + d.width / 2;
260: int centerY = p.y + d.height / 2;
261: Dimension myD = getSize();
262: setLocation(new Point(centerX - myD.width / 2, centerY
263: - myD.height / 2));
264: if (noShow)
265: cancelled = false;
266: else
267: show();
268: }
269:
270: private void createLogger() {
271: log = CSMART.createLogger(this .getClass().getName());
272: }
273:
274: private void ok_actionPerformed() {
275: cancelled = false;
276: hide();
277: }
278:
279: /**
280: * Returns true if any logistics supply thread was selected and false otherwise.
281: */
282: public boolean isULThreadSelected() {
283: int n = ULThreads.length;
284: for (int i = 0; i < n; i++) {
285: JCheckBox cb = (JCheckBox) ULThreadCheckBoxes.get(i);
286: if (cb.isSelected())
287: return true;
288: }
289: return false;
290: }
291:
292: /**
293: * Returns true if the force recompute society box was selected, false otherwise.
294: */
295: public boolean isForceRecomputeSelected() {
296: return forceRecomputeBox.isSelected();
297: }
298:
299: /**
300: * If threads, groups or multipliers have been modified, then
301: * create a new trial.
302: */
303:
304: public boolean processResults() {
305: boolean modified = false;
306: int n = ULThreads.length;
307: for (int i = 0; i < n; i++) {
308: JCheckBox cb = (JCheckBox) ULThreadCheckBoxes.get(i);
309: Boolean b = (Boolean) originalThreadSelected.get(i);
310: if (b.booleanValue() == cb.isSelected())
311: continue;
312: if (!modified) {
313: if (!cloneExperiment())
314: return false; // user cancelled modifications
315: modified = true;
316: }
317: ExperimentDB.setULThreadSelected(trialId, ULDBThreads[i],
318: cb.isSelected());
319: }
320: n = groupCheckBoxes.size();
321: for (int i = 0; i < n; i++) {
322: String groupName = groupNames[i];
323: JCheckBox cb = (JCheckBox) groupCheckBoxes.get(i);
324: Boolean b = (Boolean) originalGroupSelected.get(i);
325: if (b.booleanValue() != cb.isSelected()) {
326: if (!modified) {
327: if (!cloneExperiment())
328: return false; // user cancelled modifications
329: modified = true;
330: }
331: ExperimentDB.setGroupSelected(trialId, groupName, cb
332: .isSelected());
333: }
334: JTextField multiplierField = (JTextField) multiplierFields
335: .get(i);
336: int multiplier = ((Integer) originalGroupMultiplier.get(i))
337: .intValue();
338: try {
339: int newMultiplier = Integer.parseInt(multiplierField
340: .getText());
341: if (multiplier == newMultiplier)
342: continue;
343: if (!modified) {
344: if (!cloneExperiment())
345: return false; // user cancelled modifications
346: modified = true;
347: }
348: ExperimentDB.setMultiplier(trialId, groupName,
349: newMultiplier);
350: } catch (NumberFormatException e) {
351: }
352: }
353: if (forceRecomputeBox.isSelected()) {
354: if (log.isInfoEnabled()) {
355: log.info("Force Recompute Checked");
356: }
357: ExperimentDB.deleteCMTAssembly(experimentId);
358: modified = true;
359: }
360:
361: if (modified) {
362: String newCMTasb = ExperimentDB
363: .updateCMTAssembly(experimentId);
364: if (forceRecomputeBox.isSelected()) {
365: if (log.isInfoEnabled()) {
366: log.info("new CMTasb is: " + newCMTasb);
367: }
368: ExperimentDB.deleteCMTAssembly(experimentId);
369: newCMTasb = ExperimentDB
370: .updateCMTAssembly(experimentId);
371: if (log.isInfoEnabled()) {
372: log.info("new CMTasb is: " + newCMTasb);
373: }
374: }
375: trialId = ExperimentDB.getTrialId(experimentId);
376: }
377: return true;
378: }
379:
380: private boolean cloneExperiment() {
381: // ask user to confirm cloning experiment
382: // int result = JOptionPane.showConfirmDialog(this,
383: // "Modify Experiment",
384: // "Modify Experiment?",
385: // JOptionPane.YES_NO_OPTION,
386: // JOptionPane.QUESTION_MESSAGE);
387: // if (result == JOptionPane.NO_OPTION)
388: // return false;
389: // if experiment name is in the database, then ask user for new name
390: // or allow user to re-use existing name
391: if (ExperimentDB.isExperimentNameInDatabase(experimentName)) {
392: boolean allowOrig = true;
393: if (!experimentId.startsWith("EXPT-"))
394: allowOrig = false;
395: String name = organizer.getUniqueExperimentName(
396: experimentName, allowOrig);
397: if (name == null)
398: return false;
399: experimentName = name;
400: }
401: if (log.isDebugEnabled()) {
402: log.debug("Cloning experiment: " + experimentName);
403: }
404: experimentId = ExperimentDB.cloneExperiment(experimentId,
405: experimentName);
406: trialId = ExperimentDB.getTrialId(experimentId);
407: cloned = true;
408: return true;
409: }
410:
411: private void cancel_actionPerformed() {
412: cancelled = true;
413: hide();
414: trialId = null;
415: }
416:
417: public String getExperimentId() {
418: return experimentId;
419: }
420:
421: public String getExperimentName() {
422: return experimentName;
423: }
424:
425: public String getTrialId() {
426: return trialId;
427: }
428:
429: public boolean isCloned() {
430: return cloned;
431: }
432:
433: public boolean wasCancelled() {
434: return cancelled;
435: }
436:
437: public static void main(String[] args) {
438: CMTDialog d = new CMTDialog(null, null, "ExperimentName",
439: "ExperimentID");
440: d.show();
441: }
442: }
|