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