1 | package com.hammurapi.extract; |
2 | |
3 | import java.util.Arrays; |
4 | import java.util.Set; |
5 | |
6 | /** |
7 | * Result of comparison of two extractors/predicates. |
8 | * @author Pavel Vlasov |
9 | * |
10 | */ |
11 | public class ComparisonResult { |
12 | |
13 | // Not mapping constants |
14 | public static final ComparisonResult EQUAL_NM = new ComparisonResult(Type.EQUAL, null); |
15 | public static final ComparisonResult UNEQUAL_NM = new ComparisonResult(Type.UNEQUAL, null); |
16 | public static final ComparisonResult LESS_RESTRICTIVE_NM = new ComparisonResult(Type.LESS_RESTRICTIVE, null); |
17 | public static final ComparisonResult MORE_RESTRICTIVE_NM = new ComparisonResult(Type.MORE_RESTRICTIVE, null); |
18 | public static final ComparisonResult NOT_EQUAL_NM = new ComparisonResult(Type.NOT_EQUAL, null); |
19 | public static final ComparisonResult OPPOSITE_NM = new ComparisonResult(Type.OPPOSITE, null); |
20 | public static final ComparisonResult OPPOSITE_LESS_RESTRICTIVE_NM = new ComparisonResult(Type.OPPOSITE_LESS_RESTRICTIVE, null); |
21 | public static final ComparisonResult OPPOSITE_MORE_RESTRICTIVE_NM = new ComparisonResult(Type.OPPOSITE_MORE_RESTRICTIVE, null); |
22 | |
23 | /** |
24 | * Result of extractor comparison. |
25 | * @author Pavel Vlasov. |
26 | * |
27 | */ |
28 | public enum Type { |
29 | /** |
30 | * Extractors are equal. |
31 | */ |
32 | EQUAL, |
33 | /** |
34 | * Extractors are not equal, i.e. no conclusion can be drawn about values |
35 | * returned by extractors. |
36 | */ |
37 | NOT_EQUAL, |
38 | |
39 | // Enums below are applicable only to predicates. |
40 | /** |
41 | * This predicate is less restrictive than the parameter |
42 | * predicate. E.g. x<=5 is less restrictive than x<5. |
43 | */ |
44 | LESS_RESTRICTIVE, |
45 | /** |
46 | * This predicate is more restrictive than the parameter |
47 | * predicate. E.g. x<6 is more restrictive than x<7. |
48 | */ |
49 | MORE_RESTRICTIVE, |
50 | /** |
51 | * When this predicate evaluates to true, the parameter |
52 | * predicate evaluates to false and vice-versa. |
53 | */ |
54 | OPPOSITE, |
55 | /** |
56 | * The opposite of this predicate is less restrictive than |
57 | * the parameter predicate. |
58 | * E.g. x>5 opposite is x<=5 and it is is less restrictive than x<5. |
59 | */ |
60 | OPPOSITE_LESS_RESTRICTIVE, |
61 | /** |
62 | * The opposite of this predicate is more restrictive than |
63 | * the parameter predicate. |
64 | * E.g. x>5 opposite is x<=5 and it is is more restrictive than x<7. |
65 | */ |
66 | OPPOSITE_MORE_RESTRICTIVE, |
67 | |
68 | // Enums applicable to extractors and constants. |
69 | |
70 | /** |
71 | * Value extracted by the first extractor is less than value extracted by the second extractor |
72 | * for any combination of parameters. |
73 | */ |
74 | LESS_THAN, |
75 | |
76 | /** |
77 | * Value extracted by the first extractor is less than or equal to the value extracted by the second extractor |
78 | * for any combination of parameters. |
79 | */ |
80 | LESS_EQUAL, |
81 | |
82 | /** |
83 | * Value extracted by the first extractor is more than or equal to the value extracted by the second extractor |
84 | * for any combination of parameters. |
85 | */ |
86 | MORE_EQUAL, |
87 | |
88 | /** |
89 | * Value extracted by the first extractor is more than value extracted by the second extractor |
90 | * for any combination of parameters. |
91 | */ |
92 | MORE_THAN, |
93 | |
94 | /** |
95 | * Value extracted by the first extractor is not equal to the value extracted by the second extractor |
96 | * for any combination of parameters. Do not mistake this with NOT_EQUAL. For boolean values (predicates) UNEQUAL is |
97 | * equivalent to OPPOSITE. |
98 | */ |
99 | UNEQUAL |
100 | } |
101 | |
102 | private ComparisonResult.Type type; |
103 | private int[] indexMap; |
104 | |
105 | public ComparisonResult(ComparisonResult.Type type, int[] indexMap) { |
106 | this.type = type; |
107 | this.indexMap = indexMap; |
108 | } |
109 | |
110 | /** |
111 | * @return mapping of indices of parameter extractor to this extractor. E.g. extractors |
112 | * <code>arg[0] < arg[1]</code> and <code>arg[1] > arg[0]</code> are equal with index mapping {1, 0}. |
113 | * <code>null</code> is returned for no mapping (if extractors are <code>NOT_EQUAL</code>) and for 1 to 1 mapping. |
114 | * In other words, if cr = e1.compareTo(e2), |
115 | * then new MappedExtractor(e1, cr.getIndexMap()).compareTo(e2).isOneToOneMapping()==true or |
116 | * return value of new MappedExtractor(e1, cr.getIndexMap()).extract() is the same as of e2.extract() |
117 | */ |
118 | public int[] getIndexMap() { |
119 | return indexMap; |
120 | } |
121 | |
122 | public Type getType() { |
123 | return type; |
124 | } |
125 | |
126 | public boolean isOneToOneMapping() { |
127 | return isOneToOneMapping(indexMap); |
128 | } |
129 | |
130 | public static boolean isOneToOneMapping(int[] map) { |
131 | if (map==null) { |
132 | return true; |
133 | } |
134 | for (int i=0; i<map.length; ++i) { |
135 | if (map[i]!=i && map[i]!=-1) { |
136 | return false; |
137 | } |
138 | } |
139 | return true; |
140 | } |
141 | |
142 | public boolean compareIndexMaps(int[] otherIndexMap) { |
143 | if (indexMap==null) { // Assumes 1-1 mapping |
144 | if (otherIndexMap==null) { |
145 | return true; |
146 | } |
147 | |
148 | for (int i=0; i<otherIndexMap.length; ++i) { |
149 | if (otherIndexMap[i]!=i) { |
150 | return false; |
151 | } |
152 | } |
153 | return true; |
154 | } |
155 | |
156 | if (otherIndexMap==null) { |
157 | for (int i=0; i<indexMap.length; ++i) { |
158 | if (indexMap[i]!=i) { |
159 | return false; |
160 | } |
161 | } |
162 | return true; |
163 | } |
164 | |
165 | return Arrays.equals(indexMap, otherIndexMap); |
166 | } |
167 | |
168 | @Override |
169 | public String toString() { |
170 | return "ComparisonResult [type=" + type + ", indexMap=" |
171 | + Arrays.toString(indexMap) + "]"; |
172 | } |
173 | |
174 | /** |
175 | * Inverses index map. |
176 | * @param indexMap2 |
177 | * @return |
178 | */ |
179 | public static int[] inverse(int[] map, Set<Integer> parameterIndices) { |
180 | if (map==null) { |
181 | return null; |
182 | } |
183 | |
184 | int dim = -1; |
185 | for (int i=0; i<map.length; ++i) { |
186 | if (parameterIndices.contains(i)) { |
187 | if (map[i]>dim) { |
188 | dim = map[i]; |
189 | } |
190 | } |
191 | } |
192 | int[] ret = new int[dim+1]; |
193 | |
194 | for (int i=0; i<map.length; ++i) { |
195 | if (parameterIndices.contains(i)) { |
196 | ret[map[i]] = i; |
197 | } |
198 | } |
199 | return ret; |
200 | } |
201 | |
202 | @Override |
203 | public int hashCode() { |
204 | final int prime = 31; |
205 | int result = 1; |
206 | result = prime * result + Arrays.hashCode(indexMap); |
207 | result = prime * result + ((type == null) ? 0 : type.hashCode()); |
208 | return result; |
209 | } |
210 | |
211 | @Override |
212 | public boolean equals(Object obj) { |
213 | if (this == obj) |
214 | return true; |
215 | if (obj == null) |
216 | return false; |
217 | if (getClass() != obj.getClass()) |
218 | return false; |
219 | ComparisonResult other = (ComparisonResult) obj; |
220 | if (!(isOneToOneMapping() && other.isOneToOneMapping())) { |
221 | if (!Arrays.equals(indexMap, other.indexMap)) |
222 | return false; |
223 | } |
224 | |
225 | if (type != other.type) |
226 | return false; |
227 | return true; |
228 | } |
229 | |
230 | } |