mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-08 03:30:16 +00:00
GP-2797 - Fixed the table column filtering to correctly match input data containing newline characters when using the 'Contains' string column filter.
This commit is contained in:
parent
a3c72f3859
commit
65142e127d
@ -293,7 +293,7 @@
|
||||
</CENTER><BR>
|
||||
|
||||
|
||||
<P>The <IMG alt="" src="images/view-filter.png"> button in lower right corner will bring up
|
||||
<P>The <IMG alt="" src="images/filter_off.png"> button in lower right corner will bring up
|
||||
the Column Filter Dialog.</P>
|
||||
<BR>
|
||||
<BR>
|
||||
|
@ -77,7 +77,7 @@ public abstract class StringColumnConstraint implements ColumnConstraint<String>
|
||||
protected Pattern generateFindsPattern() {
|
||||
String regexString = UserSearchUtils.createPatternString(patternString, true);
|
||||
return Pattern.compile("(" + regexString + ")",
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,6 @@ public class StringContainsColumnConstraint extends StringColumnConstraint {
|
||||
@Override
|
||||
protected Pattern generateMatchesPattern(String patternString) {
|
||||
return UserSearchUtils.createContainsPattern(patternString.trim(), true,
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,6 @@ public class StringEndsWithColumnConstraint extends StringColumnConstraint {
|
||||
@Override
|
||||
protected Pattern generateMatchesPattern(String patternString) {
|
||||
return UserSearchUtils.createEndsWithPattern(patternString, true,
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL);
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ package docking.widgets.table.constraint;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import ghidra.util.UserSearchUtils;
|
||||
|
||||
/**
|
||||
* String column constraint for matching column values if they match a full regular expression pattern.
|
||||
*/
|
||||
@ -26,7 +28,7 @@ public class StringMatchesColumnConstraint extends StringColumnConstraint {
|
||||
* Constructor
|
||||
*
|
||||
* <P> This class is for users to enter true regular expression which is why it creates
|
||||
* a pattern directly without using the UserSearchUtils
|
||||
* a pattern directly without using the {@link UserSearchUtils}.
|
||||
*
|
||||
* @param spec the string to use to create a "matcher" pattern.
|
||||
*/
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package docking.widgets.table.constraint;
|
||||
|
||||
import ghidra.util.UserSearchUtils;
|
||||
|
||||
/**
|
||||
* String column constraint for matching column values if they do not match a full regular
|
||||
* expression pattern.
|
||||
@ -25,7 +27,7 @@ public class StringNotMatchesColumnConstraint extends StringMatchesColumnConstra
|
||||
* Constructor
|
||||
*
|
||||
* <P> This class is for users to enter true regular expression which is why it creates
|
||||
* a pattern directly without using the UserSearchUtils
|
||||
* a pattern directly without using the {@link UserSearchUtils}
|
||||
*
|
||||
* @param spec the string to use to create a "matcher" pattern.
|
||||
*/
|
||||
|
@ -46,6 +46,6 @@ public class StringStartsWithColumnConstraint extends StringColumnConstraint {
|
||||
@Override
|
||||
protected Pattern generateMatchesPattern(String patternString) {
|
||||
return UserSearchUtils.createStartsWithPattern(patternString, true,
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE | Pattern.DOTALL);
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +227,6 @@ public class AutocompletingStringConstraintEditor extends DataLoadingConstraintE
|
||||
matcher.appendReplacement(sb, replacement);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,8 @@ import static org.junit.Assert.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.table.TableColumn;
|
||||
|
||||
@ -29,14 +29,9 @@ import org.junit.Test;
|
||||
|
||||
import docking.test.AbstractDockingTest;
|
||||
import docking.widgets.table.*;
|
||||
import docking.widgets.table.constraint.ColumnConstraint;
|
||||
import docking.widgets.table.constraint.MappedColumnConstraint;
|
||||
import docking.widgets.table.constraint.dialog.*;
|
||||
import docking.widgets.table.constraint.provider.*;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.classfinder.ClassSearcher;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
@ -85,6 +80,18 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
return new TableModelWrapper<>(testTableModel);
|
||||
}
|
||||
|
||||
private RowObjectFilterModel<Integer> createTableModelWithNewlines() {
|
||||
TestTableModel testTableModel = new TestTableModel();
|
||||
|
||||
testTableModel.addColumn("Name",
|
||||
new String[] { "Hello World\n", "\nHello World", "Hello\nWorld", "Hello World" });
|
||||
|
||||
testTableModel.addColumn("Long ID",
|
||||
new Long[] { 1000l, 2000l, 3000l });
|
||||
|
||||
return new TableModelWrapper<>(testTableModel);
|
||||
}
|
||||
|
||||
private Date date(String dateString) {
|
||||
try {
|
||||
return DATE_FORMAT.parse(dateString);
|
||||
@ -107,6 +114,27 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
assertEquals("Chuck", tableModel.getValueAt(0, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringStartsWithColumnFilter_WithNewline() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Starts With", "Hello");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(3, tableModel.getRowCount());
|
||||
|
||||
int col = getColumn("Name");
|
||||
assertEquals("Hello World\n", tableModel.getValueAt(0, col));
|
||||
assertEquals("Hello\nWorld", tableModel.getValueAt(1, col));
|
||||
assertEquals("Hello World", tableModel.getValueAt(2, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringDoesNotStartsWithColumnFilter() {
|
||||
addFirstFilter("Name", "Does Not Start With", "C");
|
||||
@ -136,6 +164,27 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
assertEquals("Dave", tableModel.getValueAt(1, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringEndsWithColumnFilter_WithNewline() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Ends With", "World");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(3, tableModel.getRowCount());
|
||||
|
||||
int col = getColumn("Name");
|
||||
assertEquals("\nHello World", tableModel.getValueAt(0, col));
|
||||
assertEquals("Hello\nWorld", tableModel.getValueAt(1, col));
|
||||
assertEquals("Hello World", tableModel.getValueAt(2, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringContainsColumnFilter() {
|
||||
addFirstFilter("Name", "Contains", "l");
|
||||
@ -149,6 +198,44 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
assertEquals("Ellen", tableModel.getValueAt(1, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringContainsColumnFilter_WithNewline() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Contains", "Hello");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(4, tableModel.getRowCount());
|
||||
|
||||
int col = getColumn("Name");
|
||||
assertEquals("Hello World\n", tableModel.getValueAt(0, col));
|
||||
assertEquals("\nHello World", tableModel.getValueAt(1, col));
|
||||
assertEquals("Hello\nWorld", tableModel.getValueAt(2, col));
|
||||
assertEquals("Hello World", tableModel.getValueAt(3, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringNotContainsColumnFilter_WithNewline() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Does Not Contain", "Hello");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(0, tableModel.getRowCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMatchesColumnFilter() {
|
||||
addFirstFilter("Name", "Matches Regex", ".*l.*e.*");
|
||||
@ -162,6 +249,49 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
assertEquals("Ellen", tableModel.getValueAt(1, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMatchesColumnFilter_WithNewline() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Matches Regex", ".*Hello\\sWorld.*");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(2, tableModel.getRowCount());
|
||||
|
||||
// only matches when newline not at the beginning or end, since DOTALL mode is not used
|
||||
int col = getColumn("Name");
|
||||
assertEquals("Hello\nWorld", tableModel.getValueAt(0, col));
|
||||
assertEquals("Hello World", tableModel.getValueAt(1, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMatchesColumnFilter_WithNewline_WithDotallMode() {
|
||||
|
||||
runSwing(() -> gTable.dispose());
|
||||
|
||||
tableModel = createTableModelWithNewlines();
|
||||
gTable = new GTable(tableModel);
|
||||
filterModel = new ColumnFilterDialogModel<>(tableModel, gTable.getColumnModel(), null);
|
||||
|
||||
addFirstFilter("Name", "Matches Regex", "(?s).*Hello\\sWorld.*");
|
||||
|
||||
applyFilter();
|
||||
|
||||
assertEquals(4, tableModel.getRowCount());
|
||||
|
||||
int col = getColumn("Name");
|
||||
assertEquals("Hello World\n", tableModel.getValueAt(0, col));
|
||||
assertEquals("\nHello World", tableModel.getValueAt(1, col));
|
||||
assertEquals("Hello\nWorld", tableModel.getValueAt(2, col));
|
||||
assertEquals("Hello World", tableModel.getValueAt(3, col));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringNotMatchesColumnFilter() {
|
||||
addFirstFilter("Name", "Does Not Match Regex", ".*l.*e.*");
|
||||
@ -683,20 +813,6 @@ public class ColumnTableFilterTest extends AbstractDockingTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<ColumnConstraint<?>> loadConstraints() {
|
||||
List<ColumnConstraint<?>> list = new ArrayList<>();
|
||||
list.addAll(new NumberColumnConstraintProvider().getColumnConstraints());
|
||||
list.addAll(new StringColumnConstraintProvider().getColumnConstraints());
|
||||
Collection<ColumnConstraint<?>> columnConstraints =
|
||||
new DateColumnConstraintProvider().getColumnConstraints();
|
||||
for (ColumnConstraint<?> c : columnConstraints) {
|
||||
list.add(new MappedColumnConstraint<>(new DateColumnTypeMapper(),
|
||||
(ColumnConstraint<LocalDate>) c));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void addConstraints(String columnName, String[] constraintNames,
|
||||
String[] constraintValues, boolean first) {
|
||||
|
||||
|
@ -112,7 +112,7 @@ class TestTableModel implements RowObjectTableModel<Integer> {
|
||||
@Override
|
||||
public List<Integer> getModelData() {
|
||||
List<Integer> rowObjects = new ArrayList<>();
|
||||
for (int i = 0; i < getColumnCount(); i++) {
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
rowObjects.add(i);
|
||||
}
|
||||
return rowObjects;
|
||||
|
Loading…
Reference in New Issue
Block a user