Merge remote-tracking branch

'origin/GP-2582-dragonmacher-table-column-regex-filter' into patch
(Closes #4608)
This commit is contained in:
Ryan Kurtz 2022-09-21 11:54:10 -04:00
commit 0d5ff7628f
7 changed files with 102 additions and 5 deletions

View file

@ -19,6 +19,7 @@ import java.util.List;
import java.util.Objects;
import docking.widgets.table.constraint.provider.NumberColumnConstraintProvider;
import generic.json.Json;
import ghidra.util.classfinder.ExtensionPoint;
import utilities.util.reflection.ReflectionUtilities;
@ -59,6 +60,11 @@ public abstract class ColumnTypeMapper<T, M> implements ExtensionPoint {
this.destinationType = destinationType;
}
@Override
public String toString() {
return Json.toString(this);
}
@Override
public int hashCode() {
return Objects.hash(sourceType, destinationType);

View file

@ -17,12 +17,13 @@ package docking.widgets.table.constraint;
import docking.widgets.table.constrainteditor.ColumnConstraintEditor;
import docking.widgets.table.constrainteditor.MappedColumnConstraintEditor;
import generic.json.Json;
import ghidra.util.SystemUtilities;
/**
* Class that maps one type of column constraint into another. Typically, these are created
* automatically based on {@link ColumnTypeMapper} that are discovered by the system. For example,
* {@literal if you have a column type of "Foo", and you create a ColumnTypeMapper<Foo, String>,
* {@literal if you have a column type of "Foo", and you create a ColumnTypeMapper<Foo, String>,
* then all the} string constraints would now be available that column.
*
* @param <T> The column type
@ -100,6 +101,11 @@ public class MappedColumnConstraint<T, M> implements ColumnConstraint<T> {
return delegate;
}
@Override
public String toString() {
return Json.toString(this);
}
@Override
public int hashCode() {
final int prime = 31;

View file

@ -125,6 +125,11 @@ public abstract class StringColumnConstraint implements ColumnConstraint<String>
return copy(newValue);
}
@Override
public String toString() {
return getName();
}
@Override
public int hashCode() {
return Objects.hash(this.getClass(), getPatternString());

View file

@ -21,7 +21,7 @@ import java.util.regex.PatternSyntaxException;
/**
* String column constraint for matching column values if they match a full regular expression pattern.
*/
public class StringMatcherColumnConstraint extends StringColumnConstraint {
public class StringMatchesColumnConstraint extends StringColumnConstraint {
/**
* Constructor
*
@ -30,7 +30,7 @@ public class StringMatcherColumnConstraint extends StringColumnConstraint {
*
* @param spec the string to use to create a "matcher" pattern.
*/
public StringMatcherColumnConstraint(String spec) {
public StringMatchesColumnConstraint(String spec) {
super(spec, "Please enter a regular expression.");
}
@ -41,7 +41,7 @@ public class StringMatcherColumnConstraint extends StringColumnConstraint {
@Override
public ColumnConstraint<String> copy(String newPatternString) {
return new StringMatcherColumnConstraint(newPatternString);
return new StringMatchesColumnConstraint(newPatternString);
}
@Override

View file

@ -0,0 +1,58 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docking.widgets.table.constraint;
/**
* String column constraint for matching column values if they do not match a full regular
* expression pattern.
*/
public class StringNotMatchesColumnConstraint extends StringMatchesColumnConstraint {
/**
* Constructor
*
* <P> This class is for users to enter true regular expression which is why it creates
* a pattern directly without using the UserSearchUtils
*
* @param spec the string to use to create a "matcher" pattern.
*/
public StringNotMatchesColumnConstraint(String spec) {
super(spec);
}
@Override
public String getName() {
return "Does Not Match Regex";
}
@Override
public String getGroup() {
return "z string";
}
@Override
public ColumnConstraint<String> copy(String newPatternString) {
return new StringNotMatchesColumnConstraint(newPatternString);
}
@Override
public boolean accepts(String value, TableFilterContext context) {
if (value == null) {
return false;
}
return !matchesPattern.matcher(value).matches();
}
}

View file

@ -31,7 +31,8 @@ public class StringColumnConstraintProvider implements ColumnConstraintProvider
list.add(new StringContainsColumnConstraint(""));
list.add(new StringStartsWithColumnConstraint(""));
list.add(new StringMatcherColumnConstraint(""));
list.add(new StringMatchesColumnConstraint(""));
list.add(new StringNotMatchesColumnConstraint(""));
list.add(new StringNotContainsColumnConstraint(""));
list.add(new StringNotStartsWithColumnConstraint(""));

View file

@ -171,6 +171,27 @@ public class ColumnTableFilterTest {
assertEquals("Ellen", tableModel.getValueAt(1, col));
}
@Test
public void testStringNotMatchesColumnFilter() {
addFirstFilter("Name", "Does Not Match Regex", ".*l.*e.*");
applyFilter();
//
// Data: "Alice", "Bob", "Chuck", "Dave", "Ellen", "Frank"
//
// The regex matches Alice and Ellen, but it is then negated
//
assertEquals(4, tableModel.getRowCount());
// does not match: Alice and Ellen
int col = getColumn("Name");
assertEquals("Bob", tableModel.getValueAt(0, col));
assertEquals("Chuck", tableModel.getValueAt(1, col));
assertEquals("Dave", tableModel.getValueAt(2, col));
assertEquals("Frank", tableModel.getValueAt(3, col));
}
@Test
public void testStringNotContainsColumnFilter() {
addFirstFilter("Name", "Does Not Contain", "l");