./codecover/src/org/codecover/eclipse/views/BooleanAnalyzer.java
/******************************************************************************
* Copyright (c) 2007 Stefan Franke, Robert Hanussek, Benjamin Keil, *
* Steffen Kieß, Johannes Langauf, *
* Christoph Marian Müller, Igor Podolskiy, *
* Tilmann Scheller, Michael Starzmann, Markus Wittlinger *
* All rights reserved. This program and the accompanying materials *
* are made available under the terms of the Eclipse Public License v1.0 *
* which accompanies this distribution, and is available at *
* http://www.eclipse.org/legal/epl-v10.html *
******************************************************************************/
package org.codecover.eclipse.views;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.codecover.eclipse.CodeCoverPlugin;
import org.codecover.eclipse.Messages;
import org.codecover.eclipse.tscmanager.ActiveTSContainerInfo;
import org.codecover.eclipse.tscmanager.TSContainerInfo;
import org.codecover.eclipse.tscmanager.TSContainerManagerListener;
import org.codecover.metrics.coverage.CoverageResult;
import org.codecover.metrics.coverage.TermCoverage;
import org.codecover.model.TestCase;
import org.codecover.model.TestSession;
import org.codecover.model.TestSessionContainer;
import org.codecover.model.mast.BasicBooleanTerm;
import org.codecover.model.mast.BooleanAssignment;
import org.codecover.model.mast.BooleanAssignmentMap;
import org.codecover.model.mast.BooleanResult;
import org.codecover.model.mast.BooleanTerm;
import org.codecover.model.mast.HierarchyLevel;
import org.codecover.model.mast.Location;
import org.codecover.model.mast.OperatorTerm;
import org.codecover.model.mast.RootTerm;
import org.codecover.model.utils.ChangeType;
import org.codecover.model.utils.criteria.Criterion;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;
/**
* This {@link BooleanAnalyzer} is a view in eclipse. It provides the user with
* the opportunity to view the conditions contained in their SUTs and the
* assignments, that occurred during the execution. Also displayed is the amount
* of {@link TermCoverage} the condition achieved and which of the
* {@link BasicBooleanTerm}s are covered under this {@link Criterion}.
*
* @author Markus Wittlinger
* @version 1.0 ($Id: BooleanAnalyzer.java 71 2010-04-14 18:28:46Z schmidberger $)
*/
public class BooleanAnalyzer extends ViewPart {
private static final String LABEL_CLASS = Messages
.getString("BooleanAnalyzer.LABEL_CLASS"); //$NON-NLS-1$
private static final String LABEL_CONDITION = Messages
.getString("BooleanAnalyzer.LABEL_CONDITION"); //$NON-NLS-1$
private static final String HEADER_TEST_CASES = Messages
.getString("BooleanAnalyzer.HEADER_TEST_CASES"); //$NON-NLS-1$
private static final String HEADER_RESULT = Messages
.getString("BooleanAnalyzer.HEADER_RESULT"); //$NON-NLS-1$
private static final String STATUS_BAR_TEXT = Messages
.getString("BooleanAnalyzer.STATUS_BAR_TEXT"); //$NON-NLS-1$
private static final String COLUMN_STORE_KEY = "columnStoreKeyBooleanTerm"; //$NON-NLS-1$
private TableViewer tableViewer;
private Label statusBar;
private Combo classCombo;
private Combo conditionCombo;
private final List classList;
private final List conditionList;
private final TSManagerListener managerListener;
/**
* Constructor
*/
public BooleanAnalyzer() {
this.classList = new LinkedList();
this.conditionList = new LinkedList();
this.managerListener = new TSManagerListener();
CodeCoverPlugin.getDefault().getTSContainerManager().addListener(
this.managerListener);
CodeCoverPlugin.getDefault().setBooleanAnalyzer(this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(4, false));
Label classLabel = new Label(parent, SWT.NONE);
classLabel.setText(LABEL_CLASS);
this.classCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
this.classCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ActiveTSContainerInfo activeTSCInfo = CodeCoverPlugin
.getDefault().getTSContainerManager()
.getActiveTSContainer();
fillConditionList(getSelectedClass());
fillConditionComboBox();
createTableColumns(getSelectedRootTerm());
if (activeTSCInfo != null) {
fillTable(new LinkedList(activeTSCInfo
.getActiveTestCases()), getSelectedRootTerm());
} else {
fillTable(new LinkedList(), getSelectedRootTerm());
}
}
});
Label conditionLabel = new Label(parent, SWT.NONE);
conditionLabel.setText(LABEL_CONDITION);
this.conditionCombo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
this.conditionCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ActiveTSContainerInfo activeTSCInfo = CodeCoverPlugin
.getDefault().getTSContainerManager()
.getActiveTSContainer();
createTableColumns(getSelectedRootTerm());
if (activeTSCInfo != null) {
fillTable(new LinkedList(activeTSCInfo
.getActiveTestCases()), getSelectedRootTerm());
} else {
fillTable(new LinkedList(), getSelectedRootTerm());
}
}
});
this.conditionCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER,
true, false));
this.tableViewer = new TableViewer(parent, SWT.HIDE_SELECTION
| SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION
| SWT.MULTI);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.horizontalSpan = 4;
this.tableViewer.getTable().setLayoutData(gridData);
this.tableViewer.getTable().setHeaderVisible(true);
this.tableViewer.setLabelProvider(new TableLabelAndColorProvider());
this.tableViewer.setContentProvider(new TableContentProvider());
this.statusBar = new Label(parent, SWT.NONE);
final GridData statusLabelGridData = new GridData(SWT.FILL, SWT.CENTER,
true, false);
statusLabelGridData.horizontalSpan = 4;
this.statusBar.setLayoutData(statusLabelGridData);
ActiveTSContainerInfo activeTSCInfo = CodeCoverPlugin.getDefault()
.getTSContainerManager().getActiveTSContainer();
TestSessionContainer currentTSC;
if (activeTSCInfo != null) {
currentTSC = activeTSCInfo.getTestSessionContainer();
} else {
currentTSC = null;
}
fillClassList(currentTSC);
fillClassComboBox();
fillConditionList(getSelectedClass());
fillConditionComboBox();
createTableColumns(getSelectedRootTerm());
if (activeTSCInfo != null) {
fillTable(new LinkedList(activeTSCInfo
.getActiveTestCases()), getSelectedRootTerm());
} else {
fillTable(new LinkedList(), getSelectedRootTerm());
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
@Override
public void dispose() {
CodeCoverPlugin.getDefault().getTSContainerManager().removeListener(
this.managerListener);
}
private final RootTerm getSelectedRootTerm() {
int index = this.conditionCombo.getSelectionIndex();
if (index == -1) {
return null;
}
if (index >= this.conditionList.size()) {
CodeCoverPlugin
.getDefault()
.getLogger()
.error(
"Boolean Analyzer: Invalid index in the list of conditions"); //$NON-NLS-1$
return null;
}
return this.conditionList.get(index);
}
private final HierarchyLevel getSelectedClass() {
int index = this.classCombo.getSelectionIndex();
if (index == -1) {
return null;
}
if (index >= this.classList.size()) {
CodeCoverPlugin.getDefault().getLogger().error(
"Boolean Analyzer: Invalid index in the list of classes"); //$NON-NLS-1$
return null;
}
return this.classList.get(index);
}
private final void fillConditionComboBox() {
this.conditionCombo.removeAll();
String[] itemNames = new String[this.conditionList.size()];
for (int i = 0; i < itemNames.length; i++) {
itemNames[i] = getConditionNameFromRootTerm(this.conditionList
.get(i));
}
if (this.conditionList.size() > 0) {
this.conditionCombo.setItems(itemNames);
}
this.conditionCombo.select(0);
}
/**
* Gets the full text of a condition for display in the ComboBox.
*
* @param rootTerm
* the {@link RootTerm} to be displayed.
* @return the string representing the {@link RootTerm}.
*/
private final String getConditionNameFromRootTerm(RootTerm rootTerm) {
final StringBuilder sb = new StringBuilder();
traverseRootTerm(rootTerm.getTerm(), new Visitor() {
public void visit(BasicBooleanTerm booleanTerm) {
for (Location location : booleanTerm.getLocation()
.getLocations()) {
appendString(sb, location.getContent());
}
}
public void visit(OperatorTerm operatorTerm) {
appendString(sb, operatorTerm.getShortNameOfOperator());
}
public void visit(OperatorTerm operatorTerm, String name) {
appendString(sb, name);
}
public void visit(String name) {
appendString(sb, name);
}
private void appendString(final StringBuilder sb, String name) {
sb.append(name);
sb.append(" "); //$NON-NLS-1$
}
});
String name = sb.toString();
// Compact the name of the condition, by removing unnecessary spaces
// between braces.
name = name.replaceAll("\\(\\s", "("); //$NON-NLS-1$ //$NON-NLS-2$
name = name.replaceAll("\\s\\)", ")"); //$NON-NLS-1$ //$NON-NLS-2$
return name;
}
private final void fillConditionList(HierarchyLevel classLevel) {
this.conditionList.clear();
if (classLevel == null) {
return;
}
classLevel.accept(null, null, null, null, new RootTerm.Visitor() {
public void visit(RootTerm term) {
BooleanAnalyzer.this.conditionList.add(term);
}
}, null, null, null, null);
}
private final void fillClassComboBox() {
this.classCombo.removeAll();
String[] itemNames = new String[this.classList.size()];
for (int i = 0; i < itemNames.length; i++) {
itemNames[i] = this.classList.get(i).getName();
}
if (this.classList.size() > 0) {
this.classCombo.setItems(itemNames);
}
this.classCombo.select(0);
}
private final void fillClassList(TestSessionContainer testSessionContainer) {
this.classList.clear();
if (testSessionContainer == null) {
return;
}
HierarchyLevel topLevel = testSessionContainer.getCode();
topLevel.accept(new HierarchyLevel.Visitor() {
public void visit(HierarchyLevel hierarchyLevel) {
if (isHierarchyLevelTypeForClass(hierarchyLevel.getType()
.getInternalName())) {
BooleanAnalyzer.this.classList.add(hierarchyLevel);
}
}
}, null, null, null, null, null, null, null, null);
}
private final boolean isHierarchyLevelTypeForClass(String internalName) {
if (internalName.equals("class") || internalName.equals("interface") //$NON-NLS-1$ //$NON-NLS-2$
|| internalName.equals("enum") //$NON-NLS-1$
|| internalName.equals("@interface")) { //$NON-NLS-1$
return true;
}
return false;
}
/**
* Creates the {@link TableColumn} according to the {@link OperatorTerm}s
* and {@link BasicBooleanTerm}s of the given {@link RootTerm}.
*
* @param rootTerm
* the given {@link RootTerm}, to be used in the creation of the
* columns.
*/
private final void createTableColumns(RootTerm rootTerm) {
// Remove all the old table columns
for (TableColumn tableColumn : this.tableViewer.getTable().getColumns()) {
tableColumn.dispose();
}
if (rootTerm == null) {
return;
}
// We traverse the RootTerm and create TableColums for every time the
// visitor is called. The BooleanTerm is stored in the TableColum for
// later usage and ease of the retrieval of the information, that is to
// be displayed in the table.
traverseRootTerm(rootTerm.getTerm(), new Visitor() {
public void visit(BasicBooleanTerm booleanTerm) {
StringBuilder sb = new StringBuilder();
for (Location location : booleanTerm.getLocation()
.getLocations()) {
sb.append(location.getContent());
sb.append(" "); //$NON-NLS-1$
}
createTableColumn(sb.toString(), COLUMN_STORE_KEY, booleanTerm);
}
public void visit(OperatorTerm operatorTerm) {
createTableColumn(operatorTerm.getShortNameOfOperator(),
COLUMN_STORE_KEY, operatorTerm);
}
public void visit(OperatorTerm operatorTerm, String name) {
createTableColumn(name, COLUMN_STORE_KEY, operatorTerm);
}
public void visit(String name) {
createTableColumn(name);
}
/**
* Creates a {@link TableColumn} with the given text and returns it.
*
* @param text
* the header text.
* @return the created {@link TableColumn}
*/
private TableColumn createTableColumn(String text) {
TableColumn tableColumn = new TableColumn(
BooleanAnalyzer.this.tableViewer.getTable(), SWT.CENTER);
// The columns seem to consume a leading '&' so we add another
// one, which seems to work. Is an ugly workaround.
tableColumn.setText(escapeAmpersand(text));
tableColumn.pack();
return tableColumn;
}
private String escapeAmpersand(String input) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
sb.append(c);
if (c == '&') {
sb.append(c);
}
}
return sb.toString();
}
/**
* Creates a {@link TableColumn} with the given text and stores the
* given data under the given key and returns the created
* {@link TableColumn}.
*
* @param text
* the header text.
* @param key
* the key to be used in the storage
* @param data
* the data to be stored.
* @return the created {@link TableColumn}
*/
private TableColumn createTableColumn(String text, String key,
Object data) {
TableColumn tableColumn = createTableColumn(text);
tableColumn.setData(key, data);
return tableColumn;
}
});
TableColumn resultColumn = new TableColumn(this.tableViewer.getTable(),
SWT.CENTER);
resultColumn.setText(HEADER_RESULT);
resultColumn.pack();
TableColumn testCaseColumn = new TableColumn(this.tableViewer
.getTable(), SWT.LEFT);
testCaseColumn.setText(HEADER_TEST_CASES);
testCaseColumn.pack();
}
private final void traverseRootTerm(BooleanTerm booleanTerm, Visitor visitor) {
if (booleanTerm instanceof BasicBooleanTerm) {
visitor.visit((BasicBooleanTerm) booleanTerm);
} else if (booleanTerm instanceof OperatorTerm) {
OperatorTerm operatorTerm = (OperatorTerm) booleanTerm;
switch (operatorTerm.getOperator().getArity()) {
case 0:
visitor.visit(operatorTerm);
break;
case 1:
visitor.visit(operatorTerm);
traverseRootTerm(operatorTerm.getOperands().get(0), visitor);
break;
case 2:
visitor.visit("("); //$NON-NLS-1$
traverseRootTerm(operatorTerm.getOperands().get(0), visitor);
visitor.visit(operatorTerm);
traverseRootTerm(operatorTerm.getOperands().get(1), visitor);
visitor.visit(")"); //$NON-NLS-1$
break;
case 3:
visitor.visit("("); //$NON-NLS-1$
traverseRootTerm(operatorTerm.getOperands().get(0), visitor);
String firstPart;
firstPart = operatorTerm.getLocation().getLocations()
.get(0).getContent();
visitor.visit(operatorTerm, firstPart);
traverseRootTerm(operatorTerm.getOperands().get(1), visitor);
String secondPart;
secondPart = operatorTerm.getLocation().getLocations().get(
1).getContent();
visitor.visit(secondPart);
traverseRootTerm(operatorTerm.getOperands().get(2), visitor);
visitor.visit(")"); //$NON-NLS-1$
break;
default:
/*
* XXX for arity 4 and above we don't reorder the condition.
*/
visitor.visit("("); //$NON-NLS-1$
visitor.visit(operatorTerm);
for (BooleanTerm term : operatorTerm.getOperands()) {
traverseRootTerm(term, visitor);
}
visitor.visit(")"); //$NON-NLS-1$
break;
}
}
}
private final void fillTable(final List testCases,
final RootTerm rootTerm) {
if (testCases == null || rootTerm == null || testCases.size() == 0) {
refreshAndPackTable(null);
return;
}
Map assignmentsMap = new HashMap();
// Merge the assignments of all the test cases.
for (TestCase testCase : testCases) {
assignmentsMap.putAll(testCase.getAssignments(rootTerm));
}
final TermCoverage termCoverage = TermCoverage.getInstance();
List rows = new LinkedList();
for (BooleanAssignment assignment : assignmentsMap.keySet()) {
Map cells = new HashMap();
CellObject resultCell;
CellObject testCaseCell;
Map wirksamMapT = new HashMap();
Map wirksamMapF = new HashMap();
Map termResults = new HashMap();
termCoverage.evaluateTermWirksamkeit(rootTerm, rootTerm.getTerm(), assignment, termResults, wirksamMapT, wirksamMapF);
Set allTerms = termResults.keySet();
for(BooleanTerm term : allTerms) {
if(term instanceof BasicBooleanTerm) {
Color coveredColor = null;
if (wirksamMapT.get(term) != null || wirksamMapF.get(term) != null) {
coveredColor = getCoveredBackground();
}
// Store the new CellObject in the cells map for the current
// BooleanTerm.
cells.put(term, new CellObject(
getStringFromBooleanResult(termResults.get(term)), null,
coveredColor));
} else {
// Store the new CellObject in the cells map for the current
// BooleanTerm.
cells.put(term, new CellObject(
getStringFromBooleanResult(termResults.get(term)),
getOperatorForeground(), null));
}
}
// Add result cell:
resultCell = new CellObject(
assignmentsMap.get(assignment) ? "1" : "0", null, null); //$NON-NLS-1$//$NON-NLS-2$
// Add test case cell:
StringBuilder sb = new StringBuilder();
for (TestCase testCase : testCases) {
BooleanAssignmentMap countMap = testCase
.getAssignmentsCount(rootTerm);
long count = countMap.get(assignment);
if (count != 0) {
if (sb.length() != 0) {
sb.append(", "); //$NON-NLS-1$
}
sb.append(testCase.getName());
sb.append(" ("); //$NON-NLS-1$
sb.append(count);
sb.append(")"); //$NON-NLS-1$
}
}
int allTermCoverageCount = rootTerm.getTerm().getBasicBooleanTerms() * 2;
int covered = wirksamMapT.size() + wirksamMapF.size();
float coverage = 0;
if(allTermCoverageCount != 0) {
coverage = covered * 100 / allTermCoverageCount;
}
DecimalFormat df = new DecimalFormat("0.0"); //$NON-NLS-1$
sb.append(" Coverage: " + df.format(coverage));
testCaseCell = new CellObject(sb.toString(), null, null);
rows.add(new RowObject(cells, resultCell, testCaseCell));
}
refreshAndPackTable(rows.toArray());
// update the status bar;
CoverageResult result = termCoverage.getCoverage(testCases, rootTerm);
double coveredItems = result.getCoveredItems();
double totalItems = result.getTotalItems();
double coverage;
if (totalItems == 0.0) {
coverage = 1.0;
} else {
coverage = coveredItems / totalItems;
}
DecimalFormat df = new DecimalFormat("0.0"); //$NON-NLS-1$
this.statusBar.setText("term coverage for all test cases: " + df
.format(100 * coverage) + " %");
}
Map termResults;
/**
* Evaluates the given {@link RootTerm} and its {@link BooleanTerm}s under
* the given assignment, by traversing the expression tree. The cells are
* filled with their data during that traversing.
*
* @param rootTerm
* the {@link RootTerm}, the {@link BooleanTerm} belongs to.
* @param booleanTerm
* the {@link BooleanTerm}, that is currently evaluated.
* @param assignment
* the {@link BooleanAssignment}, that is used to evaluate.
* @param cells
* the {@link Map} of {@link CellObject}s, that is filled.
* @param coveringAssignments
* the {@link Map} of those {@link BooleanAssignment}s, that
* cover a given {@link BasicBooleanTerm}.
* @return The {@link BooleanResult} of the evaluation of the given
* {@link BooleanTerm}.
*/
private final BooleanResult evaluateTerm(RootTerm rootTerm,
BooleanTerm booleanTerm, BooleanAssignment assignment,
Map cells,
Map> coveringAssignments) {
if (booleanTerm instanceof BasicBooleanTerm) {
int position = rootTerm.getPositionOfTerm((BasicBooleanTerm) booleanTerm);
// Get the BooleanResult, that is at the position of the
// BasicBooleanTerm in the given BooleanAssignment.
BooleanResult booleanResult = assignment.getResults().get(position);
Color coveredColor = null;
// Set the background color of the cell to the color for coverage,
// if the BasicBooleanTerm is covered by the given
// BooleanAssignment.
if (coveringAssignments.get(booleanTerm).contains(assignment)) {
coveredColor = getCoveredBackground();
}
// Store the new CellObject in the cells map for the current
// BooleanTerm.
cells.put(booleanTerm, new CellObject(
getStringFromBooleanResult(booleanResult), null,
coveredColor));
termResults.put(booleanTerm, booleanResult);
return booleanResult;
} else if (booleanTerm instanceof OperatorTerm) {
OperatorTerm operatorTerm = (OperatorTerm)booleanTerm;
List operatorResults = new LinkedList();
// Evaluate all the operands of this OperatorTerm and store the
// results in a list.
for (BooleanTerm subTerms : operatorTerm.getOperands()) {
BooleanResult result = evaluateTerm(rootTerm, subTerms, assignment, cells, coveringAssignments);
operatorResults.add(result);
}
// Retrieve the Boolean result produced by the assignment of the
// operands.
BooleanAssignment operatorAssignment = new BooleanAssignment(operatorResults);
Boolean result = ((OperatorTerm) booleanTerm).getOperator()
.getPossibleAssignments().get(operatorAssignment);
// Convert into BooleanResult.
BooleanResult booleanResult;
if (result == null) {
booleanResult = BooleanResult.NOT_EVALUATED;
} else {
booleanResult = result ? BooleanResult.TRUE
: BooleanResult.FALSE;
}
// Store the new CellObject in the cells map for the current
// BooleanTerm.
cells.put(booleanTerm, new CellObject(
getStringFromBooleanResult(booleanResult),
getOperatorForeground(), null));
termResults.put(booleanTerm, booleanResult);
return booleanResult;
}
return BooleanResult.NOT_EVALUATED;
}
private final void evaluateTermWirksamkeit(RootTerm rootTerm,
BooleanTerm booleanTerm, BooleanAssignment assignment,
Map cells) {
}
/**
* Gets the {@link Color}, that is to be used for the text of the operator
* results in the table.
*
* @return the {@link Color} for the text of the operator results.
*/
private final Color getOperatorForeground() {
if (this.tableViewer == null) {
return null;
}
return this.tableViewer.getTable().getDisplay().getSystemColor(
SWT.COLOR_GRAY);
}
/**
* Gets the {@link Color}, that is to be used for the background of the
* cells of covered {@link BasicBooleanTerm}s.
*
* @return the {@link Color} for the covered cells.
*/
private final Color getCoveredBackground() {
if (this.tableViewer == null) {
return null;
}
return this.tableViewer.getTable().getDisplay().getSystemColor(
SWT.COLOR_GREEN);
}
/**
* Gets the string representation of a boolean result.
*
* @param booleanResult
* the {@link BooleanResult} to be converted to a string
* @return the string representation of a {@link BooleanResult}
*/
private final String getStringFromBooleanResult(BooleanResult booleanResult) {
String text;
switch (booleanResult) {
case FALSE:
text = "F"; //$NON-NLS-1$
break;
case TRUE:
text = "T"; //$NON-NLS-1$
break;
case NOT_EVALUATED:
text = "x"; //$NON-NLS-1$
break;
default:
text = ""; //$NON-NLS-1$
}
return text;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
this.tableViewer.getTable().setFocus();
}
/**
* Refreshes the {@link TableViewer} with the given input and packs the
* columns.
*
* @param input
* the new input for the viewer.
*/
private final void refreshAndPackTable(Object input) {
this.tableViewer.setInput(input);
this.tableViewer.refresh();
for (TableColumn column : this.tableViewer.getTable().getColumns()) {
column.pack();
}
}
/**
* Handles the change to a new {@link TestSessionContainer}
*
* @param testSessionContainer
* the new {@link TestSessionContainer}
*/
private final void onTSCChanged(TestSessionContainer testSessionContainer) {
ActiveTSContainerInfo activeTSCInfo = CodeCoverPlugin.getDefault()
.getTSContainerManager().getActiveTSContainer();
fillClassList(testSessionContainer);
fillClassComboBox();
fillConditionList(getSelectedClass());
fillConditionComboBox();
createTableColumns(getSelectedRootTerm());
if (activeTSCInfo != null) {
fillTable(new LinkedList(activeTSCInfo
.getActiveTestCases()), getSelectedRootTerm());
} else {
fillTable(new LinkedList(), getSelectedRootTerm());
}
}
/**
* Handles the change of active status of the {@link TestCase}s in the
* current {@link TestSessionContainer}
*
* @param activeTestCases
* the {@link Set} of active {@link TestCase}s
*/
private final void onActiveTestCasesChanged(Set activeTestCases) {
fillTable(new LinkedList(activeTestCases),
getSelectedRootTerm());
}
/**
* Displays the given {@link RootTerm} in the {@link BooleanAnalyzer}.
* Note: The {@link RootTerm} must be part of the given
* {@link HierarchyLevel}. If it is not, then nothing will be done.
*
* @param classLevel
* the {@link HierarchyLevel} representing the class the
* condition is part of.
* @param rootTerm
* the {@link RootTerm} representing the to be displayed
* condition.
*/
public void displayRootTerm(HierarchyLevel classLevel, RootTerm rootTerm) {
ActiveTSContainerInfo activeTSCInfo = CodeCoverPlugin.getDefault()
.getTSContainerManager().getActiveTSContainer();
if (!this.classList.contains(classLevel)) {
return;
}
// Select the given class in the ComboBox.
this.classCombo.select(this.classList.indexOf(classLevel));
this.fillConditionList(classLevel);
// If the condition was not contained in the given class, we do nothing
// further.
if (!this.conditionList.contains(rootTerm)) {
return;
}
this.conditionCombo.setRedraw(false);
this.fillConditionComboBox();
// If the condition was not contained in the given class, we display the
// default RootTerm.
if (this.conditionList.contains(rootTerm)) {
this.conditionCombo.select(this.conditionList.indexOf(rootTerm));
}
this.conditionCombo.setRedraw(true);
this.tableViewer.getTable().setRedraw(false);
createTableColumns(getSelectedRootTerm());
if (activeTSCInfo != null) {
fillTable(new LinkedList(activeTSCInfo
.getActiveTestCases()), getSelectedRootTerm());
} else {
fillTable(new LinkedList(), getSelectedRootTerm());
}
this.tableViewer.getTable().setRedraw(true);
}
private final class TableContentProvider implements
IStructuredContentProvider {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
// Do nothing here.
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
* java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// Do nothing here.
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return (Object[]) inputElement;
}
}
private final class TableLabelAndColorProvider implements
ITableLabelProvider, ITableColorProvider {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
* int)
*/
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
* int)
*/
public String getColumnText(Object element, int columnIndex) {
TableColumn column = BooleanAnalyzer.this.tableViewer.getTable()
.getColumn(columnIndex);
int columnCount = BooleanAnalyzer.this.tableViewer.getTable()
.getColumnCount();
BooleanTerm booleanTerm = (BooleanTerm) column
.getData(COLUMN_STORE_KEY);
if (columnIndex == columnCount - 2) {
return ((RowObject) element).resultCell.text;
}
if (columnIndex == columnCount - 1) {
return ((RowObject) element).testCaseCell.text;
}
if (booleanTerm == null) {
// Nothing was stored, so this is either a bracket column, or a
// column for other inactive elements.
return ""; //$NON-NLS-1$
}
return ((RowObject) element).cells.get(booleanTerm).text;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void addListener(ILabelProviderListener listener) {
// Do nothing here.
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
*/
public void dispose() {
CodeCoverPlugin.getDefault().setBooleanAnalyzer(null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object,
* java.lang.String)
*/
public boolean isLabelProperty(Object element, String property) {
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void removeListener(ILabelProviderListener listener) {
// Do nothing here.
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableColorProvider#getBackground(java.lang.Object,
* int)
*/
public Color getBackground(Object element, int columnIndex) {
TableColumn column = BooleanAnalyzer.this.tableViewer.getTable()
.getColumn(columnIndex);
int columnCount = BooleanAnalyzer.this.tableViewer.getTable()
.getColumnCount();
BooleanTerm booleanTerm = (BooleanTerm) column
.getData(COLUMN_STORE_KEY);
if (columnIndex == columnCount - 2) {
return ((RowObject) element).resultCell.backgroundColor;
}
if (columnIndex == columnCount - 1) {
return ((RowObject) element).testCaseCell.backgroundColor;
}
if (booleanTerm == null) {
// Nothing was stored, so this is either a bracket column, or a
// column for other inactive elements.
return null;
}
return ((RowObject) element).cells.get(booleanTerm).backgroundColor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableColorProvider#getForeground(java.lang.Object,
* int)
*/
public Color getForeground(Object element, int columnIndex) {
TableColumn column = BooleanAnalyzer.this.tableViewer.getTable()
.getColumn(columnIndex);
int columnCount = BooleanAnalyzer.this.tableViewer.getTable()
.getColumnCount();
BooleanTerm booleanTerm = (BooleanTerm) column
.getData(COLUMN_STORE_KEY);
if (columnIndex == columnCount - 2) {
return ((RowObject) element).resultCell.foregroundColor;
}
if (columnIndex == columnCount - 1) {
return ((RowObject) element).testCaseCell.foregroundColor;
}
if (booleanTerm == null) {
// Nothing was stored, so this is either a bracket column, or a
// column for other inactive elements.
return null;
}
return ((RowObject) element).cells.get(booleanTerm).foregroundColor;
}
}
private final class TSManagerListener implements TSContainerManagerListener {
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testCaseChanged(org.codecover.eclipse.tscmanager.ActiveTSContainerInfo,
* org.codecover.model.utils.ChangeType,
* org.codecover.model.TestCase)
*/
public void testCaseChanged(final ActiveTSContainerInfo tscInfo,
ChangeType changeType, TestCase testCase) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
onActiveTestCasesChanged(tscInfo.getActiveTestCases());
}
});
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testCasesActivated(org.codecover.eclipse.tscmanager.ActiveTSContainerInfo)
*/
public void testCasesActivated(final ActiveTSContainerInfo tscInfo) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
onActiveTestCasesChanged(tscInfo.getActiveTestCases());
}
});
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testSessionChanged(org.codecover.eclipse.tscmanager.ActiveTSContainerInfo,
* org.codecover.model.utils.ChangeType,
* org.codecover.model.TestSession)
*/
public void testSessionChanged(ActiveTSContainerInfo tscInfo,
ChangeType changeType, TestSession testSession) {
// We don't react on this.
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testSessionContainerActivated(org.codecover.eclipse.tscmanager.ActiveTSContainerInfo)
*/
public void testSessionContainerActivated(
final ActiveTSContainerInfo tscInfo) {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
if (tscInfo != null) {
onTSCChanged(tscInfo.getTestSessionContainer());
} else {
onTSCChanged(null);
}
}
});
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testSessionContainerAdded(org.codecover.eclipse.tscmanager.TSContainerInfo,
* int)
*/
public void testSessionContainerAdded(TSContainerInfo tscInfo, int index) {
// We don't react on this.
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testSessionContainerChanged(org.codecover.model.utils.ChangeType,
* org.codecover.eclipse.tscmanager.ActiveTSContainerInfo)
*/
public void testSessionContainerChanged(ChangeType changeType,
ActiveTSContainerInfo tscInfo) {
// We don't react on this.
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#testSessionContainerRemoved(org.codecover.eclipse.tscmanager.TSContainerInfo)
*/
public void testSessionContainerRemoved(TSContainerInfo tscInfo) {
// We don't react on this.
}
/*
* (non-Javadoc)
*
* @see org.codecover.eclipse.tscmanager.TSContainerManagerListener#synchronizedStateChanged(TSContainerInfo, boolean)
*/
public void synchronizedStateChanged(TSContainerInfo tscInfo,
boolean isSynchronized) {
// We don't react on this.
}
}
private interface Visitor {
/**
* Visits a {@link BasicBooleanTerm}
*
* @param booleanTerm
* the visited {@link BasicBooleanTerm}
*/
public void visit(BasicBooleanTerm booleanTerm);
/**
* Visits a {@link OperatorTerm}
*
* @param operatorTerm
* the visited {@link OperatorTerm}
*/
public void visit(OperatorTerm operatorTerm);
/**
* Visits a {@link OperatorTerm} with an given name for the
* {@link OperatorTerm}
*
* @param operatorTerm
* the visited {@link OperatorTerm}
* @param name
* the name of the {@link OperatorTerm}
*/
public void visit(OperatorTerm operatorTerm, String name);
/**
* Visit method, which only gives a name for elements in the expression,
* that is traversed, that do not correspond to either a
* {@link BasicBooleanTerm} or an {@link OperatorTerm}.
*
* @param name
* the name of the element.
*/
public void visit(String name);
}
private final class CellObject {
final String text;
final Color foregroundColor;
final Color backgroundColor;
/**
* Constructor
*
* @param text
* @param foregroundColor
* @param backgroundColor
*/
public CellObject(String text, Color foregroundColor,
Color backgroundColor) {
this.text = text;
this.foregroundColor = foregroundColor;
this.backgroundColor = backgroundColor;
}
}
private final class RowObject {
final Map cells;
final CellObject resultCell;
final CellObject testCaseCell;
/**
* Constructor
*
* @param cells
* @param resultCell
* @param testCaseCell
*/
public RowObject(Map cells,
CellObject resultCell, CellObject testCaseCell) {
this.cells = new HashMap(cells);
this.resultCell = resultCell;
this.testCaseCell = testCaseCell;
}
}
}