/*
* Created on Dec 14, 2005
*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.treeui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.plaf.ColorUIResource;
import javax.swing.tree.TreePath;
import jsystem.extensions.report.html.HtmlCodeWriter;
import jsystem.framework.scenario.DistributedExecutionHelper;
import jsystem.framework.scenario.DistributedExecutionParameter;
import jsystem.framework.scenario.JTest;
import jsystem.framework.scenario.JTestContainer;
import jsystem.framework.scenario.MultipleScenarioOps;
import jsystem.framework.scenario.Parameter;
import jsystem.framework.scenario.ParameterUtils;
import jsystem.framework.scenario.PresentationDefinitions;
import jsystem.framework.scenario.RunnerFixture;
import jsystem.framework.scenario.RunnerTest;
import jsystem.framework.scenario.Scenario;
import jsystem.framework.scenario.ScenarioParameter;
import jsystem.framework.scenario.UIHandler;
import jsystem.framework.scenario.ValidationError;
import jsystem.framework.scenario.ValidationError.Originator;
import jsystem.framework.scenario.flow_control.AntFlowControl;
import jsystem.guiMapping.JsystemMapping;
import jsystem.runner.ErrorLevel;
import jsystem.treeui.client.JSystemAgentClientsPool;
import jsystem.treeui.error.ErrorPanel;
import jsystem.treeui.images.ImageCenter;
import jsystem.treeui.params.ParametersPanel;
import jsystem.treeui.teststable.ScenarioTreeNode;
import jsystem.treeui.teststable.TestsTableController;
import jsystem.utils.StringUtils;
import jsystem.utils.SwingUtils;
import junit.framework.SystemTest;
/**
* @author guy.arieli
*
*/
public class TestInformationTab implements TreeSelectionListener, FocusListener, ParameterListener, ActionListener,
ChangeListener {
HTMLJavaDocView testDocumentation;
JTextArea testUserDocumentation;
JLabel runningTime;
JLabel fixture;
JLabel failToFixture;
JLabel classLabel;
JLabel returnParams;
JPanel pane;
JTree tableTree;
JTabbedPane tabbes;
JTabbedPane docTabs;
ParametersPanel ppanel;
JTest currentTest = null;
JButton applyButton;
private String userDoc;
TestsTableController testTableController;
private UserDocumentation ud;
private static Logger log = Logger.getLogger(TestInformationTab.class.getName());
private String currentSectionName = "";
private ScenarioTreeNode node;
public TestInformationTab(TestsTableController testTableController) {
this.testTableController = testTableController;
testTableController.getTree().getSelectionModel().addTreeSelectionListener(this);
testTableController.getTree().addFocusListener(this);
ud = new UserDocumentation(testTableController);
ud.setBackground(new Color(0xf6, 0xf6, 0xf6));
}
public JPanel getTestInformationPanel() {
pane = new JPanel();
pane.setLayout(new BorderLayout());
pane.setPreferredSize(new Dimension(pane.getWidth(), 400));
JPanel docPane = new JPanel();
docPane.setLayout(new BorderLayout());
testDocumentation = new HTMLJavaDocView(new Color(0xf6, 0xf6, 0xf6));
testDocumentation.setEditable(false);
JScrollPane sp = new JScrollPane(testDocumentation);
docPane.setSize(new Dimension(pane.getWidth(), 100));
docPane.add(sp, BorderLayout.CENTER);
JPanel testInfoPane = new JPanel();
testInfoPane.setLayout(new GridLayout(5, 1));
testInfoPane.setBackground(new Color(0xf6, 0xf6, 0xf6));
classLabel = new JLabel();
testInfoPane.add(classLabel);
fixture = new JLabel();
testInfoPane.add(fixture);
failToFixture = new JLabel();
testInfoPane.add(failToFixture);
returnParams = new JLabel();
testInfoPane.add(returnParams);
runningTime = new JLabel();
testInfoPane.add(runningTime);
ppanel = new ParametersPanel(this, testTableController);
pane.add(testInfoPane, BorderLayout.NORTH);
docTabs = SwingUtils.getJTabbedPaneWithBgImage(
ImageCenter.getInstance().getImage(ImageCenter.ICON_TABBES_TOOLBAR_BG), ImageCenter.getInstance()
.getImage(ImageCenter.ICON_TABBES_TOOLBAR_BG));
docPane.setBackground(new Color(0xf6, 0xf6, 0xf6));
docTabs.add(docPane, "Test Documentation");
docTabs.add(ud, "User Test Documentation");
UIDefaults uidefs = UIManager.getLookAndFeelDefaults();
uidefs.put("SplitPane.background", new ColorUIResource(new Color(0x99, 0xaa, 0xbb)));
JSplitPane spp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, docTabs, ppanel);
spp.setDividerLocation(150);
pane.add(spp, BorderLayout.CENTER);
return pane;
}
/**
* used when test has changed and a new information has to be displayed
*
* @param jtest
* the new test to display
* @param applyJTestContainer
* @param updateParameterChange
*
*/
public void setCurrentTest(JTest jtest, boolean applyJTestContainer, boolean updateParameterChange) {
// save previous test settings
updateCurrentTestUIDefinition();
if (updateParameterChange) {
parameterChanged(applyJTestContainer);
}
if (!StringUtils.isEmpty(ppanel.getActiveSectionName())) {
currentSectionName = ppanel.getActiveSectionName();
}
Parameter[] clonedParameters = null;
// load new test and update ui with new test
if (jtest != null) {
jtest.loadParametersAndValues();
clonedParameters = ParameterUtils.clone(jtest.getVisibleParamters(ppanel.recursiveRegulerParameter
.isSelected()));
if (jtest instanceof UIHandler) {
((UIHandler) jtest).handleUIEvent(clonedParameters);
if (jtest instanceof RunnerTest) {
ValidationError[] errors = ((RunnerTest) jtest).validate(clonedParameters);
ValidationError.clearValidatorsWithOriginator(jtest.getValidationErrors(), Originator.TEST);
if (errors != null) {
for (ValidationError error : errors) {
error.setOriginator(Originator.TEST);
}
jtest.getValidationErrors().addAll(Arrays.asList(errors));
}
}
}
}
synchronized (TestInformationTab.class) {
currentTest = jtest;
}
ud.setTest(jtest);
setTextDocumentation(null);
setName("", "");
setFailToFixture("");
setFixtureName("");
setRunningTime(-1);
if (jtest == null) {
ud.resetText("", false);
ud.setTest(null);
userDoc = "";
docTabs.setSelectedIndex(0);
ppanel.reset();
ppanel.repaint();
pane.repaint();
return;
}
/**
* if a test has a user documentation then set it as default (1)
* otherwise set the test documentation as default (0)
*/
userDoc = jtest.getDocumentation();
ud.setEnabled(true);
if (!StringUtils.isEmpty(userDoc)) {
docTabs.setSelectedIndex(1);
} else {
docTabs.setSelectedIndex(0);
}
ud.resetText(userDoc, true);
ScenarioParameter[] scenarioParameters = null;
ppanel.setIsJTestContainer((jtest instanceof JTestContainer));
if (jtest instanceof RunnerTest) {
RunnerTest test = (RunnerTest) jtest;
String className = test.getClassName();
String methodName = test.getMethodName();
setName(className, methodName);
updateUD();
String doc = null;
try {
doc = HtmlCodeWriter.getInstance().getMethodJavaDoc(className, methodName);
} catch (Exception e1) {
log.log(Level.WARNING, "Fail to read javadoc", e1);
}
if (StringUtils.isEmpty(doc)) {
doc = test.getDocumentation();
}
if (doc != null) {
setTextDocumentation(doc);
}
String[] retParams = test.getReturnParameters();
if (retParams == null) {
setReturnParams("");
} else {
setReturnParams(StringUtils.objectArrayToString(",", (Object[]) retParams));
}
if (test.getTest() instanceof SystemTest) {
SystemTest sTest = (SystemTest) test.getTest();
setFixtureName(sTest.getFixture().getName());
Class<?> ff = sTest.getTearDownFixture();
if (ff != null) {
setFailToFixture(ff.getName());
} else {
setFailToFixture("not set");
}
}
setRunningTime(ProgressController.getTestTime(className, methodName));
} else if (jtest instanceof Scenario) {
updateUD();
Scenario scenario = (Scenario) jtest;
setScenarioName(scenario.getName());
scenarioParameters = scenario.getScenarioParameters(true, ppanel.recursiveReference.isSelected());
} else if (jtest instanceof AntFlowControl) {
docTabs.remove(ud);
}
DistributedExecutionParameter[] hostsParameters = new DistributedExecutionParameter[0];
try {
if ((jtest instanceof RunnerTest || jtest instanceof Scenario) // hosts
// tab
// should
// be
// shown
// only
// for
// scenarios
// and
// tests.
&& ((JSystemAgentClientsPool.getClients(null).length > 0) || DistributedExecutionHelper
.isAssigned(jtest))) { // show agents tab if runner
// is connected to agents or
// test is associated to an
// agent
hostsParameters = jtest.getDistributedExecutionParameters();
if (DistributedExecutionHelper.ancestorIsAssignedWithHosts(jtest)) {
ParameterUtils.setEnabled(hostsParameters, false);
}
if (jtest.getParent() == null) {
ParameterUtils.setVisible(hostsParameters, false);
}
if (jtest instanceof RunnerFixture) {
ParameterUtils.setVisible(hostsParameters, false);
}
}
} catch (Exception e) {
ErrorPanel.showErrorDialog("Failure loading JSystem hosts", e, ErrorLevel.Error);
}
if (jtest instanceof RunnerTest) {
ppanel.setSectionOrder(((RunnerTest) jtest).getSectionOrder());
}
PresentationDefinitions sort = jtest.getPresentationObject();
if (sort != null) {
ppanel.changeVals(sort);
} else {
sort = new PresentationDefinitions();
jtest.setPresentationObject(sort);
}
ppanel.setParameters(clonedParameters, scenarioParameters, hostsParameters);
ppanel.setActiveTab(currentSectionName);
testTableController.getTree().requestFocusInWindow();
}
private void handleWithMandatoryParameters(Parameter[] clonedParameters) {
for (Parameter currentParameter : clonedParameters) {
if (currentParameter.isMandatory()
&& (currentParameter.getValue() == null || currentParameter.getValue().toString().isEmpty())) {
ValidationError error = new ValidationError();
error.setOriginator(Originator.TEST);
error.setTitle("Parameter " + currentParameter.getName() + " is mandatory");
currentTest.addValidationError(error);
}
}
}
private void updateUD() {
// TODO Fixed Ticket #158
boolean isMissing = true;
for (Component comp : docTabs.getComponents()) {
if (comp instanceof UserDocumentation) {
isMissing = false;
break;
}
}
if (isMissing) {
docTabs.add(ud, "User Test Documentation");
}
}
public void updateCurrentTestUIDefinition() {
if (currentTest == null) {
return;
}
PresentationDefinitions sort = currentTest.getPresentationObject();
sort.saveDefinitions(ppanel.getSortSection(), ppanel.getSortHeader(), ppanel.getParametersOrder(),
ppanel.getActiveTab(), ppanel.getHeaderRatio());
}
/**
* resets the information tab and sets currentTest to null
*
*/
public void resetInformationTab() {
setCurrentTest(null, false, true);
}
private void setTextDocumentation(String doc) {
if (doc == null) {
doc = "To set the documentation javadoc the test source";
}
testDocumentation.setContent(doc);
}
private void setRunningTime(long runningTime) {
if (runningTime >= 0) {
this.runningTime.setText(bold("Last run time: " + runningTime / 1000 + " Sec."));
} else {
this.runningTime.setText(bold("Last run time: unknown"));
}
}
private void setFixtureName(String name) {
fixture.setText(bold("Fixture: " + name));
}
private void setFailToFixture(String name) {
failToFixture.setText(bold("Fail to fixture: " + name));
}
private void setReturnParams(String name) {
returnParams.setText(bold("Return parameters: " + name));
}
private void setName(String className, String methodName) {
classLabel.setText(bold("Name: " + className + "-" + methodName));
}
private void setScenarioName(String name) {
classLabel.setText(bold("Name: " + name));
}
private static String bold(String in) {
return "<html><B>" + in + "</B></html>";
}
public void setTabbes(JTabbedPane tabbes) {
this.tabbes = tabbes;
}
/**
*
*/
public void parameterChanged(boolean isApplyForScenario) {
/**
* synchronized to prevent null pointer exception that can be created if
* currentTest changes in the middle
*/
synchronized (TestInformationTab.class) {
if (currentTest == null) {
return;
}
ppanel.stopEditing();
boolean uiHandlerWasActivated = false;
try {
// first update the scenario reference parameters
ScenarioParameter[] scenarioParameters = ppanel.getScenarioParameters();
if (currentTest instanceof Scenario && ParameterUtils.isDirty(scenarioParameters)) {// &&
// (!ppanel.recursiveReference.isSelected() ||
// isApplyForScenario)){
((Scenario) currentTest).setScenarioParameters(scenarioParameters, isApplyForScenario);
}
// then update hosts
DistributedExecutionParameter[] hostsParameters = ppanel.getHostParameters();
if (ParameterUtils.isDirty(hostsParameters)) {
currentTest.setDistributedExecutionParameters(hostsParameters);
}
// don't update scenario test parameters if apply wasn't pressed
if (currentTest instanceof Scenario && !isApplyForScenario) {
return;
}
ppanel.applyJTestContainer.setEnabled(false);
if (currentTest instanceof UIHandler) {
Parameter[] parameterArray = ppanel.getTestParameters();
uiHandlerWasActivated = ((UIHandler) currentTest).handleUIEvent(parameterArray);
if (currentTest instanceof RunnerTest) {
ValidationError.clearValidatorsWithOriginator(currentTest.getValidationErrors(),
Originator.TEST);
handleWithMandatoryParameters(parameterArray);
ValidationError[] errors = ((RunnerTest) currentTest).validate(parameterArray);
if (errors != null) {
for (ValidationError error : errors) {
error.setOriginator(Originator.TEST);
}
currentTest.getValidationErrors().addAll(Arrays.asList(errors));
}
}
}
if (!ParameterUtils.isDirty(ppanel.getAllParameters())) {
return;
}
updateCurrentTestUIDefinition();
MultipleScenarioOps.updateTest(currentTest, ppanel.getTestParameters(),
ppanel.recursiveRegulerParameter.isSelected());
// Reset the tree, since Ant Flow Control's comment might have
// changed
this.testTableController.fireCurrentNodeChange();
} catch (Exception e1) {
ErrorPanel
.showErrorDialog("Failed updating scenario.", StringUtils.getStackTrace(e1), ErrorLevel.Error);
}
if (uiHandlerWasActivated) {
ppanel.buildTabs();
}
}
}
/**
* implementation of ChangeListener. Invoked when tab selection (Test Tree,
* Reporter, Test Info ...) is changed. In case the user selects tab 2 (Test
* Info) the test info panel is refreshed.
*/
public void stateChanged(ChangeEvent e) {
TreePath treePath = testTableController.getTree().getSelectionPath();
if (treePath == null || treePath.getLastPathComponent() == null) {
return;
}
node = (ScenarioTreeNode) treePath.getLastPathComponent();
if (testTableController.getTabbes().getSelectedIndex() == 2) {
setCurrentTest(node.getTest(), false, true);
}
}
/**
* Invoked when the user changes selection in the scenario tree. In case the
* selected tab is 2 (Test Info) the test info panel is refreshed.
*/
public void valueChanged(TreeSelectionEvent e) {
if (testTableController.isEventCheckEvent()) {
return;
}
TreePath[] paths = e.getPaths();
if (paths == null) {
return;
}
node = (ScenarioTreeNode) e.getPath().getLastPathComponent();
if (testTableController.getTabbes().getSelectedIndex() != 2) {
return;
}
/**
* not allowed for scenarios, only for tests
*/
if (node.getTest() != currentTest) {
// We can gain major performance improvement when traveling between
// BB if we change the last parameter the false. The problem is that
// we will lose support for the mandatory parameter feature and when
// leaving parameter of BB when it is in focus, the value will not
// be saved.
//TODO: Change the last parameter to false.
setCurrentTest(node.getTest(), false, true);
}
}
public void focusGained(FocusEvent e) {
}
/**
*
*/
public void focusLost(FocusEvent e) {
TreePath treePath = testTableController.getTree().getSelectionPath();
if (treePath == null) {
/**
* not allowed for scenarios, only for tests
*/
setCurrentTest(null, false, true);
} else {
ScenarioTreeNode node = (ScenarioTreeNode) treePath.getLastPathComponent();
if (node == null) {
/**
* not allowed for scenarios, only for tests
*/
setCurrentTest(null, false, true);
}
}
}
public TestsTableController getTestTableController() {
return testTableController;
}
/**
* serves the applyJTestContainer button
*/
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source.equals(ppanel.applyJTestContainer)) {
boolean applyRecursively = ppanel.recursiveRegulerParameter.isSelected();
boolean applyChanges = showapplyJTestContainerDialog(applyRecursively);
if (!applyChanges) {
return;
}
if (node.getTest() instanceof JTestContainer) {
setCurrentTest(node.getTest(), true, true);
}
} else if (source.equals(ppanel.recursiveReference) || source.equals(ppanel.recursiveRegulerParameter)) {
ppanel.resetDirty = false;
setCurrentTest(node.getTest(), false, true);
}
}
private boolean showapplyJTestContainerDialog(boolean recursively) {
StringBuffer buffer = new StringBuffer();
if (recursively) {
buffer.append("The following parameters will be updated in ALL sub tests:");
} else {
buffer.append("The following parameters will be updated in ROOT tests only:");
}
buffer.append(System.getProperty("line.separator"));
buffer.append(System.getProperty("line.separator"));
Parameter[] params = ppanel.getAllParameters();
String lineSeperator = System.getProperty("line.separator");
boolean scenarioDirty = false;
for (Parameter p : params) {
if (p.isDirty()) {
if (p instanceof ScenarioParameter) {
scenarioDirty = true;
}
buffer.append(p.getName() + " new value: " + p.getValue() + lineSeperator);
}
}
if (ppanel.recursiveReference.isSelected() && scenarioDirty) {
if (JOptionPane.showConfirmDialog(ppanel,
"NOTICE: Reference parameters will be changed in All sub-scenarios recursively. continue?",
JsystemMapping.getInstance().getRecursiveDialogTitle(), JOptionPane.YES_NO_OPTION) != 0) {
return false;
}
}
TextArea area = new TextArea();
area.setEditable(false);
area.setEnabled(true);
area.setText(buffer.toString());
int res = JOptionPane.showConfirmDialog(ppanel, area, "Apply Scenario Parameters", JOptionPane.YES_NO_OPTION);
return res == 0;
}
/**
* refreshes the information tab<br>
* refreshes the last test, without updating the parameters
*/
public void refresh() {
setCurrentTest(currentTest, false, false);
}
}