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