001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.validator.routines;
018
019 import java.text.Format;
020 import java.text.ParsePosition;
021 import java.util.Locale;
022 import java.io.Serializable;
023
024 /**
025 * <p>Abstract class for <i>Format</i> based Validation.</p>
026 *
027 * <p>This is a <i>base</i> class for building Date and Number
028 * Validators using format parsing.</p>
029 *
030 * @version $Revision: 594917 $ $Date: 2007-11-14 16:36:40 +0100 (Mi, 14. Nov 2007) $
031 * @since Validator 1.3.0
032 */
033 public abstract class AbstractFormatValidator implements Serializable {
034
035 private final boolean strict;
036
037 /**
038 * Construct an instance with the specified strict setting.
039 *
040 * @param strict <code>true</code> if strict
041 * <code>Format</code> parsing should be used.
042 */
043 public AbstractFormatValidator(boolean strict) {
044 this.strict = strict;
045 }
046
047 /**
048 * <p>Indicates whether validated values should adhere
049 * strictly to the <code>Format</code> used.</p>
050 *
051 * <p>Typically implementations of <code>Format</code>
052 * ignore invalid characters at the end of the value
053 * and just stop parsing. For example parsing a date
054 * value of <code>01/01/20x0</code> using a pattern
055 * of <code>dd/MM/yyyy</code> will result in a year
056 * of <code>20</code> if <code>strict</code> is set
057 * to <code>false</code>, whereas setting <code>strict</code>
058 * to <code>true</code> will cause this value to fail
059 * validation.</p>
060 *
061 * @return <code>true</code> if strict <code>Format</code>
062 * parsing should be used.
063 */
064 public boolean isStrict() {
065 return strict;
066 }
067
068 /**
069 * <p>Validate using the default <code>Locale</code>.
070 *
071 * @param value The value validation is being performed on.
072 * @return <code>true</code> if the value is valid.
073 */
074 public boolean isValid(String value) {
075 return isValid(value, (String)null, (Locale)null);
076 }
077
078 /**
079 * <p>Validate using the specified <i>pattern</i>.
080 *
081 * @param value The value validation is being performed on.
082 * @param pattern The pattern used to validate the value against.
083 * @return <code>true</code> if the value is valid.
084 */
085 public boolean isValid(String value, String pattern) {
086 return isValid(value, pattern, (Locale)null);
087 }
088
089 /**
090 * <p>Validate using the specified <code>Locale</code>.
091 *
092 * @param value The value validation is being performed on.
093 * @param locale The locale to use for the Format, defaults to the default
094 * @return <code>true</code> if the value is valid.
095 */
096 public boolean isValid(String value, Locale locale) {
097 return isValid(value, (String)null, locale);
098 }
099
100 /**
101 * <p>Validate using the specified pattern and/or <code>Locale</code>.
102 *
103 * @param value The value validation is being performed on.
104 * @param pattern The pattern used to format the value.
105 * @param locale The locale to use for the Format, defaults to the default
106 * @return <code>true</code> if the value is valid.
107 */
108 public abstract boolean isValid(String value, String pattern, Locale locale);
109
110 /**
111 * <p>Format an object into a <code>String</code> using
112 * the default Locale.</p>
113 *
114 * @param value The value validation is being performed on.
115 * @return The value formatted as a <code>String</code>.
116 */
117 public String format(Object value) {
118 return format(value, (String)null, (Locale)null);
119 }
120
121 /**
122 * <p>Format an object into a <code>String</code> using
123 * the specified pattern.</p>
124 *
125 * @param value The value validation is being performed on.
126 * @param pattern The pattern used to format the value.
127 * @return The value formatted as a <code>String</code>.
128 */
129 public String format(Object value, String pattern) {
130 return format(value, pattern, (Locale)null);
131 }
132
133 /**
134 * <p>Format an object into a <code>String</code> using
135 * the specified Locale.</p>
136 *
137 * @param value The value validation is being performed on.
138 * @param locale The locale to use for the Format.
139 * @return The value formatted as a <code>String</code>.
140 */
141 public String format(Object value, Locale locale) {
142 return format(value, (String)null, locale);
143 }
144
145 /**
146 * <p>Format an object using the specified pattern and/or
147 * <code>Locale</code>.
148 *
149 * @param value The value validation is being performed on.
150 * @param pattern The pattern used to format the value.
151 * @param locale The locale to use for the Format.
152 * @return The value formatted as a <code>String</code>.
153 */
154 public String format(Object value, String pattern, Locale locale) {
155 Format formatter = getFormat(pattern, locale);
156 return format(value, formatter);
157 }
158
159 /**
160 * <p>Format a value with the specified <code>Format</code>.</p>
161 *
162 * @param value The value to be formatted.
163 * @param formatter The Format to use.
164 * @return The formatted value.
165 */
166 protected String format(Object value, Format formatter) {
167 return formatter.format(value);
168 }
169
170 /**
171 * <p>Parse the value with the specified <code>Format</code>.</p>
172 *
173 * @param value The value to be parsed.
174 * @param formatter The Format to parse the value with.
175 * @return The parsed value if valid or <code>null</code> if invalid.
176 */
177 protected Object parse(String value, Format formatter) {
178
179 ParsePosition pos = new ParsePosition(0);
180 Object parsedValue = formatter.parseObject(value, pos);
181 if (pos.getErrorIndex() > -1) {
182 return null;
183 }
184
185 if (isStrict() && pos.getIndex() < value.length()) {
186 return null;
187 }
188
189 if (parsedValue != null) {
190 parsedValue = processParsedValue(parsedValue, formatter);
191 }
192
193 return parsedValue;
194
195 }
196
197 /**
198 * <p>Process the parsed value, performing any further validation
199 * and type conversion required.</p>
200 *
201 * @param value The parsed object created.
202 * @param formatter The Format used to parse the value with.
203 * @return The parsed value converted to the appropriate type
204 * if valid or <code>null</code> if invalid.
205 */
206 protected abstract Object processParsedValue(Object value, Format formatter);
207
208 /**
209 * <p>Returns a <code>Format</code> for the specified <i>pattern</i>
210 * and/or <code>Locale</code>.</p>
211 *
212 * @param pattern The pattern used to validate the value against or
213 * <code>null</code> to use the default for the <code>Locale</code>.
214 * @param locale The locale to use for the currency format, system default if null.
215 * @return The <code>NumberFormat</code> to created.
216 */
217 protected abstract Format getFormat(String pattern, Locale locale);
218
219 }