/*
* $Id$
*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javatest.exec;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.util.Arrays;
import java.util.Map;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.sun.interview.Interview;
import com.sun.interview.Question;
import com.sun.javatest.InterviewParameters;
import com.sun.javatest.InitialUrlFilter;
import com.sun.javatest.Keywords;
import com.sun.javatest.KeywordsFilter;
import com.sun.javatest.Parameters.ExcludeListParameters;
import com.sun.javatest.Parameters.MutableExcludeListParameters;
import com.sun.javatest.Status;
import com.sun.javatest.StatusFilter;
import com.sun.javatest.TestFilter;
import com.sun.javatest.TestDescription;
import com.sun.javatest.TestResultTable;
import com.sun.javatest.TestSuite;
import com.sun.javatest.ObservableTestFilter;
import com.sun.javatest.ObservableTestFilter.Observer;
import com.sun.javatest.util.DynamicArray;
import com.sun.javatest.util.StringArray;
import com.sun.javatest.tool.TestTreeSelectionPane;
import com.sun.javatest.tool.UIFactory;
import java.util.HashSet;
/**
* This filter allows the user to configure the filter using
* the filtering attributes normally found in the parameter
* section of an interview:
*
* - Initial URLs
*
- Status
*
- Exclude List
*
- Keywords
*
*
*
* The settings for this panel are global, so any changes made affect all
* exec tool instances.
*/
class BasicCustomTestFilter extends ConfigurableTestFilter {
// UIFactory parameter assume this class stays in the exec package
BasicCustomTestFilter(String name, ExecModel e, UIFactory uif) {
super(name, e);
this.uif = uif;
init(null);
}
BasicCustomTestFilter(Map map, ExecModel e, UIFactory uif) {
super(map, e);
this.uif = uif;
init(map);
}
BasicCustomTestFilter(ExecModel e, UIFactory uif) {
super(uif.getI18NString("basicTf.namePrefix"), e);
this.uif = uif;
init(null);
}
ConfigurableTestFilter cloneInstance() {
return new BasicCustomTestFilter(uif.getI18NString("basicTf.namePrefix") +
instanceCount, execModel, uif);
}
// override superclass methods
// observers must be static data since all exec tool instances
// must be notified of changes
@Override
public void addObserver(Observer o) {
obs = DynamicArray.append(obs, o);
}
@Override
public void removeObserver(Observer o) {
obs = DynamicArray.remove(obs, o);
}
@Override
protected void notifyUpdated(ObservableTestFilter filter) {
// obs will be null if called indirectly via load(map) from the
// superclass constructor, because super(...) is defined to be
// called before instance variables are initialized.
// (Hence the danger of overriding methods called from a superclass
// constructor.) 11/12/02
if (obs == null) {
return;
}
for (int i = 0; i < obs.length; i++) {
obs[i].filterUpdated(filter);
}
}
@Override
boolean load(Map map) {
boolean result = super.load(map);
activeSettings = new SettingsSnapshot(map);
putSettings(activeSettings);
activateSettings(activeSettings);
notifyUpdated(this);
return result;
}
@Override
boolean save(Map map) {
boolean result = super.save(map);
activeSettings.save(map);
return result;
}
void update(InterviewParameters ip) {
activateSettings(activeSettings);
}
synchronized JComponent getEditorPane() {
if (editorPane == null) {
editorPane = uif.createTabbedPane("basicTf.tabs", createTabPanels());
editorPane.setTabPlacement(SwingConstants.TOP);
try {
if (activeSettings == null) {
activeSettings = grabSettings();
} else {
putSettings(activeSettings);
}
} catch (IllegalStateException e) {
throw new IllegalStateException("Illegal state of BCTF GUI on startup.");
} // catch
editorPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}
return editorPane;
}
String commitEditorSettings() {
SettingsSnapshot nowSettings = null;
try {
nowSettings = grabSettings();
} catch (IllegalStateException e) {
// indicates that the GUI settings are not valid
return e.getMessage();
} // catch
if (!activeSettings.equals(nowSettings)) {
return activateSettings(nowSettings);
} else {
return null;
}
}
void resetEditorSettings() {
// set GUI to match live settings
putSettings(activeSettings);
}
boolean isEditorChanged() {
SettingsSnapshot nowSettings = null;
try {
nowSettings = grabSettings();
} catch (IllegalStateException e) {
// indicates that the GUI settings are not valid
return true;
} // catch
if (activeSettings.equals(nowSettings)) {
return false;
} else {
return true;
}
}
// TestFilter interface
public boolean accepts(TestDescription td)
throws TestFilter.Fault {
return accepts(td, null);
}
public boolean accepts(TestDescription td, TestFilter.Observer o)
throws TestFilter.Fault {
if (statusFilterNeedsUpdate)
updateStatusFilter();
for (int i = 0; i < activeFilters.length; i++) {
if (activeFilters[i] != null &&
!activeFilters[i].accepts(td)) {
if (o != null) {
o.rejected(td, activeFilters[i]);
} else {
}
return false;
} // outer if
} // for
return true;
}
public String getBaseName() {
return NAME;
}
public String getName() {
return instanceName;
}
public String getReason() {
return REASON;
}
public String getDescription() {
return DESCRIPTION;
}
// ----- PRIVATE -----
private void init(Map map) {
if (NAME == null) {
NAME = uif.getI18NString("basicTf.name");
}
if (REASON == null) {
REASON = uif.getI18NString("basicTf.reason");
}
if (DESCRIPTION == null) {
DESCRIPTION = uif.getI18NString("basicTf.description");
}
if (map != null) {
activeSettings = new SettingsSnapshot(map);
} else {
activeSettings = new SettingsSnapshot();
}
instanceCount++;
// not using this from superclass
observers = null;
activateSettings(activeSettings);
}
/**
* Make the given settings the active ones.
* Except under exceptional conditions, the filters are recreated and
* an update message is sent.
*/
private String activateSettings(SettingsSnapshot nowSettings) {
KeywordsFilter newKeyFilter = null;
InitialUrlFilter newUrlFilter = null;
TestFilter newJtxFilter = null;
StatusFilter newStatusFilter = null;
TestFilter newTsfFilter = null;
InterviewParameters ip = execModel.getInterviewParameters();
TestSuite ts = execModel.getTestSuite();
updateInterviewObserver(ip);
// recreate filters
if (nowSettings.urlsEnabled) {
// converting to strings to avoid any confusion
// files vs urls
if (nowSettings.initialUrls != null) {
newUrlFilter = new InitialUrlFilter(nowSettings.initialUrls);
}
}
if (nowSettings.keywordsEnabled) {
try {
String[] validKeywords = ts.getKeywords();
HashSet validKeywordsSet;
if (validKeywords == null) {
validKeywordsSet = null;
} else {
validKeywordsSet = new HashSet<>(Arrays.asList(validKeywords));
}
Keywords kw = Keywords.create(kwModeToType(nowSettings.keyChoice),
nowSettings.keyString, validKeywordsSet);
newKeyFilter = new KeywordsFilter(kw);
} catch (Keywords.Fault f) {
return f.getMessage();
}
}
if (nowSettings.statusEnabled) {
// this filter won't work without a TRT
TestResultTable trt = execModel.getActiveTestResultTable();
if (trt != null) {
newStatusFilter = new StatusFilter(
nowSettings.statusFields,
trt);
statusFilterNeedsUpdate = false;
} else {
statusFilterNeedsUpdate = true;
}
} else {
// to clear any old status
statusFilterNeedsUpdate = false;
}
if (nowSettings.jtxEnabled) {
// we only support copying exclude list from interview
// right now
if (ip != null) {
// may set var. to null, but that's okay
newJtxFilter = ip.getExcludeListFilter();
}
}
if (nowSettings.tsfEnabled) {
// we only support copying exclude list from interview
// right now
if (ip != null && ts != null) {
// may set filter to null, but that's okay
newTsfFilter = ts.createTestFilter(ip.getEnv());
}
}
// can abort anytime before this
// commit now
keyFilter = newKeyFilter;
urlFilter = newUrlFilter;
jtxFilter = newJtxFilter;
statusFilter = newStatusFilter;
tsfFilter = newTsfFilter;
// initialize the array if not yet done so
if (activeFilters == null) {
activeFilters = new TestFilter[NUM_FILTERS];
}
activeFilters[KEY_FILTER] = keyFilter;
activeFilters[URL_FILTER] = urlFilter;
activeFilters[JTX_FILTER] = jtxFilter;
activeFilters[STATUS_FILTER] = statusFilter;
activeFilters[TSS_FILTER] = tsfFilter;
activeSettings = nowSettings;
updateExcludeInfo();
// notify observers
notifyUpdated(this);
return null;
}
private void updateStatusFilter() {
if (!statusFilterNeedsUpdate)
return;
TestResultTable trt = execModel.getActiveTestResultTable();
if (trt != null) {
activeFilters[STATUS_FILTER] = new StatusFilter(
activeSettings.statusFields,
trt);
statusFilterNeedsUpdate = false;
}
}
/**
* Attach observer to the given interview.
* Automatically detaches from other interviews being observed.
* @param ip The interview to observe. For convenience, if this param
* is null, any current observers will be detached.
*/
private void updateInterviewObserver(InterviewParameters ip) {
if (ip == null && intObs != null) {
intObs.getInterview().removeObserver(intObs);
} else if (intObs == null || intObs.getInterview() != ip) {
if (intObs != null) {
intObs.getInterview().removeObserver(intObs);
}
if (ip != null) {
intObs = new InterviewObserver(ip);
ip.addObserver(intObs);
}
}
}
private void updateExcludeInfo() {
// check to see if GUI is init-ed
if (jtxMode == null) {
return;
}
InterviewParameters ip = execModel.getInterviewParameters();
if (ip == null) // nothing to do
{
return;
}
boolean isUnknown = true;
ExcludeListParameters elp = ip.getExcludeListParameters();
if (ip != null) {
elp = ip.getExcludeListParameters();
if (elp instanceof MutableExcludeListParameters) {
MutableExcludeListParameters melp = (MutableExcludeListParameters) elp;
int mode = melp.getExcludeMode();
switch (mode) {
case MutableExcludeListParameters.NO_EXCLUDE_LIST:
jtxMode.setText(uif.getI18NString("basicTf.exclude.mode.none"));
setExcludeFiles(null);
isUnknown = false;
break;
case MutableExcludeListParameters.INITIAL_EXCLUDE_LIST:
jtxMode.setText(uif.getI18NString("basicTf.exclude.mode.initial"));
setExcludeFiles(melp.getExcludeFiles());
isUnknown = false;
break;
case MutableExcludeListParameters.LATEST_EXCLUDE_LIST:
jtxMode.setText(uif.getI18NString("basicTf.exclude.mode.latest"));
setExcludeFiles(null);
isUnknown = false;
break;
case MutableExcludeListParameters.CUSTOM_EXCLUDE_LIST:
jtxMode.setText(uif.getI18NString("basicTf.exclude.mode.custom"));
setExcludeFiles(melp.getCustomExcludeFiles());
isUnknown = false;
break;
} // switch
}
}
// done here to avoid duplicating code above
if (isUnknown) {
jtxMode.setText(uif.getI18NString("basicTf.exclude.mode.unknown"));
jtxFiles.removeAllElements();
}
}
/**
* Adds exclude list files to the list.
* If null or zero length, the list is cleared.
* @param files The files to add. Null ok.
*/
private void setExcludeFiles(File[] files) {
jtxFiles.removeAllElements();
if (files == null || files.length == 0) {
return;
} else {
for (int i = 0; i < files.length; i++) {
jtxFiles.addElement(files[i].getPath());
}
}
}
private JComponent[] createTabPanels() {
JComponent[] items = {createTestsPanel(), createKeywordPanel(),
createStatusPanel(), createExcludePanel(),
createSpecialPanel()};
return items;
}
// KEYWORD PANEL
private JComponent createKeywordPanel() {
JPanel p = uif.createPanel(
"basicTf.keywords.mainPanel", new GridBagLayout(), false);
p.setName("keywords");
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
keyBtnGrp = new ButtonGroup();
keyAllBtn = uif.createRadioButton("basicTf.keywords.all", keyBtnGrp);
keyAllBtn.setMnemonic(uif.getI18NString("basicTf.keywords.all.mne").charAt(0));
p.add(keyAllBtn, c);
keyMatchBtn = uif.createRadioButton("basicTf.keywords.match", keyBtnGrp);
keyMatchBtn.setMnemonic(uif.getI18NString("basicTf.keywords.match.mne").charAt(0));
keyMatchBtn.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
enableKeywordFields();
}
});
c.weightx = 0;
c.gridwidth = 1;
p.add(keyMatchBtn, c);
String[] kc = {ANY_OF, ALL_OF, EXPR};
keywordsChoice = uif.createChoice("basicTf.keywords.choice", kc);
p.add(keywordsChoice, c);
keywordsField = uif.createInputField("basicTf.keywords.field", 20);
keywordsField.setEditable(true);
uif.setAccessibleInfo(keywordsField, "basicTf.keywords.field");
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
p.add(keywordsField, c);
keyAllBtn.setSelected(true);
enableKeywordFields();
return p;
}
private void enableKeywordFields() {
boolean b = keyMatchBtn.isSelected();
keywordsChoice.setEnabled(b);
keywordsField.setEnabled(b);
}
// STATUS PANEL
private JComponent createStatusPanel() {
JPanel p = uif.createPanel(
"basicTf.status.mainPanel", new GridBagLayout(), false);
p.setName("status");
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
c.gridwidth = GridBagConstraints.REMAINDER;
statusBtnGrp = new ButtonGroup();
statusAllBtn = uif.createRadioButton("basicTf.status.all", statusBtnGrp);
statusAllBtn.setMnemonic(uif.getI18NString("basicTf.status.all.mne").charAt(0));
p.add(statusAllBtn, c);
statusAnyOfBtn = uif.createRadioButton("basicTf.status.anyOf", statusBtnGrp);
statusAnyOfBtn.setMnemonic(uif.getI18NString("basicTf.status.anyOf.mne").charAt(0));
statusAnyOfBtn.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
enableStatusFields();
}
});
c.gridwidth = 1;
c.weightx = 0;
p.add(statusAnyOfBtn, c);
JPanel row = new JPanel(new GridBagLayout());
row.setBorder(BorderFactory.createEtchedBorder());
GridBagConstraints rc = new GridBagConstraints();
rc.insets.left = 10;
statusChecks[Status.PASSED] =
uif.createCheckBox("basicTf.status.prev.passed", false);
row.add(statusChecks[Status.PASSED], rc);
statusChecks[Status.FAILED] =
uif.createCheckBox("basicTf.status.prev.failed", true);
row.add(statusChecks[Status.FAILED], rc);
statusChecks[Status.ERROR] =
uif.createCheckBox("basicTf.status.prev.error", true);
row.add(statusChecks[Status.ERROR], rc);
rc.insets.right = 10;
statusChecks[Status.NOT_RUN] =
uif.createCheckBox("basicTf.status.prev.notRun", true);
row.add(statusChecks[Status.NOT_RUN], rc);
uif.setToolTip(row, "basicTf.status.prev");
statusAllBtn.setSelected(true);
enableStatusFields();
p.add(row, c);
return p;
}
private void enableStatusFields() {
boolean enable = statusAnyOfBtn.isEnabled() && statusAnyOfBtn.isSelected();
for (int i = 0; i < statusChecks.length; i++) {
statusChecks[i].setEnabled(enable);
}
}
// INIT URLS
private JComponent createTestsPanel() {
final JPanel p = uif.createPanel(
"basicTf.tests.mainPanel", new BorderLayout(), false);
p.setName("tests");
// more configure ...
lastTrt = execModel.getActiveTestResultTable();
testsField = new TestTreeSelectionPane(lastTrt);
p.add(testsField, BorderLayout.CENTER);
p.addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent e) {
TestResultTable nowTrt = execModel.getActiveTestResultTable();
// replaces widget with an updated one
// only really important if the test suite contents (structure)
// changes
// this code basically keeps it in sync with the main tree,
// otherwise it might be left behind watching a temporary TRT
if (nowTrt != lastTrt) {
TestTreeSelectionPane newTree = new TestTreeSelectionPane(nowTrt);
String[] paths = testsField.getSelection(); // save
p.remove(testsField);
testsField = newTree;
testsField.setSelection(paths); // restore
p.add(testsField, BorderLayout.CENTER);
lastTrt = nowTrt;
}
}
});
return p;
}
// JTX lists
private JComponent createExcludePanel() {
JPanel p = new JPanel(new GridBagLayout());
p.setName("exclude");
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.ipadx = 10;
c.gridwidth = 1;
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.NONE;
// column 1
c.gridwidth = 3;
jtxCheckBox = uif.createCheckBox("basicTf.exclude", false);
jtxCheckBox.setMnemonic(uif.getI18NString("basicTf.exclude.mne").charAt(0));
p.add(jtxCheckBox, c);
// create some margins
c.gridy = 1;
p.add(Box.createVerticalStrut(5), c);
c.gridy = 2;
c.gridwidth = 1;
c.gridheight = 2;
p.add(Box.createHorizontalStrut(8), c);
c.gridheight = 1;
c.gridx = 2;
// labels
final JLabel modeLab = uif.createLabel("basicTf.exclude.mode");
modeLab.setDisplayedMnemonic(uif.getI18NString("basicTf.exclude.mode.mne").charAt(0));
modeLab.setEnabled(jtxCheckBox.isSelected());
p.add(modeLab, c);
c.gridy = 3;
final JLabel fileLab = uif.createLabel("basicTf.exclude.file");
fileLab.setDisplayedMnemonic(uif.getI18NString("basicTf.exclude.file.mne").charAt(0));
fileLab.setEnabled(jtxCheckBox.isSelected());
p.add(fileLab, c);
// column 2
c.gridy = 2;
c.gridx = 3;
c.fill = GridBagConstraints.HORIZONTAL;
jtxMode = uif.createOutputField("basicTf.exclude.mode", modeLab);
jtxMode.setBorder(BorderFactory.createEmptyBorder());
jtxMode.setEditable(false);
jtxMode.setEnabled(jtxCheckBox.isSelected());
uif.setAccessibleInfo(jtxMode, "basicTf.exclude.mode");
p.add(jtxMode, c);
c.gridy = 3;
c.weightx = 2;
c.weighty = 2;
c.fill = GridBagConstraints.BOTH;
jtxFiles = new DefaultListModel();
jtxFileList = uif.createList("basicTf.exclude.file", jtxFiles);
jtxFileList.setEnabled(jtxCheckBox.isSelected());
uif.setAccessibleInfo(jtxFileList, "basicTf.exclude.file");
fileLab.setLabelFor(jtxFileList);
// might need to add a scroll panel here
p.add(uif.createScrollPane(jtxFileList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), c);
jtxCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jtxFileList.setEnabled(jtxCheckBox.isSelected());
jtxMode.setEnabled(jtxCheckBox.isSelected());
modeLab.setEnabled(jtxCheckBox.isSelected());
fileLab.setEnabled(jtxCheckBox.isSelected());
}
});
return p;
}
// test suite specific filter
private JComponent createSpecialPanel() {
String k = "basicTf.tsf";
JPanel p = uif.createPanel("basicTf.tsf", new BorderLayout(), false);
p.setName("special");
tsfCheckBox = uif.createCheckBox("basicTf.tsf", false);
tsfCheckBox.setMnemonic(uif.getI18NString("basicTf.tsf.mne").charAt(0));
p.add(tsfCheckBox, BorderLayout.CENTER);
return p;
}
/**
* Capture the settings in the current GUI.
* @return A snapshot of the settings currently entred into the GUI.
* @throws IllegalStateException If any part of the GUI has a state which
* does not produce a consistent setting. The message of this
* exception will contain an internationalized message to help the
* user resolve the problem.
*/
private SettingsSnapshot grabSettings() {
SettingsSnapshot shot = new SettingsSnapshot();
// grad top level togggle state of each type
shot.keywordsEnabled = !keyAllBtn.isSelected();
//shot.urlsEnabled = !allTestsBtn.isSelected();
shot.urlsEnabled = true; // always enabled in current impl.
shot.statusEnabled = statusAnyOfBtn.isSelected();
shot.jtxEnabled = jtxCheckBox.isSelected();
shot.tsfEnabled = tsfCheckBox.isSelected();
// grab status checkbox state
boolean oneSelected = false;
shot.statusFields = new boolean[statusChecks.length];
for (int i = 0; i < statusChecks.length; i++) {
shot.statusFields[i] = statusChecks[i].isSelected();
oneSelected = oneSelected || shot.statusFields[i];
}
if (shot.statusEnabled && !oneSelected) {
throw new IllegalStateException(uif.getI18NString("basicTf.badStatus"));
}
// init. urls
shot.initialUrls = testsField.getSelection();
// special case post processing for root selection
// if length is one and that string is zero length, that indicates
// a root selection
if (shot.initialUrls != null &&
shot.initialUrls.length == 1 &&
shot.initialUrls[0].length() == 0) {
shot.initialUrls = null;
}
// keywords
shot.keyChoice = (String) (keywordsChoice.getSelectedItem());
shot.keyString = keywordsField.getText();
return shot;
}
/**
* Put a set of settings into the GUI.
*/
private void putSettings(SettingsSnapshot s) {
// no GUI, don't do anything
if (editorPane == null) {
return;
}
keyAllBtn.setSelected(!s.keywordsEnabled);
keyMatchBtn.setSelected(s.keywordsEnabled);
statusAllBtn.setSelected(!s.statusEnabled);
statusAnyOfBtn.setSelected(s.statusEnabled);
jtxCheckBox.setSelected(s.jtxEnabled);
tsfCheckBox.setSelected(s.tsfEnabled);
for (int i = 0; i < statusChecks.length; i++) {
statusChecks[i].setSelected(s.statusFields[i]);
}
testsField.setSelection(s.initialUrls);
keywordsChoice.setSelectedItem(s.keyChoice);
keywordsField.setText(s.keyString);
updateExcludeInfo();
}
// Utility methods
private static String kwModeToType(String mode) {
if (mode == ALL_OF) {
return "all of";
} else if (mode == ANY_OF) {
return "any of";
} else {
return EXPR;
}
}
private Observer[] obs = new Observer[0];
private static int instanceCount;
private TestResultTable lastTrt;
private InterviewObserver intObs;
private static int NUM_FILTERS = 5;
private static int KEY_FILTER = 0;
private static int URL_FILTER = 1;
private static int JTX_FILTER = 2;
private static int STATUS_FILTER = 3;
private static int TSS_FILTER = 4;
private SettingsSnapshot activeSettings;
private TestFilter[] activeFilters; // for convenience
private KeywordsFilter keyFilter;
private InitialUrlFilter urlFilter;
private TestFilter jtxFilter;
private StatusFilter statusFilter;
private TestFilter tsfFilter; // test suite filter
private final UIFactory uif;
private JTabbedPane editorPane;
private boolean statusFilterNeedsUpdate;
// keyword info
private ButtonGroup keyBtnGrp;
private JRadioButton keyAllBtn;
private JRadioButton keyMatchBtn;
private JComboBox keywordsChoice;
private JTextField keywordsField;
private static final String ALL_OF = "allOf";
private static final String ANY_OF = "anyOf";
private static final String EXPR = "expr";
// status info
private ButtonGroup statusBtnGrp;
private JRadioButton statusAllBtn;
private JRadioButton statusAnyOfBtn;
private JCheckBox[] statusChecks = new JCheckBox[Status.NUM_STATES];
// tests info
private ButtonGroup testsBtnGrp;
//private JRadioButton allTestsBtn;
//private JRadioButton selectTestsBtn;
private TestTreeSelectionPane testsField;
// checkboxes to enable exclude list from interview and test suite filter
private JCheckBox jtxCheckBox;
private JCheckBox tsfCheckBox;
// jtx info fields
private JTextField jtxMode;
private JList> jtxFileList;
private DefaultListModel jtxFiles;
private static String NAME, REASON, DESCRIPTION;
/**
* Necessary to track changes which occur in the active interview.
*/
private class InterviewObserver implements Interview.Observer {
InterviewObserver(InterviewParameters i) {
interview = i;
}
InterviewParameters getInterview() {
return interview;
}
public void currentQuestionChanged(Question q) {
// ignore
}
public void pathUpdated() {
TestFilter underTest;
boolean needsUpdate = false;
updateExcludeInfo();
// determine if jtx and tsf filters were updated
if (activeSettings.jtxEnabled) {
// we only support copying exclude list from interview
// right now
InterviewParameters ip = execModel.getInterviewParameters();
if (ip != null) {
// may set var. to null, but that's okay
underTest = ip.getExcludeListFilter();
if (underTest != null &&
(jtxFilter == null || !underTest.equals(jtxFilter))) {
needsUpdate = true;
} else if (jtxFilter != null) // jtx filter now null
{
needsUpdate = true;
}
}
}
if (needsUpdate) {
activateSettings(activeSettings);
return; // rest of checking no longer needed
}
if (activeSettings.tsfEnabled) {
// we only support copying exclude list from interview
// right now
InterviewParameters ip = execModel.getInterviewParameters();
TestSuite ts = execModel.getTestSuite();
if (ip != null && ts != null) {
underTest = ts.createTestFilter(ip.getEnv());
if (underTest != null) {
if (tsfFilter == null || !underTest.equals(tsfFilter)) {
needsUpdate = true;
} else {
}
} else if (tsfFilter != null) // tsf filter now null
{
needsUpdate = true;
} else {
}
} else {
}
}
if (needsUpdate) {
activateSettings(activeSettings);
return; // rest of checking no longer needed
}
}
private InterviewParameters interview;
}
private class SettingsSnapshot {
SettingsSnapshot() {
statusFields = new boolean[Status.NUM_STATES];
urlsEnabled = true;
keyChoice = EXPR;
keyString = "";
}
SettingsSnapshot(Map m) {
this();
load(m);
}
public boolean equals(Object settings) {
if (settings == null) {
return false;
}
SettingsSnapshot incoming = (SettingsSnapshot) settings;
if (!Arrays.equals(initialUrls, incoming.initialUrls)) {
return false;
}
if (keywordsEnabled != incoming.keywordsEnabled) {
return false;
} else {
if (keyChoice != incoming.keyChoice) {
return false;
}
// destination of structure is to handle null values
if (keyString == null) {
if (keyString != incoming.keyString) {
return false;
} else {
}
} else {
if (!keyString.equals(incoming.keyString)) {
return false;
} else {
}
}
} // outer else
if (statusEnabled != incoming.statusEnabled) {
return false;
} else if (!Arrays.equals(statusFields, incoming.statusFields)) {
return false;
}
if (jtxEnabled != incoming.jtxEnabled) {
return false;
}
if (tsfEnabled != incoming.tsfEnabled) {
return false;
}
return true;
} // equals()
void save(Map map) {
map.put(MAP_URL_ENABLE, booleanToInt(urlsEnabled));
map.put(MAP_KEY_ENABLE, booleanToInt(keywordsEnabled));
map.put(MAP_STATUS_ENABLE, booleanToInt(statusEnabled));
map.put(MAP_JTX_ENABLE, booleanToInt(jtxEnabled));
map.put(MAP_TSF_ENABLE, booleanToInt(tsfEnabled));
for (int i = 0; i < statusFields.length; i++) {
map.put(MAP_STATUS_PREFIX + i, booleanToInt(statusFields[i]));
}
map.put(MAP_URLS, StringArray.join(initialUrls));
map.put(MAP_KEY_CHOICE, keyChoice);
map.put(MAP_KEY_STRING, keyString);
}
void load(Map map) {
urlsEnabled = intToBoolean((map.get(MAP_URL_ENABLE)));
keywordsEnabled = intToBoolean((map.get(MAP_KEY_ENABLE)));
statusEnabled = intToBoolean((map.get(MAP_STATUS_ENABLE)));
jtxEnabled = intToBoolean((map.get(MAP_JTX_ENABLE)));
tsfEnabled = intToBoolean((map.get(MAP_TSF_ENABLE)));
for (int i = 0; i < Status.NUM_STATES; i++) {
statusFields[i] = intToBoolean((map.get(MAP_STATUS_PREFIX + i)));
} // for
initialUrls = StringArray.split((map.get(MAP_URLS)));
keyChoice = map.get(MAP_KEY_CHOICE);
keyString = map.get(MAP_KEY_STRING);
validate();
}
private void validate() {
// conserve strings, but also sync with the actual
// objects in the choice list for easy use
if (keyChoice.equals(ALL_OF)) {
keyChoice = ALL_OF;
} else if (keyChoice.equals(ANY_OF)) {
keyChoice = ANY_OF;
} else if (keyChoice.equals(EXPR)) {
keyChoice = EXPR;
} else {
keyChoice = ALL_OF; // unknown, use default
}
}
String booleanToInt(boolean val) {
if (val) {
return "1";
} else {
return "0";
}
}
boolean intToBoolean(String num) {
if (num == null) {
return false;
}
if (num.equals("1")) {
return true;
} else {
return false;
}
}
boolean urlsEnabled;
boolean keywordsEnabled;
boolean statusEnabled;
boolean jtxEnabled;
boolean tsfEnabled;
boolean[] statusFields;
String[] initialUrls;
String keyChoice;
String keyString;
private static final String MAP_URL_ENABLE = "urlsEnabled";
private static final String MAP_KEY_ENABLE = "keyEnabled";
private static final String MAP_STATUS_ENABLE = "statusEnable";
private static final String MAP_JTX_ENABLE = "jtxEnable";
private static final String MAP_TSF_ENABLE = "tsfEnable";
private static final String MAP_URLS = "urls";
private static final String MAP_KEY_CHOICE = "keyChoice";
private static final String MAP_KEY_STRING = "keyString";
private static final String MAP_STATUS_PREFIX = "status";
}
}