Merge branch 'bug/JAL-2846' into develop
[jalview.git] / test / jalview / datamodel / features / FeatureMatcherTest.java
1 package jalview.datamodel.features;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertNull;
6 import static org.testng.Assert.assertSame;
7 import static org.testng.Assert.assertTrue;
8
9 import jalview.datamodel.SequenceFeature;
10 import jalview.util.MessageManager;
11 import jalview.util.matcher.Condition;
12
13 import java.util.Locale;
14
15 import org.testng.annotations.Test;
16
17 public class FeatureMatcherTest
18 {
19   @Test(groups = "Functional")
20   public void testMatches_byLabel()
21   {
22     SequenceFeature sf = new SequenceFeature("Cath", "this is my label", 11,
23             12, "grp");
24
25     /*
26      * contains - not case sensitive
27      */
28     assertTrue(
29             FeatureMatcher.byLabel(Condition.Contains, "IS").matches(sf));
30     assertTrue(FeatureMatcher.byLabel(Condition.Contains, "").matches(sf));
31     assertFalse(
32             FeatureMatcher.byLabel(Condition.Contains, "ISNT").matches(sf));
33
34     /*
35      * does not contain
36      */
37     assertTrue(FeatureMatcher.byLabel(Condition.NotContains, "isnt")
38             .matches(sf));
39     assertFalse(FeatureMatcher.byLabel(Condition.NotContains, "is")
40             .matches(sf));
41
42     /*
43      * matches
44      */
45     assertTrue(FeatureMatcher.byLabel(Condition.Matches, "THIS is MY label")
46             .matches(sf));
47     assertFalse(FeatureMatcher.byLabel(Condition.Matches, "THIS is MY")
48             .matches(sf));
49
50     /*
51      * does not match
52      */
53     assertFalse(FeatureMatcher
54             .byLabel(Condition.NotMatches, "THIS is MY label").matches(sf));
55     assertTrue(FeatureMatcher.byLabel(Condition.NotMatches, "THIS is MY")
56             .matches(sf));
57
58     /*
59      * is present / not present
60      */
61     assertTrue(FeatureMatcher.byLabel(Condition.Present, "").matches(sf));
62     assertFalse(
63             FeatureMatcher.byLabel(Condition.NotPresent, "").matches(sf));
64   }
65
66   @Test(groups = "Functional")
67   public void testMatches_byScore()
68   {
69     SequenceFeature sf = new SequenceFeature("Cath", "this is my label", 11,
70             12, 3.2f, "grp");
71
72     assertTrue(FeatureMatcher.byScore(Condition.LT, "3.3").matches(sf));
73     assertFalse(FeatureMatcher.byScore(Condition.LT, "3.2").matches(sf));
74     assertFalse(FeatureMatcher.byScore(Condition.LT, "2.2").matches(sf));
75
76     assertTrue(FeatureMatcher.byScore(Condition.LE, "3.3").matches(sf));
77     assertTrue(FeatureMatcher.byScore(Condition.LE, "3.2").matches(sf));
78     assertFalse(FeatureMatcher.byScore(Condition.LE, "2.2").matches(sf));
79
80     assertFalse(FeatureMatcher.byScore(Condition.EQ, "3.3").matches(sf));
81     assertTrue(FeatureMatcher.byScore(Condition.EQ, "3.2").matches(sf));
82
83     assertFalse(FeatureMatcher.byScore(Condition.GE, "3.3").matches(sf));
84     assertTrue(FeatureMatcher.byScore(Condition.GE, "3.2").matches(sf));
85     assertTrue(FeatureMatcher.byScore(Condition.GE, "2.2").matches(sf));
86
87     assertFalse(FeatureMatcher.byScore(Condition.GT, "3.3").matches(sf));
88     assertFalse(FeatureMatcher.byScore(Condition.GT, "3.2").matches(sf));
89     assertTrue(FeatureMatcher.byScore(Condition.GT, "2.2").matches(sf));
90   }
91
92   @Test(groups = "Functional")
93   public void testMatches_byAttribute()
94   {
95     /*
96      * a numeric matcher - MatcherTest covers more conditions
97      */
98     FeatureMatcherI fm = FeatureMatcher
99             .byAttribute(Condition.GE, "-2", "AF");
100     SequenceFeature sf = new SequenceFeature("Cath", "desc", 11, 12, "grp");
101     assertFalse(fm.matches(sf));
102     sf.setValue("AF", "foobar");
103     assertFalse(fm.matches(sf));
104     sf.setValue("AF", "-2");
105     assertTrue(fm.matches(sf));
106     sf.setValue("AF", "-1");
107     assertTrue(fm.matches(sf));
108     sf.setValue("AF", "-3");
109     assertFalse(fm.matches(sf));
110     sf.setValue("AF", "");
111     assertFalse(fm.matches(sf));
112
113     /*
114      * a string pattern matcher
115      */
116     fm = FeatureMatcher.byAttribute(Condition.Contains, "Cat", "AF");
117     assertFalse(fm.matches(sf));
118     sf.setValue("AF", "raining cats and dogs");
119     assertTrue(fm.matches(sf));
120
121     fm = FeatureMatcher.byAttribute(Condition.Present, "", "AC");
122     assertFalse(fm.matches(sf));
123     sf.setValue("AC", "21");
124     assertTrue(fm.matches(sf));
125
126     fm = FeatureMatcher.byAttribute(Condition.NotPresent, "", "AC_Females");
127     assertTrue(fm.matches(sf));
128     sf.setValue("AC_Females", "21");
129     assertFalse(fm.matches(sf));
130   }
131
132   @Test(groups = "Functional")
133   public void testToString()
134   {
135     Locale.setDefault(Locale.ENGLISH);
136
137     /*
138      * toString uses the i18n translation of the enum conditions
139      */
140     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.LT, "1.2",
141             "AF");
142     assertEquals(fm.toString(), "AF < 1.2");
143
144     /*
145      * Present / NotPresent omit the value pattern
146      */
147     fm = FeatureMatcher.byAttribute(Condition.Present, "", "AF");
148     assertEquals(fm.toString(), "AF is present");
149     fm = FeatureMatcher.byAttribute(Condition.NotPresent, "", "AF");
150     assertEquals(fm.toString(), "AF is not present");
151
152     /*
153      * by Label
154      */
155     fm = FeatureMatcher.byLabel(Condition.Matches, "foobar");
156     assertEquals(fm.toString(),
157             MessageManager.getString("label.label") + " matches 'foobar'");
158
159     /*
160      * by Score
161      */
162     fm = FeatureMatcher.byScore(Condition.GE, "12.2");
163     assertEquals(fm.toString(),
164             MessageManager.getString("label.score") + " >= 12.2");
165   }
166
167   @Test(groups = "Functional")
168   public void testGetAttribute()
169   {
170     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2",
171             "AF");
172     assertEquals(fm.getAttribute(), new String[] { "AF" });
173
174     /*
175      * compound key (attribute / subattribute)
176      */
177     fm = FeatureMatcher.byAttribute(Condition.GE, "-2F", "CSQ",
178             "Consequence");
179     assertEquals(fm.getAttribute(), new String[] { "CSQ", "Consequence" });
180
181     /*
182      * answers null if match is by Label or by Score
183      */
184     assertNull(FeatureMatcher.byLabel(Condition.NotContains, "foo")
185             .getAttribute());
186     assertNull(FeatureMatcher.byScore(Condition.LE, "-1").getAttribute());
187   }
188
189   @Test(groups = "Functional")
190   public void testIsByAttribute()
191   {
192     assertFalse(FeatureMatcher.byLabel(Condition.NotContains, "foo")
193             .isByAttribute());
194     assertFalse(FeatureMatcher.byScore(Condition.LE, "-1").isByAttribute());
195     assertTrue(FeatureMatcher.byAttribute(Condition.LE, "-1", "AC")
196             .isByAttribute());
197   }
198
199   @Test(groups = "Functional")
200   public void testIsByLabel()
201   {
202     assertTrue(FeatureMatcher.byLabel(Condition.NotContains, "foo")
203             .isByLabel());
204     assertFalse(FeatureMatcher.byScore(Condition.LE, "-1").isByLabel());
205     assertFalse(FeatureMatcher.byAttribute(Condition.LE, "-1", "AC")
206             .isByLabel());
207   }
208
209   @Test(groups = "Functional")
210   public void testIsByScore()
211   {
212     assertFalse(FeatureMatcher.byLabel(Condition.NotContains, "foo")
213             .isByScore());
214     assertTrue(FeatureMatcher.byScore(Condition.LE, "-1").isByScore());
215     assertFalse(FeatureMatcher.byAttribute(Condition.LE, "-1", "AC")
216             .isByScore());
217   }
218
219   @Test(groups = "Functional")
220   public void testGetMatcher()
221   {
222     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2f",
223             "AF");
224     assertEquals(fm.getMatcher().getCondition(), Condition.GE);
225     assertEquals(fm.getMatcher().getFloatValue(), -2F);
226     assertEquals(fm.getMatcher().getPattern(), "-2.0");
227   }
228
229   @Test(groups = "Functional")
230   public void testFromString()
231   {
232     FeatureMatcherI fm = FeatureMatcher.fromString("'AF' LT 1.2");
233     assertFalse(fm.isByLabel());
234     assertFalse(fm.isByScore());
235     assertEquals(fm.getAttribute(), new String[] { "AF" });
236     assertSame(Condition.LT, fm.getMatcher().getCondition());
237     assertEquals(fm.getMatcher().getFloatValue(), 1.2f);
238     assertEquals(fm.getMatcher().getPattern(), "1.2");
239
240     // quotes are optional, condition is not case sensitive
241     fm = FeatureMatcher.fromString("AF lt '1.2'");
242     assertFalse(fm.isByLabel());
243     assertFalse(fm.isByScore());
244     assertEquals(fm.getAttribute(), new String[] { "AF" });
245     assertSame(Condition.LT, fm.getMatcher().getCondition());
246     assertEquals(fm.getMatcher().getFloatValue(), 1.2f);
247     assertEquals(fm.getMatcher().getPattern(), "1.2");
248
249     fm = FeatureMatcher.fromString("'AF' Present");
250     assertFalse(fm.isByLabel());
251     assertFalse(fm.isByScore());
252     assertEquals(fm.getAttribute(), new String[] { "AF" });
253     assertSame(Condition.Present, fm.getMatcher().getCondition());
254
255     fm = FeatureMatcher.fromString("CSQ:Consequence contains damaging");
256     assertFalse(fm.isByLabel());
257     assertFalse(fm.isByScore());
258     assertEquals(fm.getAttribute(), new String[] { "CSQ", "Consequence" });
259     assertSame(Condition.Contains, fm.getMatcher().getCondition());
260     assertEquals(fm.getMatcher().getPattern(), "damaging");
261
262     // keyword Label is not case sensitive
263     fm = FeatureMatcher.fromString("LABEL Matches 'foobar'");
264     assertTrue(fm.isByLabel());
265     assertFalse(fm.isByScore());
266     assertNull(fm.getAttribute());
267     assertSame(Condition.Matches, fm.getMatcher().getCondition());
268     assertEquals(fm.getMatcher().getPattern(), "foobar");
269
270     fm = FeatureMatcher.fromString("'Label' matches 'foo bar'");
271     assertTrue(fm.isByLabel());
272     assertFalse(fm.isByScore());
273     assertNull(fm.getAttribute());
274     assertSame(Condition.Matches, fm.getMatcher().getCondition());
275     assertEquals(fm.getMatcher().getPattern(), "foo bar");
276
277     // quotes optional on pattern
278     fm = FeatureMatcher.fromString("'Label' matches foo bar");
279     assertTrue(fm.isByLabel());
280     assertFalse(fm.isByScore());
281     assertNull(fm.getAttribute());
282     assertSame(Condition.Matches, fm.getMatcher().getCondition());
283     assertEquals(fm.getMatcher().getPattern(), "foo bar");
284
285     fm = FeatureMatcher.fromString("Score GE 12.2");
286     assertFalse(fm.isByLabel());
287     assertTrue(fm.isByScore());
288     assertNull(fm.getAttribute());
289     assertSame(Condition.GE, fm.getMatcher().getCondition());
290     assertEquals(fm.getMatcher().getPattern(), "12.2");
291     assertEquals(fm.getMatcher().getFloatValue(), 12.2f);
292
293     // keyword Score is not case sensitive
294     fm = FeatureMatcher.fromString("'SCORE' ge '12.2'");
295     assertFalse(fm.isByLabel());
296     assertTrue(fm.isByScore());
297     assertNull(fm.getAttribute());
298     assertSame(Condition.GE, fm.getMatcher().getCondition());
299     assertEquals(fm.getMatcher().getPattern(), "12.2");
300     assertEquals(fm.getMatcher().getFloatValue(), 12.2f);
301
302     // invalid numeric pattern
303     assertNull(FeatureMatcher.fromString("Score eq twelve"));
304     // unbalanced opening quote
305     assertNull(FeatureMatcher.fromString("'Score ge 12.2"));
306     // unbalanced pattern quote
307     assertNull(FeatureMatcher.fromString("'Score' ge '12.2"));
308     // pattern missing
309     assertNull(FeatureMatcher.fromString("Score ge"));
310     // condition and pattern missing
311     assertNull(FeatureMatcher.fromString("Score"));
312     // everything missing
313     assertNull(FeatureMatcher.fromString(""));
314   }
315
316   /**
317    * Tests for toStableString which (unlike toString) does not i18n the
318    * conditions
319    */
320   @Test(groups = "Functional")
321   public void testToStableString()
322   {
323     // attribute name not quoted unless it contains space
324     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.LT, "1.2",
325             "AF");
326     assertEquals(fm.toStableString(), "AF LT 1.2");
327
328     /*
329      * Present / NotPresent omit the value pattern
330      */
331     fm = FeatureMatcher.byAttribute(Condition.Present, "", "AF");
332     assertEquals(fm.toStableString(), "AF Present");
333     fm = FeatureMatcher.byAttribute(Condition.NotPresent, "", "AF");
334     assertEquals(fm.toStableString(), "AF NotPresent");
335
336     /*
337      * by Label
338      * pattern not quoted unless it contains space
339      */
340     fm = FeatureMatcher.byLabel(Condition.Matches, "foobar");
341     assertEquals(fm.toStableString(), "Label Matches foobar");
342
343     fm = FeatureMatcher.byLabel(Condition.Matches, "foo bar");
344     assertEquals(fm.toStableString(), "Label Matches 'foo bar'");
345
346     /*
347      * by Score
348      */
349     fm = FeatureMatcher.byScore(Condition.GE, "12.2");
350     assertEquals(fm.toStableString(), "Score GE 12.2");
351   }
352 }