Skip to content

Commit

Permalink
Merge pull request #32 from Florian-W/master
Browse files Browse the repository at this point in the history
Implemented Issue #5 - filter root cases
  • Loading branch information
nbrass committed Dec 7, 2015
2 parents 7e8f880 + 71c2380 commit ace0a01
Show file tree
Hide file tree
Showing 6 changed files with 703 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package de.ibm.issw.requestmetrics.engine.filter;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.RowFilter.ComparisonType;
import javax.swing.table.TableRowSorter;

import de.ibm.issw.requestmetrics.gui.CheckComboBox;
import de.ibm.issw.requestmetrics.gui.UsecaseTableModel;

public class RootCaseFilter{

private RowFilter<UsecaseTableModel, Object> elapsedTimeRowFilter;
private RowFilter<UsecaseTableModel, Object> detailFilter;
private RowFilter<UsecaseTableModel, Object> dateTimeStartFilter;
private RowFilter<UsecaseTableModel, Object> dateTimeEndFilter;
private RowFilter<UsecaseTableModel, Object> typeFilter;
private List<RowFilter<UsecaseTableModel, Object>> filters = new ArrayList<RowFilter<UsecaseTableModel, Object>>();
private JTable rootCaseTable;

private final int TIMESTAMP_COLUMN = 1;
private final int ELAPSED_TIME_COLUMN = 2;
private final int TYPE_COLUMN = 3;
private final int DETAIL_COLUMN = 5;

public RootCaseFilter(JTable rootCaseTable) {
this.rootCaseTable = rootCaseTable;
}

/**
* uses a numberfilter in the elapsed time column. whenever the input
* changes, the old filter is removed to ensure that filter is only
* applied for the current input
* @param userInput
*/
public void filterElapsedTime(final Object userInput) {
//
if (elapsedTimeRowFilter != null && filters.contains(elapsedTimeRowFilter))
filters.remove(elapsedTimeRowFilter);
elapsedTimeRowFilter = new RowFilter<UsecaseTableModel, Object>() {

//
@Override
public boolean include(javax.swing.RowFilter.Entry<? extends UsecaseTableModel, ? extends Object> entry) {
if (rootCaseTable != null){
Long elapsedTime = (Long) rootCaseTable.getModel().getValueAt((int) entry.getIdentifier(), ELAPSED_TIME_COLUMN);
if (userInput == null || elapsedTime >= (Long) userInput)
return true;
else
return false;
}
else {
return false;
}
}
};
if (elapsedTimeRowFilter != null) {
filters.add(elapsedTimeRowFilter);
}
buildCompoundFilter();
}

/**
* uses a regex filter in the detail column. whenever the input changes,
* the old filter is removed to ensure that filter is only applied for
* the current input
* @param userInput the input we want to filter for
*/
public void filterDetails(final String userInput) {
if (detailFilter != null && filters.contains(detailFilter))
filters.remove(detailFilter);

try {
detailFilter = RowFilter.regexFilter(userInput, DETAIL_COLUMN);
} catch (Exception e) {
//TODO: define exception handling
}

if (detailFilter != null)
filters.add(detailFilter);
buildCompoundFilter();
}

/**
*
* @param startDate
*/
public void filterStartDate(final Date startDate) {
if (dateTimeStartFilter != null && filters.contains(dateTimeStartFilter))
filters.remove(dateTimeStartFilter);

dateTimeStartFilter = RowFilter.dateFilter(ComparisonType.AFTER, startDate, TIMESTAMP_COLUMN);

if (dateTimeStartFilter != null)
filters.add(dateTimeStartFilter);
buildCompoundFilter();
}

/**
* uses a date filter in the timestamp column. whenever the input changes,
* the old filter is removed to ensure that filter is only applied for
* the current input
* @param endDate
*/
public void filterEndDate(final Date endDate) {
if (dateTimeEndFilter != null && filters.contains(dateTimeEndFilter))
filters.remove(dateTimeEndFilter);

dateTimeEndFilter = RowFilter.dateFilter(ComparisonType.BEFORE, endDate, TIMESTAMP_COLUMN);

if (dateTimeEndFilter != null)
filters.add(dateTimeEndFilter);
buildCompoundFilter();
}

/**
* uses a date filter in the timestamp column. whenever the input changes,
* the old filter is removed to ensure that filter is only applied for
* the current input
* @param comboBox
*/
public void filterType(CheckComboBox comboBox) {
if (typeFilter != null && filters.contains(typeFilter))
filters.remove(typeFilter);

List<RowFilter<UsecaseTableModel, Object>> typeFilterList = new ArrayList<RowFilter<UsecaseTableModel, Object>>();
if (comboBox.getSelectedItems() != null) {
for (Object type : comboBox.getSelectedItems()) {
RowFilter<UsecaseTableModel, Object> rowFilter = RowFilter.regexFilter(type.toString(), TYPE_COLUMN);
typeFilterList.add(rowFilter);
}
typeFilter = RowFilter.orFilter(typeFilterList);
filters.add(typeFilter);
} else {
filters.remove(typeFilter);
}

buildCompoundFilter();
}

/**
* clears the all filters and thereby ensures that the table is unfiltered
* (i.e. all table entries are displayed again)
*/
public void clearFilters() {
filters.clear();

if (rootCaseTable != null) {
TableRowSorter<UsecaseTableModel> sorter = new TableRowSorter<UsecaseTableModel>((UsecaseTableModel) rootCaseTable.getModel());
rootCaseTable.setRowSorter(sorter);
sorter.setRowFilter(null);
}
}

/**
* applies all the different filters on the table by using an "andFilter"
* thereby ensures that different filters can be applied at the same time
*/
private void buildCompoundFilter() {
RowFilter<UsecaseTableModel, Object> compoundFilter = RowFilter.andFilter(filters);

TableRowSorter<UsecaseTableModel> sorter = new TableRowSorter<UsecaseTableModel>((UsecaseTableModel) rootCaseTable.getModel());
rootCaseTable.setRowSorter(sorter);
sorter.setRowFilter(compoundFilter);
}
}
211 changes: 211 additions & 0 deletions src/main/java/de/ibm/issw/requestmetrics/gui/CheckComboBox.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package de.ibm.issw.requestmetrics.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.EventListener;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import javax.swing.DefaultListCellRenderer;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;

@SuppressWarnings({ "serial", "rawtypes", "unchecked" })
public class CheckComboBox extends JComboBox {
private List<CheckBoxObject> checkBoxesList;
private Map<Object, Boolean> mapCheckBoxObjectsSelected;
private List<CheckComboBoxSelectionChangedListener> changedListeners = new Vector();

private Object nullObject = new Object();

public CheckComboBox(final Set objects) {
resetCheckBoxes(objects, false);
}

public void addSelectionChangedListener(CheckComboBoxSelectionChangedListener listener) {
if (listener == null) {
return;
}
changedListeners.add(listener);
}

public void resetCheckBoxes(final Set objects, boolean selected) {
mapCheckBoxObjectsSelected = new LinkedHashMap();
for (Object object : objects) {
mapCheckBoxObjectsSelected.put(object, selected);
}

reset();
}

public Object[] getSelectedItems() {
Set selectedItemsSet = new TreeSet(); // alphabetically
for (Map.Entry<Object, Boolean> entry : mapCheckBoxObjectsSelected.entrySet()) {
Object object = entry.getKey();
Boolean selected = entry.getValue();

if (selected) {
selectedItemsSet.add(object);
}
}

if (selectedItemsSet.isEmpty())
return null;

return selectedItemsSet.toArray(new Object[selectedItemsSet.size()]);
}

public void reset() {
this.removeAllItems();

initCheckBoxes();

this.addItem(new String());
for (JCheckBox checkBox : checkBoxesList) {
this.addItem(checkBox);
}

setRenderer(new CheckBoxRenderer(checkBoxesList));
addActionListener(this);
}

private void initCheckBoxes() {
checkBoxesList = new Vector<CheckBoxObject>();

boolean selectedNone = false;

CheckBoxObject checkBox;
for (Map.Entry<Object, Boolean> entry : mapCheckBoxObjectsSelected.entrySet()) {
Object object = entry.getKey();
Boolean selected = entry.getValue();

if (selected)
selectedNone = false;

checkBox = new CheckBoxObject(object);
checkBox.setSelected(selected);
checkBoxesList.add(checkBox);
}

checkBox = new CheckBoxObject("Clear Type Filters");
checkBox.setSelected(selectedNone);
checkBoxesList.add(checkBox);
}

private void checkBoxSelectionChanged(int index) {
int n = checkBoxesList.size();
if (index < 0 || index >= n)
return;

if (index < n - 1) {
CheckBoxObject checkBox = checkBoxesList.get(index);
if (checkBox.getObject() == nullObject) {
return;
}

if (checkBox.isSelected()) {
checkBox.setSelected(false);
mapCheckBoxObjectsSelected.put(checkBox.getObject(), false);

checkBoxesList.get(n - 1).setSelected(getSelectedItems() == null); // select
// none
} else {
checkBox.setSelected(true);
mapCheckBoxObjectsSelected.put(checkBox.getObject(), true);

checkBoxesList.get(n - 1).setSelected(false); // select none
}
} else if (index == n - 1){
for (Object object : mapCheckBoxObjectsSelected.keySet()) {
mapCheckBoxObjectsSelected.put(object, false);
}

for (int i = 0; i < n - 1; i++) {
checkBoxesList.get(i).setSelected(false);
}
checkBoxesList.get(n - 1).setSelected(true);
}
}

@Override
public void actionPerformed(ActionEvent e) {
int selection = getSelectedIndex();

if (selection == 0) {
getUI().setPopupVisible(this, true);
} else if (selection > 0) {
checkBoxSelectionChanged(selection - 1);
for (CheckComboBoxSelectionChangedListener l : changedListeners) {
l.selectionChanged();
}
}

this.setSelectedIndex(-1); // clear selection
}

// checkbox renderer for combobox
class CheckBoxRenderer implements ListCellRenderer {
private final DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
private JSeparator separator;
private final List<CheckBoxObject> checkBoxes;

public CheckBoxRenderer(final List<CheckBoxObject> checkBoxes) {
this.checkBoxes = checkBoxes;
separator = new JSeparator(JSeparator.HORIZONTAL);
}

// @Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (index > 0 && index <= checkBoxes.size()) {
CheckBoxObject checkBox = checkBoxes.get(index - 1);
if (checkBox.getObject() == nullObject) {
return separator;
}

checkBox.setBackground(isSelected ? Color.blue : Color.white);
checkBox.setForeground(isSelected ? Color.white : Color.black);

return checkBox;
}

String string;
Object[] objects = getSelectedItems();
Vector<String> strings = new Vector();
if (objects == null) {
string = "Please select one or more ID types";
} else {
for (Object object : objects) {
strings.add(object.toString());
}
string = strings.toString();
}
return defaultRenderer.getListCellRendererComponent(list, string, index, isSelected, cellHasFocus);
}
}

class CheckBoxObject extends JCheckBox {
private final Object object;

public CheckBoxObject(final Object obj) {
super(obj.toString());
this.object = obj;
}

public Object getObject() {
return object;
}
}
}

interface CheckComboBoxSelectionChangedListener extends EventListener {
public void selectionChanged();
}
Loading

0 comments on commit ace0a01

Please sign in to comment.