1 /*
2 * $Id$
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21 package org.apache.struts.validator.validwhen;
22
23 import java.math.BigDecimal;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 /**
28 * Enum for comparing two values.
29 *
30 * @author Graff Stefan
31 *
32 * @since Struts 1.4.1
33 */
34 public enum ValidWhenComparison {
35 /** Compare V1 <= V2 */
36 LESS_EQUAL(ValidWhenParser.LESSEQUALSIGN) {
37 @Override
38 protected boolean compareTo(int compareTo) {
39 return compareTo <= 0;
40 }
41 },
42 /** Compare V1 < V2 */
43 LESS_THAN(ValidWhenParser.LESSTHANSIGN) {
44 @Override
45 protected boolean compareTo(int compareTo) {
46 return compareTo < 0;
47 }
48 },
49 /** Compare V1 == V2 */
50 EQUAL(ValidWhenParser.EQUALSIGN) {
51 @Override
52 protected boolean compareWithNull(Object v1, Object v2) {
53 return v1 == v2;
54 }
55
56 @Override
57 protected boolean compareTo(int compareTo) {
58 return compareTo == 0;
59 }
60 },
61 /** Compare V1 > V2 */
62 GREATER_THAN(ValidWhenParser.GREATERTHANSIGN) {
63 @Override
64 protected boolean compareTo(int compareTo) {
65 return compareTo > 0;
66 }
67 },
68 /** Compare V1 >= V2 */
69 GREATER_EQUAL(ValidWhenParser.GREATEREQUALSIGN) {
70 @Override
71 protected boolean compareTo(int compareTo) {
72 return compareTo >= 0;
73 }
74 },
75 /** Compare V1 != V2 */
76 NOT_EQUAL(ValidWhenParser.NOTEQUALSIGN) {
77 @Override
78 protected boolean compareWithNull(Object v1, Object v2) {
79 return v1 != v2;
80 }
81
82 @Override
83 protected boolean compareTo(int compareTo) {
84 return compareTo != 0;
85 }
86 };
87
88 /**
89 * {@code Map} to get the correct Comparison for Token-Number.
90 */
91 private final static Map<Integer, ValidWhenComparison> COMP_MAPPER = new HashMap<>();
92
93 static {
94 for (ValidWhenComparison comp : ValidWhenComparison.values()) {
95 COMP_MAPPER.put(comp.tokenNum, comp);
96 }
97 }
98
99 /**
100 * Get the {@code ValidWhenComparison} for given
101 * token-number.
102 *
103 * @param tokenNum the token-number
104 *
105 * @return the {@code ValidWhenComparison} or
106 * {@code null} when not found
107 */
108 public static ValidWhenComparison getComp(int tokenNum) {
109 return COMP_MAPPER.get(tokenNum);
110 }
111
112 /**
113 * The token-number for this {@code ValidWhenComparison}
114 */
115 private final int tokenNum;
116
117 /**
118 * Constructor for this class.
119 *
120 * @param tokenNum the token-number
121 */
122 private ValidWhenComparison(int tokenNum) {
123 this.tokenNum = tokenNum;
124 }
125
126 /**
127 * Method to compare two {@code values} where at least
128 * one of them is {@code null}.
129 *
130 * @param v1 first value
131 * @param v2 second value
132 *
133 * @return {@code true} or {@code false} depending of
134 * the {@code ValidWhenComparison}
135 */
136 protected boolean compareWithNull(Object v1, Object v2) {
137 return false;
138 }
139
140 /**
141 * Method to compare two {@code values}, neither of
142 * which is {@code null}.
143 *
144 * @param v1 first value
145 * @param v2 second value
146 *
147 * @return {@code true} or {@code false} depending of
148 * the {@code ValidWhenComparison}
149 */
150 protected <T extends Comparable<T>> boolean compareTo(T v1, T v2) {
151 return compareTo(v1.compareTo(v2));
152 }
153
154 /**
155 * Method for the correct interpretation of the
156 * return-value of {@code compareTo}, depending on
157 * {@code ValidWhenComparison}.
158 *
159 * @param compareTo the return-value of {@code compareTo}
160 *
161 * @return {@code true} or {@code false} depending of
162 * the {@code ValidWhenComparison}
163 */
164 protected abstract boolean compareTo(int compareTo);
165
166 /**
167 * Compares two {@code value}s with consideration
168 * of {@code ValidWhenComparison}.
169 *
170 * <p>Following the comparing-steps:</p>
171 * <ol>
172 * <li>Tests whether at least one value is {@code null}.
173 * If so, then it is only possible to compare for
174 * (non)-equality.</li>
175 * <li>Try to convert both values into numbers and compares them.</li>
176 * <li>Compares both values as {@code String}s.</code>
177 * </ol>
178 *
179 * @param v1 first value
180 * @param v2 second value
181 *
182 * @return {@code true} or {@code false} depending of
183 * the {@code ValidWhenComparison}
184 */
185 public boolean compare(ValidWhenResult<?> v1, ValidWhenResult<?> v2) {
186 Object o1 = v1.getValue();
187 Object o2 = v2.getValue();
188
189 if (o1 == null || o2 == null) {
190 return compareWithNull(o1, o2);
191 }
192
193 try {
194 BigDecimal i1 = convertBigDecimal(o1);
195 BigDecimal i2 = convertBigDecimal(o2);
196
197 return compareTo(i1, i2);
198 } catch (NumberFormatException e) {
199 // No problem, test strings
200 }
201
202 String s1 = v1.toString();
203 String s2 = v2.toString();
204 return compareTo(s1, s2);
205 }
206
207 /**
208 * Tries to convert {@code val} to a {@code BigDecimal}.
209 *
210 * @param val Value to convert to a {@code BigDecimal}
211 *
212 * @return the converted {@code BigDecimal}-value
213 *
214 * @throws NumberFormatException if {@code val} is not a valid
215 * representation of a {@code BigDecimal}.
216 */
217 private static BigDecimal convertBigDecimal(Object val) {
218 if (val instanceof BigDecimal) {
219 return (BigDecimal)val;
220 } else if (val instanceof Integer) {
221 return new BigDecimal((Integer)val);
222 } else {
223 return new BigDecimal(val.toString());
224 }
225 }
226 }