View Javadoc
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 &lt; 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 &gt; V2 */
62      GREATER_THAN(ValidWhenParser.GREATERTHANSIGN) {
63          @Override
64          protected boolean compareTo(int compareTo) {
65              return compareTo > 0;
66          }
67      },
68      /** Compare V1 &gt;= 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 }