/*******************************************************************************
* Copyright (c) 2004, 2007 Boeing.
* 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
*
* Contributors:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.nebula.widgets.xviewer;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.nebula.widgets.xviewer.core.model.ColumnDateFilter;
import org.eclipse.nebula.widgets.xviewer.core.model.DateRangeType;
import org.eclipse.nebula.widgets.xviewer.core.model.XViewerColumn;
import org.eclipse.nebula.widgets.xviewer.core.util.Strings;
/**
* @author Donald G. Dunne
*/
public class XViewerTextFilter extends ViewerFilter {
protected final XViewer xViewer;
protected Pattern textPattern;
protected Matcher matcher;
protected final Map<String, Pattern> colIdToPattern = new HashMap<String, Pattern>();
protected final Map<String, ColumnDateFilter> colIdToDateFilter = new HashMap<String, ColumnDateFilter>();
protected static final Pattern EMPTY_STR_PATTERN = Pattern.compile("");
protected static final Pattern NOT_EMPTY_STR_PATTERN = Pattern.compile("^.+$");
private final Set<Object> parentMatches = new HashSet<Object>();
public XViewerTextFilter(XViewer xViewer) {
this.xViewer = xViewer;
}
/**
* Setup all patterns for text and column text filters
*/
public void update() {
parentMatches.clear();
// Update text filter pattern
if (!Strings.isValid(xViewer.getCustomizeMgr().getFilterText())) {
textPattern = null;
} else {
int flags = Pattern.CASE_INSENSITIVE;
if (!xViewer.getCustomizeMgr().isFilterTextRegularExpression()) {
flags = Pattern.LITERAL | flags;
}
textPattern = Pattern.compile(xViewer.getCustomizeMgr().getFilterText(), flags);
}
// Update column filter patterns
colIdToPattern.clear();
colIdToDateFilter.clear();
for (String colId : xViewer.getCustomizeMgr().getColumnFilterData().getColIds()) {
String colFilterText = xViewer.getCustomizeMgr().getColumnFilterText(colId);
if (colFilterText != null) {
boolean isNot = colFilterText.startsWith("!");
if (isNot) {
colFilterText = colFilterText.replaceFirst("^!", "");
}
// Handle != case ^(.(?<!big))*$
if (isNot) {
if (colFilterText.equals("")) {
colIdToPattern.put(colId, NOT_EMPTY_STR_PATTERN);
} else {
colIdToPattern.put(colId,
Pattern.compile("^(.(?<!" + colFilterText + "))*$", Pattern.CASE_INSENSITIVE));
}
}
// Handle normal case
else {
if (colFilterText.equals("")) {
colIdToPattern.put(colId, EMPTY_STR_PATTERN);
} else {
colIdToPattern.put(colId, Pattern.compile(
xViewer.getCustomizeMgr().getColumnFilterData().getFilterText(colId), Pattern.CASE_INSENSITIVE));
}
}
}
ColumnDateFilter dateFilter = xViewer.getCustomizeMgr().getColumnDateFilter(colId);
if (dateFilter != null) {
colIdToDateFilter.put(colId, dateFilter);
}
}
}
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (textPattern == null && colIdToPattern.isEmpty() && colIdToDateFilter.isEmpty()) {
return true;
}
// If element matches, it's parent is added to this collection; it should always match so get full path shown
if (parentMatches.contains(element)) {
if (parentElement != null) {
parentMatches.add(parentElement);
}
return true;
}
boolean match = true;
// Must match all column filters or don't show
Set<String> colIds = xViewer.getCustomizeMgr().getColumnFilterData().getColIds();
for (String filteredColId : colIds) {
XViewerColumn xCol = xViewer.getCustomizeMgr().getCurrentTableColumn(filteredColId);
if (xCol.isShow()) {
if (colIdToPattern.keySet().contains(xCol.getId())) {
String cellStr =
xViewer.getColumnText(element, xViewer.getCustomizeMgr().getColumnNumFromXViewerColumn(xCol));
if (cellStr != null) {
matcher = colIdToPattern.get(xCol.getId()).matcher(cellStr);
if (!matcher.find()) {
return false;
}
}
}
if (colIdToDateFilter.containsKey(xCol.getId())) {
String cellStr =
xViewer.getColumnText(element, xViewer.getCustomizeMgr().getColumnNumFromXViewerColumn(xCol));
if (Strings.isValid(cellStr)) {
Date cellDate = XViewerSorter.parseDatePair(cellStr, "").getFirst();
if (cellDate != null) {
ColumnDateFilter columnDateFilter = colIdToDateFilter.get(xCol.getId());
Calendar cellCal = Calendar.getInstance();
cellCal.setTime(cellDate);
Calendar filterCal = Calendar.getInstance();
Date filterDate1 = columnDateFilter.getDate1();
filterCal.setTime(filterDate1);
DateRangeType rangeType = columnDateFilter.getType();
if (rangeType == DateRangeType.Equals_Date) {
if (cellCal.get(Calendar.YEAR) != filterCal.get(Calendar.YEAR) || cellCal.get(
Calendar.MONTH) != filterCal.get(Calendar.MONTH) || cellCal.get(
Calendar.DAY_OF_MONTH) != filterCal.get(Calendar.DAY_OF_MONTH)) {
return false;
}
} else if (rangeType == DateRangeType.After_Date && cellDate.before(filterDate1)) {
return false;
} else if (rangeType == DateRangeType.Before_Date && cellDate.after(filterDate1)) {
return false;
} else if (rangeType == DateRangeType.Between_Dates) {
if (cellDate.before(filterDate1)) {
return false;
}
Date filterDate2 = columnDateFilter.getDate2();
if (cellDate.after(filterDate2)) {
return false;
}
}
}
} else {
// Do not show this row if date filter selected and no date is shown
return false;
}
}
}
}
if (!match) {
return false;
}
// Must match at least one column for filter text
if (textPattern == null) {
if (match && parentElement != null) {
parentMatches.add(parentElement);
}
return match;
}
if (textPattern != null) {
for (XViewerColumn xCol : xViewer.getCustomizeMgr().getCurrentTableColumns()) {
if (xCol.isShow()) {
// Check text filter
String cellStr =
xViewer.getColumnText(element, xViewer.getCustomizeMgr().getColumnNumFromXViewerColumn(xCol));
if (cellStr != null) {
matcher = textPattern.matcher(cellStr);
if (matcher.find()) {
if (parentElement != null) {
parentMatches.add(parentElement);
}
return true;
}
}
}
}
}
return false;
}
}