diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java index 7f7101ed98..f3377deb18 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/ColumnTypeMapper.java @@ -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 implements ExtensionPoint { this.destinationType = destinationType; } + @Override + public String toString() { + return Json.toString(this); + } + @Override public int hashCode() { return Objects.hash(sourceType, destinationType); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java index 5467ea784a..1d8c899464 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/MappedColumnConstraint.java @@ -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, + * {@literal if you have a column type of "Foo", and you create a ColumnTypeMapper, * then all the} string constraints would now be available that column. * * @param The column type @@ -100,6 +101,11 @@ public class MappedColumnConstraint implements ColumnConstraint { return delegate; } + @Override + public String toString() { + return Json.toString(this); + } + @Override public int hashCode() { final int prime = 31; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringColumnConstraint.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringColumnConstraint.java index 3a9d4f518c..6e39d79169 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringColumnConstraint.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringColumnConstraint.java @@ -125,6 +125,11 @@ public abstract class StringColumnConstraint implements ColumnConstraint return copy(newValue); } + @Override + public String toString() { + return getName(); + } + @Override public int hashCode() { return Objects.hash(this.getClass(), getPatternString()); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatcherColumnConstraint.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatchesColumnConstraint.java similarity index 90% rename from Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatcherColumnConstraint.java rename to Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatchesColumnConstraint.java index a88a12f8ef..aa4d04ea85 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatcherColumnConstraint.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringMatchesColumnConstraint.java @@ -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 copy(String newPatternString) { - return new StringMatcherColumnConstraint(newPatternString); + return new StringMatchesColumnConstraint(newPatternString); } @Override diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringNotMatchesColumnConstraint.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringNotMatchesColumnConstraint.java new file mode 100644 index 0000000000..eafc74cedb --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/StringNotMatchesColumnConstraint.java @@ -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 + * + *

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 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(); + } +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/provider/StringColumnConstraintProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/provider/StringColumnConstraintProvider.java index 69b4980def..5207ac248b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/provider/StringColumnConstraintProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/constraint/provider/StringColumnConstraintProvider.java @@ -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("")); diff --git a/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/columnfilter/ColumnTableFilterTest.java b/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/columnfilter/ColumnTableFilterTest.java index 0715ab29f3..383a91e4af 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/columnfilter/ColumnTableFilterTest.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/widgets/table/columnfilter/ColumnTableFilterTest.java @@ -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");