JAL-2808 classes to support filtering by attribute value
[jalview.git] / src / jalview / util / matcher / KeyedMatcher.java
1 package jalview.util.matcher;
2
3 import java.util.function.Function;
4
5 public class KeyedMatcher implements KeyedMatcherI
6 {
7   private String key;
8
9   private MatcherI matcher;
10
11   /*
12    * an optional second condition
13    */
14   KeyedMatcherI combineWith;
15
16   /*
17    * if true, any second condition is AND-ed with this one
18    * if false,any second condition is OR-ed with this one
19    */
20   boolean combineAnd;
21
22   /**
23    * Constructor given a match condition
24    * 
25    * @param m
26    */
27   public KeyedMatcher(String theKey, MatcherI m)
28   {
29     key = theKey;
30     matcher = m;
31   }
32
33   @Override
34   public boolean matches(Function<String, String> valueProvider)
35   {
36     String value = valueProvider.apply(key);
37     boolean matched = matcher.matches(value);
38
39     /*
40      * apply a second condition if there is one, using 
41      * lazy evalution of AND and OR combinations
42      */
43     if (combineWith != null)
44     {
45       if (combineAnd && matched)
46       {
47         matched = combineWith.matches(valueProvider);
48       }
49       if (!combineAnd && !matched)
50       {
51         matched = combineWith.matches(valueProvider);
52       }
53     }
54
55     return matched;
56   }
57
58   @Override
59   public KeyedMatcherI and(String key2, MatcherI m)
60   {
61     return combineWith(key2, m, true);
62   }
63
64   @Override
65   public KeyedMatcherI or(String key2, MatcherI m)
66   {
67     return combineWith(key2, m, false);
68   }
69
70   /**
71    * Answers a Matcher that is the logical combination of this one with the
72    * given argument. The two matchers are AND-ed if and is true, else OR-ed.
73    * 
74    * @param key2
75    * @param condition2
76    * @param and
77    * @return
78    */
79   KeyedMatcher combineWith(String key2, MatcherI condition2,
80           boolean and)
81   {
82     if (condition2 == null)
83     {
84       return this;
85     }
86
87     KeyedMatcher combined = new KeyedMatcher(key2, condition2);
88     combined.combineWith = this;
89     combined.combineAnd = and;
90
91     return combined;
92   }
93
94   @Override
95   public String getKey()
96   {
97     return key;
98   }
99
100   @Override
101   public MatcherI getMatcher()
102   {
103     return matcher;
104   }
105
106   @Override
107   public KeyedMatcherI getSecondMatcher()
108   {
109     return combineWith;
110   }
111
112   @Override
113   public boolean isAnded()
114   {
115     return combineAnd;
116   }
117
118   /**
119    * Answers a string description of this matcher, suitable for debugging or
120    * logging. The format may change in future.
121    */
122   @Override
123   public String toString()
124   {
125     StringBuilder sb = new StringBuilder();
126     sb.append(key).append(" ").append(matcher.getCondition().name())
127             .append(" ").append(matcher.getPattern());
128
129     if (combineWith != null)
130     {
131       sb.append(" ").append(combineAnd ? "AND (" : "OR (")
132               .append(combineWith.toString()).append(")");
133     }
134     return sb.toString();
135   }
136 }