/*
* Contributions to FindBugs
* Copyright (C) 2008, Andrei Loskutov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.tobject.findbugs.wizards;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import de.tobject.findbugs.FindbugsPlugin;
import de.tobject.findbugs.preferences.FindBugsConstants;
import de.tobject.findbugs.reporter.MarkerUtil;
import de.tobject.findbugs.util.ProjectUtilities;
import de.tobject.findbugs.view.explorer.FilterBugsDialog;
import edu.umd.cs.findbugs.BugCode;
import edu.umd.cs.findbugs.BugPattern;
/**
* @author Andrei
*/
public class ExportWizardPage extends WizardPage {
private static final String SEPARATOR = ",";
private static final int BY_NAME = 0;
private static final int BY_NOT_FILTERED_COUNT = 1;
private static final int BY_OVERALL_COUNT = 2;
private Composite comp;
private int sortBy;
private Text filteredBugIdsText;
protected ExportWizardPage(String pageName, String title, String descr, String imagePath) {
super(pageName, title, AbstractUIPlugin.imageDescriptorFromPlugin(FindbugsPlugin.getDefault().getBundle()
.getSymbolicName(), imagePath));
setDescription(descr);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
* .Composite)
*/
public void createControl(Composite parent) {
comp = new Composite(parent, SWT.BORDER);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 0;
layout.marginWidth = 0;
comp.setLayout(layout);
GridData gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_HORIZONTAL);
gd.heightHint = 400;
gd.widthHint = 400;
comp.setLayoutData(gd);
setControl(comp);
Label label = new Label(comp, SWT.NONE);
label.setText("Sort by:");
final Combo sortByCombo = new Combo(comp, SWT.READ_ONLY);
final String[] items = new String[] { "Name", "Not filtered bug count", "Overall bug count" };
sortByCombo.setItems(items);
String sortOrder = FindbugsPlugin.getDefault().getPreferenceStore().getString(FindBugsConstants.EXPORT_SORT_ORDER);
if (FindBugsConstants.ORDER_BY_NOT_FILTERED_BUGS_COUNT.equals(sortOrder)) {
sortByCombo.select(1);
} else if (FindBugsConstants.ORDER_BY_OVERALL_BUGS_COUNT.equals(sortOrder)) {
sortByCombo.select(2);
} else {
sortByCombo.select(0);
}
sortBy = sortByCombo.getSelectionIndex();
sortByCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
@Override
public void widgetSelected(SelectionEvent e) {
sortBy = sortByCombo.getSelectionIndex();
}
});
label = new Label(comp, SWT.NONE);
label.setText("Filter bug ids:");
Button button = new Button(comp, SWT.PUSH);
button.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
button.setText("Browse...");
button.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
Set<BugPattern> filtered = FindbugsPlugin.getFilteredPatterns();
Set<BugCode> filteredTypes = FindbugsPlugin.getFilteredPatternTypes();
FilterBugsDialog dialog = new FilterBugsDialog(getShell(), filtered, filteredTypes);
dialog.setTitle("Bug Filter Configuration");
int result = dialog.open();
if (result != Window.OK) {
return;
}
String selectedIds = dialog.getSelectedIds();
FindbugsPlugin.getDefault().getPreferenceStore().setValue(FindBugsConstants.LAST_USED_EXPORT_FILTER, selectedIds);
filteredBugIdsText.setText(selectedIds);
}
});
label = new Label(comp, SWT.NONE);
label.setText("");
filteredBugIdsText = new Text(comp, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP | SWT.READ_ONLY);
GridData layoutData = new GridData(GridData.FILL_BOTH);
layoutData.heightHint = 200;
layoutData.widthHint = 400;
filteredBugIdsText.setLayoutData(layoutData);
filteredBugIdsText.setText(FindbugsPlugin.getDefault().getPreferenceStore()
.getString(FindBugsConstants.LAST_USED_EXPORT_FILTER));
filteredBugIdsText.setToolTipText("Bug ids to filter, separated by comma or space");
}
@Override
public void dispose() {
comp.dispose();
super.dispose();
}
public boolean finish() {
String data = collectBugsData();
copyToClipboard(data);
String filters = FindBugsConstants.encodeIds(getLastUsedExportFilters());
FindbugsPlugin.getDefault().getPreferenceStore().setValue(FindBugsConstants.LAST_USED_EXPORT_FILTER, filters);
String sortPref;
switch (sortBy) {
case BY_NOT_FILTERED_COUNT:
sortPref = FindBugsConstants.ORDER_BY_NOT_FILTERED_BUGS_COUNT;
break;
case BY_OVERALL_COUNT:
sortPref = FindBugsConstants.ORDER_BY_OVERALL_BUGS_COUNT;
break;
case BY_NAME:
default:
sortPref = FindBugsConstants.ORDER_BY_NAME;
break;
}
FindbugsPlugin.getDefault().getPreferenceStore().setValue(FindBugsConstants.EXPORT_SORT_ORDER, sortPref);
return true;
}
private Set<String> getLastUsedExportFilters() {
String text = filteredBugIdsText.getText();
return FindBugsConstants.decodeIds(text);
}
/**
* @return
*/
private String collectBugsData() {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
List<Record> lines = new ArrayList<Record>();
for (IProject project : projects) {
Record line = createProjectLine(project);
if (line != null) {
lines.add(line);
}
}
Collections.sort(lines);
StringBuilder sb = new StringBuilder();
createHeader(sb);
for (Record record : lines) {
sb.append(record);
}
return sb.toString();
}
private Record createProjectLine(IProject project) {
if (ProjectUtilities.isJavaProject(project) /*
* TODO why not working ??
* && project.hasNature(
* FindbugsPlugin.NATURE_ID)
*/) {
IMarker[] markerArr = MarkerUtil.getAllMarkers(project);
if (markerArr.length == 0) {
return null;
}
int overallBugCount = markerArr.length;
int notFilteredBugCount = 0;
Set<String> usedExportFilters = getLastUsedExportFilters();
for (IMarker marker : markerArr) {
if (!MarkerUtil.isFiltered(marker, usedExportFilters)) {
notFilteredBugCount++;
}
}
return new Record(project.getName(), overallBugCount, notFilteredBugCount);
}
return null;
}
protected int getSortBy() {
return sortBy;
}
protected void copyToClipboard(String toolTip) {
Object[] data = new Object[] { toolTip };
Transfer[] transfer = new Transfer[] { TextTransfer.getInstance() };
Clipboard clipboard = new Clipboard(Display.getCurrent());
clipboard.setContents(data, transfer);
clipboard.dispose();
}
private void createHeader(StringBuilder sb) {
switch (sortBy) {
case BY_OVERALL_COUNT:
sb.append("Overall bugs number" + SEPARATOR + " Project name" + SEPARATOR + "Not filtered bugs number\n");
break;
case BY_NOT_FILTERED_COUNT:
sb.append("Not filtered bugs number" + SEPARATOR + "Project name" + SEPARATOR + "Overall bugs number\n");
break;
case BY_NAME:
default:
sb.append("Project name" + SEPARATOR + "Not filtered bugs number" + SEPARATOR + "Overall bugs number\n");
break;
}
}
public class Record implements Comparable<Record> {
private final String name;
private final int overallBugs;
private final int notFilteredBugs;
@Override
public int hashCode() {
int result = ((name == null) ? 0 : name.hashCode());
result += notFilteredBugs;
result += overallBugs;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Record)) {
return false;
}
Record other = (Record) obj;
if (notFilteredBugs != other.notFilteredBugs) {
return false;
}
if (overallBugs != other.overallBugs) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
return true;
}
Record(String name, int overallBugs, int notFilteredBugs) {
this.name = name;
this.overallBugs = overallBugs;
this.notFilteredBugs = notFilteredBugs;
}
public int compareTo(Record other) {
int result;
switch (sortBy) {
case BY_OVERALL_COUNT:
result = other.overallBugs - overallBugs;
if (result == 0) {
return name.compareTo(other.name);
}
return result;
case BY_NOT_FILTERED_COUNT:
result = other.notFilteredBugs - notFilteredBugs;
if (result == 0) {
return name.compareTo(other.name);
}
return result;
case BY_NAME:
default:
// name can't be the same, so additional sorting is not needed
return name.compareTo(other.name);
}
}
@Override
public String toString() {
switch (sortBy) {
case BY_OVERALL_COUNT:
return overallBugs + SEPARATOR + name + SEPARATOR + notFilteredBugs + "\n";
case BY_NOT_FILTERED_COUNT:
return notFilteredBugs + SEPARATOR + name + SEPARATOR + overallBugs + "\n";
case BY_NAME:
default:
return name + SEPARATOR + notFilteredBugs + SEPARATOR + overallBugs + "\n";
}
}
}
}