View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.validator.routines;
18  
19  import java.io.Serializable;
20  import java.text.Format;
21  import java.text.ParsePosition;
22  import java.util.Locale;
23  
24  /**
25   * <p>Abstract class for <i>Format</i> based Validation.</p>
26   *
27   * <p>This is a <i>base</i> class for building Date and Number
28   *    Validators using format parsing.</p>
29   *
30   * @since 1.3.0
31   */
32  public abstract class AbstractFormatValidator implements Serializable {
33  
34      private static final long serialVersionUID = -4690687565200568258L;
35  
36      /**
37       * Whether to use strict format.
38       */
39      private final boolean strict;
40  
41      /**
42       * Constructs an instance with the specified strict setting.
43       *
44       * @param strict {@code true} if strict
45       *        <code>Format</code> parsing should be used.
46       */
47      public AbstractFormatValidator(final boolean strict) {
48          this.strict = strict;
49      }
50  
51      /**
52       * <p>Format an object into a <code>String</code> using
53       * the default Locale.</p>
54       *
55       * @param value The value validation is being performed on.
56       * @return The value formatted as a <code>String</code>.
57       */
58      public String format(final Object value) {
59          return format(value, (String)null, (Locale)null);
60      }
61  
62      /**
63       * <p>Format a value with the specified <code>Format</code>.</p>
64       *
65       * @param value The value to be formatted.
66       * @param formatter The Format to use.
67       * @return The formatted value.
68       */
69      protected String format(final Object value, final Format formatter) {
70          return formatter.format(value);
71      }
72  
73      /**
74       * <p>Format an object into a <code>String</code> using
75       * the specified Locale.</p>
76       *
77       * @param value The value validation is being performed on.
78       * @param locale The locale to use for the Format.
79       * @return The value formatted as a <code>String</code>.
80       */
81      public String format(final Object value, final Locale locale) {
82          return format(value, (String)null, locale);
83      }
84  
85      /**
86       * <p>Format an object into a <code>String</code> using
87       * the specified pattern.</p>
88       *
89       * @param value The value validation is being performed on.
90       * @param pattern The pattern used to format the value.
91       * @return The value formatted as a <code>String</code>.
92       */
93      public String format(final Object value, final String pattern) {
94          return format(value, pattern, (Locale)null);
95      }
96  
97      /**
98       * <p>Format an object using the specified pattern and/or
99       *    <code>Locale</code>.
100      *
101      * @param value The value validation is being performed on.
102      * @param pattern The pattern used to format the value.
103      * @param locale The locale to use for the Format.
104      * @return The value formatted as a <code>String</code>.
105      */
106     public String format(final Object value, final String pattern, final Locale locale) {
107         final Format formatter = getFormat(pattern, locale);
108         return format(value, formatter);
109     }
110 
111     /**
112      * <p>Returns a <code>Format</code> for the specified <i>pattern</i>
113      *    and/or <code>Locale</code>.</p>
114      *
115      * @param pattern The pattern used to validate the value against or
116      *        <code>null</code> to use the default for the <code>Locale</code>.
117      * @param locale The locale to use for the currency format, system default if null.
118      * @return The <code>NumberFormat</code> to created.
119      */
120     protected abstract Format getFormat(String pattern, Locale locale);
121 
122     /**
123      * <p>Indicates whether validated values should adhere
124      *    strictly to the <code>Format</code> used.</p>
125      *
126      * <p>Typically implementations of <code>Format</code>
127      *    ignore invalid characters at the end of the value
128      *    and just stop parsing. For example parsing a date
129      *    value of <code>01/01/20x0</code> using a pattern
130      *    of <code>dd/MM/yyyy</code> will result in a year
131      *    of <code>20</code> if <code>strict</code> is set
132      *    to {@code false}, whereas setting <code>strict</code>
133      *    to {@code true} will cause this value to fail
134      *    validation.</p>
135      *
136      * @return {@code true} if strict <code>Format</code>
137      *         parsing should be used.
138      */
139     public boolean isStrict() {
140         return strict;
141     }
142 
143     /**
144      * <p>Validate using the default <code>Locale</code>.
145      *
146      * @param value The value validation is being performed on.
147      * @return {@code true} if the value is valid.
148      */
149     public boolean isValid(final String value) {
150         return isValid(value, (String)null, (Locale)null);
151     }
152 
153     /**
154      * <p>Validate using the specified <code>Locale</code>.
155      *
156      * @param value The value validation is being performed on.
157      * @param locale The locale to use for the Format, defaults to the default
158      * @return {@code true} if the value is valid.
159      */
160     public boolean isValid(final String value, final Locale locale) {
161         return isValid(value, (String)null, locale);
162     }
163 
164     /**
165      * <p>Validate using the specified <i>pattern</i>.
166      *
167      * @param value The value validation is being performed on.
168      * @param pattern The pattern used to validate the value against.
169      * @return {@code true} if the value is valid.
170      */
171     public boolean isValid(final String value, final String pattern) {
172         return isValid(value, pattern, (Locale)null);
173     }
174 
175     /**
176      * <p>Validate using the specified pattern and/or <code>Locale</code>.
177      *
178      * @param value The value validation is being performed on.
179      * @param pattern The pattern used to format the value.
180      * @param locale The locale to use for the Format, defaults to the default
181      * @return {@code true} if the value is valid.
182      */
183     public abstract boolean isValid(String value, String pattern, Locale locale);
184 
185     /**
186      * <p>Parse the value with the specified <code>Format</code>.</p>
187      *
188      * @param value The value to be parsed.
189      * @param formatter The Format to parse the value with.
190      * @return The parsed value if valid or <code>null</code> if invalid.
191      */
192     protected Object parse(final String value, final Format formatter) {
193 
194         final ParsePosition pos = new ParsePosition(0);
195         Object parsedValue = formatter.parseObject(value, pos);
196         if (pos.getErrorIndex() > -1) {
197             return null;
198         }
199 
200         if (isStrict() && pos.getIndex() < value.length()) {
201             return null;
202         }
203 
204         if (parsedValue != null) {
205             parsedValue = processParsedValue(parsedValue, formatter);
206         }
207 
208         return parsedValue;
209 
210     }
211 
212     /**
213      * <p>Process the parsed value, performing any further validation
214      *    and type conversion required.</p>
215      *
216      * @param value The parsed object created.
217      * @param formatter The Format used to parse the value with.
218      * @return The parsed value converted to the appropriate type
219      *         if valid or <code>null</code> if invalid.
220      */
221     protected abstract Object processParsedValue(Object value, Format formatter);
222 
223 }