Line | Hits | Source |
---|---|---|
1 | /* | |
2 | Chrysalis Web Framework [http://chrysalis.sourceforge.net] | |
3 | Copyright (c) 2002, 2003, 2004, Paul Strack | |
4 | ||
5 | All rights reserved. | |
6 | ||
7 | Redistribution and use in source and binary forms, with or without | |
8 | modification, are permitted provided that the following conditions are met: | |
9 | ||
10 | 1. Redistributions of source code must retain the above copyright notice, this | |
11 | list of conditions and the following disclaimer. | |
12 | ||
13 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
14 | this list of conditions and the following disclaimer in the documentation | |
15 | and/or other materials provided with the distribution. | |
16 | ||
17 | 3. Neither the name of the copyright holder nor the names of its contributors | |
18 | may be used to endorse or promote products derived from this software without | |
19 | specific prior written permission. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | |
32 | ||
33 | package org.chwf.filter; | |
34 | ||
35 | import java.util.Map; | |
36 | ||
37 | /** | |
38 | * Generic validator. Performs basic validation using {@link BeanFilter} | |
39 | * attributes. | |
40 | * | |
41 | * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a> | |
42 | */ | |
43 | 1 | public class GenericValidator extends Validator { |
44 | ||
45 | /** Empty string. */ | |
46 | private static final String EMPTY_STRING = ""; | |
47 | ||
48 | /** The filter of the validated bean. */ | |
49 | private BeanFilter filter; | |
50 | ||
51 | /** | |
52 | * Constructor.<p> | |
53 | * | |
54 | * @param beanClass The bean class being validated. | |
55 | * @throws InitializationException If the filter cannot be initialized. | |
56 | */ | |
57 | public GenericValidator(Class beanClass) throws InitializationException { | |
58 | 2 | super(beanClass); |
59 | 2 | } |
60 | ||
61 | /** | |
62 | * Validate property value.<p> | |
63 | * | |
64 | * @param object The object. | |
65 | * @param property The property. | |
66 | * @param value The value. | |
67 | * @throws PropertyNotFoundException If property does not exist. | |
68 | * @throws ValidationException If invalid. | |
69 | */ | |
70 | public void validate(Object object, String property, Object value) | |
71 | throws PropertyNotFoundException, ValidationException { | |
72 | 27 | PropertyFilter propertyFilter = getFilter().getPropertyFilter(property); |
73 | 27 | checkRequired(propertyFilter, value); |
74 | 25 | checkExtrema(propertyFilter, value); |
75 | 21 | checkLength(propertyFilter, value); |
76 | 17 | checkOptions(propertyFilter, value); |
77 | 16 | } |
78 | ||
79 | /** | |
80 | * Check required fields. | |
81 | * | |
82 | * @param property The property checked. | |
83 | * @param value The value checked. | |
84 | * @throws ValidationException If required and null (or empty string). | |
85 | */ | |
86 | private static void checkRequired(PropertyFilter property, Object value) | |
87 | throws ValidationException { | |
88 | 27 | Boolean required = |
89 | (Boolean) property.getAttribute(BeanFilter.ATTRIBUTE_REQUIRED); | |
90 | 27 | if ((required == null) || required.booleanValue()) { |
91 | 27 | if (value == null) { |
92 | 1 | throw requiredException(property); |
93 | 26 | } else if (property.getType().equals(String.class)) { |
94 | 10 | if (String.valueOf(value).equals(EMPTY_STRING)) { |
95 | 1 | throw requiredException(property); |
96 | } | |
97 | } | |
98 | } | |
99 | 25 | } |
100 | ||
101 | /** | |
102 | * Create exception for required failures. | |
103 | * | |
104 | * @param prop The property checked. | |
105 | * @return The error. | |
106 | */ | |
107 | private static ValidationException requiredException(PropertyFilter prop) { | |
108 | 2 | String label = (String) prop.getAttribute(BeanFilter.ATTRIBUTE_LABEL); |
109 | 2 | ValidationException ex = |
110 | new ValidationException( | |
111 | ValidationException.MESSAGE_REQUIRED_FIELD, | |
112 | new Object[] { label }); | |
113 | 2 | return ex; |
114 | } | |
115 | ||
116 | /** | |
117 | * Check max/min for value. | |
118 | * | |
119 | * @param property The property checked. | |
120 | * @param value The value checked. | |
121 | * @throws ValidationException If out of range. | |
122 | */ | |
123 | private static void checkExtrema(PropertyFilter property, Object value) | |
124 | throws ValidationException { | |
125 | 25 | if (value instanceof Comparable) { |
126 | 24 | Comparable number = (Comparable) value; |
127 | 24 | Comparable min = |
128 | (Comparable) property.getAttribute(BeanFilter.ATTRIBUTE_MIN); | |
129 | 24 | if ((min != null) && (number.compareTo(min) < 0)) { |
130 | 2 | throw extremaException(property); |
131 | } | |
132 | 22 | Comparable max = |
133 | (Comparable) property.getAttribute(BeanFilter.ATTRIBUTE_MAX); | |
134 | 22 | if ((max != null) && (number.compareTo(max) > 0)) { |
135 | 2 | throw extremaException(property); |
136 | } | |
137 | } | |
138 | 21 | } |
139 | ||
140 | /** | |
141 | * Create exception for max/min failures. | |
142 | * | |
143 | * @param property The property checked. | |
144 | * @return The error. | |
145 | */ | |
146 | private static ValidationException extremaException(PropertyFilter property) { | |
147 | 4 | Object min = property.getAttribute(BeanFilter.ATTRIBUTE_MIN); |
148 | 4 | Object max = property.getAttribute(BeanFilter.ATTRIBUTE_MAX); |
149 | 4 | String label = (String) property.getAttribute(BeanFilter.ATTRIBUTE_LABEL); |
150 | 4 | if (min == null) { |
151 | 2 | return new ValidationException( |
152 | ValidationException.MESSAGE_FAILED_MAX, | |
153 | new Object[] { label, max }); | |
154 | } | |
155 | 2 | if (max == null) { |
156 | 1 | return new ValidationException( |
157 | ValidationException.MESSAGE_FAILED_MIN, | |
158 | new Object[] { label, min }); | |
159 | } | |
160 | 1 | return new ValidationException( |
161 | ValidationException.MESSAGE_FAILED_MIN_AND_MAX, | |
162 | new Object[] { label, min, max }); | |
163 | } | |
164 | ||
165 | /** | |
166 | * Check max/min length for value. | |
167 | * | |
168 | * @param property The property checked. | |
169 | * @param value The value checked. | |
170 | * @throws ValidationException If out of range. | |
171 | */ | |
172 | private static void checkLength(PropertyFilter property, Object value) | |
173 | throws ValidationException { | |
174 | 21 | if (value instanceof String) { |
175 | 9 | String string = (String) value; |
176 | 9 | Integer minlength = |
177 | (Integer) property.getAttribute(BeanFilter.ATTRIBUTE_MINLENGTH); | |
178 | 9 | if ((minlength != null) && (string.length()) < minlength.intValue()) { |
179 | 2 | throw lengthException(property); |
180 | } | |
181 | 7 | Integer maxlength = |
182 | (Integer) property.getAttribute(BeanFilter.ATTRIBUTE_MAXLENGTH); | |
183 | 7 | if ((maxlength != null) && (string.length()) > maxlength.intValue()) { |
184 | 2 | throw lengthException(property); |
185 | } | |
186 | } | |
187 | 17 | } |
188 | ||
189 | /** | |
190 | * Create exception for max/min length failures. | |
191 | * | |
192 | * @param property The property checked. | |
193 | * @return The error. | |
194 | */ | |
195 | private static ValidationException lengthException(PropertyFilter property) { | |
196 | 4 | Object minlength = property.getAttribute(BeanFilter.ATTRIBUTE_MINLENGTH); |
197 | 4 | Object maxlength = property.getAttribute(BeanFilter.ATTRIBUTE_MAXLENGTH); |
198 | 4 | String label = (String) property.getAttribute(BeanFilter.ATTRIBUTE_LABEL); |
199 | 4 | if (minlength == null) { |
200 | 2 | return new ValidationException( |
201 | ValidationException.MESSAGE_FAILED_MAXLENGTH, | |
202 | new Object[] { label, maxlength }); | |
203 | } | |
204 | 2 | if (maxlength == null) { |
205 | 1 | return new ValidationException( |
206 | ValidationException.MESSAGE_FAILED_MINLENGTH, | |
207 | new Object[] { label, minlength }); | |
208 | } | |
209 | 1 | return new ValidationException( |
210 | ValidationException.MESSAGE_FAILED_MIN_AND_MAXLENGTH, | |
211 | new Object[] { label, minlength, maxlength }); | |
212 | } | |
213 | ||
214 | /** | |
215 | * Check that value is in the options list. | |
216 | * | |
217 | * @param property The property checked. | |
218 | * @param value The value checked. | |
219 | * @throws ValidationException If not in list. | |
220 | */ | |
221 | private static void checkOptions(PropertyFilter property, Object value) | |
222 | throws ValidationException { | |
223 | 17 | Map options = (Map) property.getAttribute(BeanFilter.ATTRIBUTE_OPTIONS); |
224 | 17 | if ((options != null) && !options.keySet().contains(value)) { |
225 | 1 | String label = (String) property.getAttribute(BeanFilter.ATTRIBUTE_LABEL); |
226 | 1 | throw new ValidationException( |
227 | ValidationException.MESSAGE_INVALID_OPTION, | |
228 | new Object[] { value, label }); | |
229 | } | |
230 | 16 | } |
231 | ||
232 | /** Object used for synchronization locks on bean filter creation. */ | |
233 | 2 | private final Object lock = new Object(); |
234 | ||
235 | /** | |
236 | * Lazy-load bean filter. This lazy-loading is used because validators may | |
237 | * be used by the BeanFilter, so that the BeanFilter for a given validator | |
238 | * may not be properly initialized when the Validator is constructed. | |
239 | * | |
240 | * @return The filter. | |
241 | * @throws InitializationException If filter cannot be initialized. | |
242 | */ | |
243 | private BeanFilter getFilter() throws InitializationException { | |
244 | 27 | if (this.filter == null) { |
245 | 2 | synchronized (lock) { |
246 | 2 | this.filter = BeanFilter.findFilter(getBeanClass()); |
247 | 2 | } |
248 | } | |
249 | 27 | return filter; |
250 | } | |
251 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |