From 3013ab968530be65871281fc548c5ffa92a7b7b0 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 23 Nov 2017 12:50:43 +0000 Subject: [PATCH] JAL-2808 added conditions Present, NotPresent as options --- resources/lang/Messages.properties | 2 + resources/lang/Messages_es.properties | 2 + src/jalview/gui/FeatureTypeSettings.java | 46 +++++++++++++++++++++-- src/jalview/util/matcher/Condition.java | 1 + src/jalview/util/matcher/KeyedMatcher.java | 16 ++++---- src/jalview/util/matcher/Matcher.java | 12 +++++- test/jalview/util/matcher/ConditionTest.java | 2 + test/jalview/util/matcher/KeyedMatcherTest.java | 8 ++++ test/jalview/util/matcher/MatcherTest.java | 16 ++++++++ 9 files changed, 92 insertions(+), 13 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index a592282..00888d5 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1327,6 +1327,8 @@ label.matchCondition_contains = Contains label.matchCondition_notcontains = Does not contain label.matchCondition_matches = Matches label.matchCondition_notmatches = Does not match +label.matchCondition_present = Is present +label.matchCondition_notpresent = Is not present label.matchCondition_eq = = label.matchCondition_ne = not = label.matchCondition_lt = < diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index 31c3a86..616cb9d 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -1328,6 +1328,8 @@ label.matchCondition_contains = Contiene label.matchCondition_notcontains = No contiene label.matchCondition_matches = Es igual a label.matchCondition_notmatches = No es igual a +label.matchCondition_present = Está presente +label.matchCondition_notpresent = No está presente label.matchCondition_eq = = label.matchCondition_ne = not = label.matchCondition_lt = < diff --git a/src/jalview/gui/FeatureTypeSettings.java b/src/jalview/gui/FeatureTypeSettings.java index 372234a..1dd12aa 100644 --- a/src/jalview/gui/FeatureTypeSettings.java +++ b/src/jalview/gui/FeatureTypeSettings.java @@ -47,6 +47,7 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -94,6 +95,9 @@ public class FeatureTypeSettings extends JalviewDialog private static final int BELOW_THRESHOLD_OPTION = 2; + private static final DecimalFormat DECFMT_2_2 = new DecimalFormat( + "##.##"); + /* * FeatureRenderer holds colour scheme and filters for feature types */ @@ -1238,7 +1242,7 @@ public class FeatureTypeSettings extends JalviewDialog * and an empty filter for the user to populate (add) */ KeyedMatcherI noFilter = new KeyedMatcher(Condition.values()[0], "", - (String) null); + (String[]) null); filters.add(noFilter); /* @@ -1352,6 +1356,7 @@ public class FeatureTypeSettings extends JalviewDialog */ populateConditions((String) attCombo.getSelectedItem(), cond, condCombo); + condCombo.setPreferredSize(new Dimension(150, 20)); condCombo.addItemListener(itemListener); filterRow.add(condCombo); @@ -1371,6 +1376,32 @@ public class FeatureTypeSettings extends JalviewDialog filterRow.add(patternField); /* + * disable pattern field for condition 'Present / NotPresent' + */ + Condition selectedCondition = (Condition) condCombo.getSelectedItem(); + if (selectedCondition == Condition.Present + || selectedCondition == Condition.NotPresent) + { + patternField.setEnabled(false); + } + + /* + * if a numeric condition is selected, show the value range + * as a tooltip on the value input field + */ + if (selectedCondition.isNumeric()) + { + float[] minMax = FeatureAttributes.getInstance() + .getMinMax(featureType, attName); + if (minMax != null) + { + String tip = String.format("(%s - %s)", + DECFMT_2_2.format(minMax[0]), DECFMT_2_2.format(minMax[1])); + patternField.setToolTipText(tip); + } + } + + /* * add remove button if filter is populated (non-empty pattern) */ if (pattern != null && pattern.trim().length() > 0) @@ -1457,8 +1488,8 @@ public class FeatureTypeSettings extends JalviewDialog * Answers true unless a numeric condition has been selected with a non-numeric * value. Sets the value field to RED with a tooltip if in error. *

- * If the pattern entered is empty, this method returns false, but does not mark - * the field as invalid. This supports selecting an attribute for a new + * If the pattern is expected but is empty, this method returns false, but does + * not mark the field as invalid. This supports selecting an attribute for a new * condition before a match pattern has been entered. * * @param value @@ -1473,6 +1504,11 @@ public class FeatureTypeSettings extends JalviewDialog } Condition cond = (Condition) condCombo.getSelectedItem(); + if (cond == Condition.Present || cond == Condition.NotPresent) + { + return true; + } + value.setBackground(Color.white); value.setToolTipText(""); String v1 = value.getText().trim(); @@ -1553,7 +1589,9 @@ public class FeatureTypeSettings extends JalviewDialog for (KeyedMatcherI filter : filters) { String pattern = filter.getMatcher().getPattern(); - if (pattern.trim().length() > 0) + Condition condition = filter.getMatcher().getCondition(); + if (pattern.trim().length() > 0 || condition == Condition.Present + || condition == Condition.NotPresent) { if (anded) { diff --git a/src/jalview/util/matcher/Condition.java b/src/jalview/util/matcher/Condition.java index 455f805..4d14063 100644 --- a/src/jalview/util/matcher/Condition.java +++ b/src/jalview/util/matcher/Condition.java @@ -12,6 +12,7 @@ import java.util.Map; public enum Condition { Contains(false), NotContains(false), Matches(false), NotMatches(false), + Present(false), NotPresent(false), EQ(true), NE(true), LT(true), LE(true), GT(true), GE(true); private static Map displayNames = new HashMap<>(); diff --git a/src/jalview/util/matcher/KeyedMatcher.java b/src/jalview/util/matcher/KeyedMatcher.java index ef1c702..f21756a 100644 --- a/src/jalview/util/matcher/KeyedMatcher.java +++ b/src/jalview/util/matcher/KeyedMatcher.java @@ -73,22 +73,24 @@ public class KeyedMatcher implements KeyedMatcherI } /** - * Answers a string description of this matcher, suitable for debugging or - * logging. The format may change in future. + * Answers a string description of this matcher, suitable for display, debugging + * or logging. The format may change in future. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(String.join(COLON, key)).append(" ") - .append(matcher.getCondition().toString()).append(" "); - if (matcher.getCondition().isNumeric()) + .append(matcher.getCondition().toString()); + Condition condition = matcher.getCondition(); + if (condition.isNumeric()) { - sb.append(matcher.getPattern()); + sb.append(" ").append(matcher.getPattern()); } - else + else if (condition != Condition.Present + && condition != Condition.NotPresent) { - sb.append("'").append(matcher.getPattern()).append("'"); + sb.append(" '").append(matcher.getPattern()).append("'"); } return sb.toString(); diff --git a/src/jalview/util/matcher/Matcher.java b/src/jalview/util/matcher/Matcher.java index 715694c..14a8585 100644 --- a/src/jalview/util/matcher/Matcher.java +++ b/src/jalview/util/matcher/Matcher.java @@ -53,7 +53,7 @@ public class Matcher implements MatcherI else { // pattern matches will be non-case-sensitive - pattern = compareTo.toUpperCase(); + pattern = compareTo == null ? null : compareTo.toUpperCase(); } // if we add regex conditions (e.g. matchesPattern), then @@ -105,7 +105,8 @@ public class Matcher implements MatcherI if (val == null) { return condition == Condition.NotContains - || condition == Condition.NotMatches; + || condition == Condition.NotMatches + || condition == Condition.NotPresent; } String upper = val.toUpperCase().trim(); @@ -123,6 +124,11 @@ public class Matcher implements MatcherI case NotContains: matched = upper.indexOf(pattern) == -1; break; + case Present: + matched = true; + break; + default: + break; } return matched; } @@ -161,6 +167,8 @@ public class Matcher implements MatcherI case GE: matched = f >= value; break; + default: + break; } return matched; diff --git a/test/jalview/util/matcher/ConditionTest.java b/test/jalview/util/matcher/ConditionTest.java index 9d8b225..883596a 100644 --- a/test/jalview/util/matcher/ConditionTest.java +++ b/test/jalview/util/matcher/ConditionTest.java @@ -16,6 +16,8 @@ public class ConditionTest assertEquals(Condition.NotContains.toString(), "Does not contain"); assertEquals(Condition.Matches.toString(), "Matches"); assertEquals(Condition.NotMatches.toString(), "Does not match"); + assertEquals(Condition.Present.toString(), "Is present"); + assertEquals(Condition.NotPresent.toString(), "Is not present"); assertEquals(Condition.LT.toString(), "<"); assertEquals(Condition.LE.toString(), "<="); assertEquals(Condition.GT.toString(), ">"); diff --git a/test/jalview/util/matcher/KeyedMatcherTest.java b/test/jalview/util/matcher/KeyedMatcherTest.java index 01d0067..3fd7800 100644 --- a/test/jalview/util/matcher/KeyedMatcherTest.java +++ b/test/jalview/util/matcher/KeyedMatcherTest.java @@ -39,6 +39,14 @@ public class KeyedMatcherTest */ KeyedMatcherI km = new KeyedMatcher(Condition.LT, 1.2f, "AF"); assertEquals(km.toString(), "AF < 1.2"); + + /* + * Present / NotPresent omit the value pattern + */ + km = new KeyedMatcher(Condition.Present, "", "AF"); + assertEquals(km.toString(), "AF Is present"); + km = new KeyedMatcher(Condition.NotPresent, "", "AF"); + assertEquals(km.toString(), "AF Is not present"); } @Test diff --git a/test/jalview/util/matcher/MatcherTest.java b/test/jalview/util/matcher/MatcherTest.java index ee0ff82..f4c8181 100644 --- a/test/jalview/util/matcher/MatcherTest.java +++ b/test/jalview/util/matcher/MatcherTest.java @@ -167,6 +167,22 @@ public class MatcherTest assertTrue(m.matches(null)); /* + * value is present (is not null) + */ + m = new Matcher(Condition.Present, null); + assertTrue(m.matches("benign")); + assertTrue(m.matches("")); + assertFalse(m.matches(null)); + + /* + * value is not present (is null) + */ + m = new Matcher(Condition.NotPresent, null); + assertFalse(m.matches("benign")); + assertFalse(m.matches("")); + assertTrue(m.matches(null)); + + /* * a float with a string match condition will be treated as string */ Matcher m1 = new Matcher(Condition.Contains, "32"); -- 1.7.10.2