JAL-2808 update spike to latest
[jalview.git] / test / jalview / datamodel / features / FeatureMatcherSetTest.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.assertSame;
6 import static org.testng.Assert.assertTrue;
7 import static org.testng.Assert.fail;
8
9 import jalview.datamodel.SequenceFeature;
10 import jalview.util.matcher.Condition;
11
12 import java.util.HashMap;
13 import java.util.Iterator;
14 import java.util.Locale;
15 import java.util.Map;
16
17 import org.testng.annotations.Test;
18
19 public class FeatureMatcherSetTest
20 {
21   @Test(groups = "Functional")
22   public void testMatches_byAttribute()
23   {
24     /*
25      * a numeric matcher - MatcherTest covers more conditions
26      */
27     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2",
28             "AF");
29     FeatureMatcherSetI fms = new FeatureMatcherSet();
30     fms.and(fm);
31     SequenceFeature sf = new SequenceFeature("Cath", "desc", 11, 12, "grp");
32     assertFalse(fms.matches(sf));
33     sf.setValue("AF", "foobar");
34     assertFalse(fms.matches(sf));
35     sf.setValue("AF", "-2");
36     assertTrue(fms.matches(sf));
37     sf.setValue("AF", "-1");
38     assertTrue(fms.matches(sf));
39     sf.setValue("AF", "-3");
40     assertFalse(fms.matches(sf));
41     sf.setValue("AF", "");
42     assertFalse(fms.matches(sf));
43
44     /*
45      * a string pattern matcher
46      */
47     fm = FeatureMatcher.byAttribute(Condition.Contains, "Cat", "AF");
48     fms = new FeatureMatcherSet();
49     fms.and(fm);
50     assertFalse(fms.matches(sf));
51     sf.setValue("AF", "raining cats and dogs");
52     assertTrue(fms.matches(sf));
53   }
54
55   @Test(groups = "Functional")
56   public void testAnd()
57   {
58     // condition1: AF value contains "dog" (matches)
59     FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.Contains,
60             "dog", "AF");
61     // condition 2: CSQ value does not contain "how" (does not match)
62     FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
63             "how", "CSQ");
64
65     SequenceFeature sf = new SequenceFeature("Cath", "helix domain", 11, 12,
66             6.2f, "grp");
67     sf.setValue("AF", "raining cats and dogs");
68     sf.setValue("CSQ", "showers");
69
70     assertTrue(fm1.matches(sf));
71     assertFalse(fm2.matches(sf));
72
73     FeatureMatcherSetI fms = new FeatureMatcherSet();
74     assertTrue(fms.matches(sf)); // if no conditions, then 'all' pass
75     fms.and(fm1);
76     assertTrue(fms.matches(sf));
77     fms.and(fm2);
78     assertFalse(fms.matches(sf));
79
80     /*
81      * OR a failed attribute condition with a matched label condition
82      */
83     fms = new FeatureMatcherSet();
84     fms.and(fm2);
85     assertFalse(fms.matches(sf));
86     FeatureMatcher byLabelPass = FeatureMatcher.byLabel(Condition.Contains,
87             "Helix");
88     fms.or(byLabelPass);
89     assertTrue(fms.matches(sf));
90
91     /*
92      * OR a failed attribute condition with a failed score condition
93      */
94     fms = new FeatureMatcherSet();
95     fms.and(fm2);
96     assertFalse(fms.matches(sf));
97     FeatureMatcher byScoreFail = FeatureMatcher.byScore(Condition.LT,
98             "5.9");
99     fms.or(byScoreFail);
100     assertFalse(fms.matches(sf));
101
102     /*
103      * OR failed attribute and score conditions with matched label condition
104      */
105     fms = new FeatureMatcherSet();
106     fms.or(fm2).or(byScoreFail);
107     assertFalse(fms.matches(sf));
108     fms.or(byLabelPass);
109     assertTrue(fms.matches(sf));
110   }
111
112   @Test(groups = "Functional")
113   public void testToString()
114   {
115     Locale.setDefault(Locale.ENGLISH);
116     FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.LT, "1.2",
117             "AF");
118     assertEquals(fm1.toString(), "AF < 1.2");
119
120     FeatureMatcher fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
121             "path", "CLIN_SIG");
122     assertEquals(fm2.toString(), "CLIN_SIG does not contain 'path'");
123
124     /*
125      * AND them
126      */
127     FeatureMatcherSetI fms = new FeatureMatcherSet();
128     assertEquals(fms.toString(), "");
129     fms.and(fm1);
130     assertEquals(fms.toString(), "(AF < 1.2)");
131     fms.and(fm2);
132     assertEquals(fms.toString(),
133             "(AF < 1.2) and (CLIN_SIG does not contain 'path')");
134
135     /*
136      * OR them
137      */
138     fms = new FeatureMatcherSet();
139     assertEquals(fms.toString(), "");
140     fms.or(fm1);
141     assertEquals(fms.toString(), "(AF < 1.2)");
142     fms.or(fm2);
143     assertEquals(fms.toString(),
144             "(AF < 1.2) or (CLIN_SIG does not contain 'path')");
145
146     try
147     {
148       fms.and(fm1);
149       fail("Expected exception");
150     } catch (IllegalStateException e)
151     {
152       // expected
153     }
154   }
155
156   @Test(groups = "Functional")
157   public void testOr()
158   {
159     // condition1: AF value contains "dog" (matches)
160     FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.Contains,
161             "dog", "AF");
162     // condition 2: CSQ value does not contain "how" (does not match)
163     FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.NotContains,
164             "how", "CSQ");
165
166     SequenceFeature sf = new SequenceFeature("Cath", "desc", 11, 12, "grp");
167     sf.setValue("AF", "raining cats and dogs");
168     sf.setValue("CSQ", "showers");
169
170     assertTrue(fm1.matches(sf));
171     assertFalse(fm2.matches(sf));
172
173     FeatureMatcherSetI fms = new FeatureMatcherSet();
174     assertTrue(fms.matches(sf)); // if no conditions, then 'all' pass
175     fms.or(fm1);
176     assertTrue(fms.matches(sf));
177     fms.or(fm2);
178     assertTrue(fms.matches(sf)); // true or false makes true
179
180     fms = new FeatureMatcherSet();
181     fms.or(fm2);
182     assertFalse(fms.matches(sf));
183     fms.or(fm1);
184     assertTrue(fms.matches(sf)); // false or true makes true
185
186     try
187     {
188       fms.and(fm2);
189       fail("Expected exception");
190     } catch (IllegalStateException e)
191     {
192       // expected
193     }
194   }
195
196   @Test(groups = "Functional")
197   public void testIsEmpty()
198   {
199     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2.0",
200             "AF");
201     FeatureMatcherSetI fms = new FeatureMatcherSet();
202     assertTrue(fms.isEmpty());
203     fms.and(fm);
204     assertFalse(fms.isEmpty());
205   }
206
207   @Test(groups = "Functional")
208   public void testGetMatchers()
209   {
210     FeatureMatcherSetI fms = new FeatureMatcherSet();
211
212     /*
213      * empty iterable:
214      */
215     Iterator<FeatureMatcherI> iterator = fms.getMatchers().iterator();
216     assertFalse(iterator.hasNext());
217
218     /*
219      * one matcher:
220      */
221     FeatureMatcherI fm1 = FeatureMatcher.byAttribute(Condition.GE, "-2",
222             "AF");
223     fms.and(fm1);
224     iterator = fms.getMatchers().iterator();
225     assertSame(fm1, iterator.next());
226     assertFalse(iterator.hasNext());
227
228     /*
229      * two matchers:
230      */
231     FeatureMatcherI fm2 = FeatureMatcher.byAttribute(Condition.LT, "8f",
232             "AF");
233     fms.and(fm2);
234     iterator = fms.getMatchers().iterator();
235     assertSame(fm1, iterator.next());
236     assertSame(fm2, iterator.next());
237     assertFalse(iterator.hasNext());
238   }
239
240   /**
241    * Tests for the 'compound attribute' key i.e. where first key's value is a map
242    * from which we take the value for the second key, e.g. CSQ : Consequence
243    */
244   @Test(groups = "Functional")
245   public void testMatches_compoundKey()
246   {
247     /*
248      * a numeric matcher - MatcherTest covers more conditions
249      */
250     FeatureMatcherI fm = FeatureMatcher.byAttribute(Condition.GE, "-2",
251             "CSQ", "Consequence");
252     SequenceFeature sf = new SequenceFeature("Cath", "desc", 2, 10, "grp");
253     FeatureMatcherSetI fms = new FeatureMatcherSet();
254     fms.and(fm);
255     assertFalse(fms.matches(sf));
256     Map<String, String> csq = new HashMap<>();
257     sf.setValue("CSQ", csq);
258     assertFalse(fms.matches(sf));
259     csq.put("Consequence", "-2");
260     assertTrue(fms.matches(sf));
261     csq.put("Consequence", "-1");
262     assertTrue(fms.matches(sf));
263     csq.put("Consequence", "-3");
264     assertFalse(fms.matches(sf));
265     csq.put("Consequence", "");
266     assertFalse(fms.matches(sf));
267     csq.put("Consequence", "junk");
268     assertFalse(fms.matches(sf));
269
270     /*
271      * a string pattern matcher
272      */
273     fm = FeatureMatcher.byAttribute(Condition.Contains, "Cat", "CSQ",
274             "Consequence");
275     fms = new FeatureMatcherSet();
276     fms.and(fm);
277     assertFalse(fms.matches(sf));
278     csq.put("PolyPhen", "damaging");
279     assertFalse(fms.matches(sf));
280     csq.put("Consequence", "damaging");
281     assertFalse(fms.matches(sf));
282     csq.put("Consequence", "Catastrophic");
283     assertTrue(fms.matches(sf));
284   }
285 }