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    *      https://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  
18  package org.apache.commons.validator.routines;
19  
20  import java.io.Serializable;
21  import java.text.Format;
22  import java.text.ParsePosition;
23  import java.util.Locale;
24  
25  /**
26   * Abstracts class for <em>Format</em> based Validation.
27   * <p>
28   * This is a <em>base</em> class for building Date and Number Validators using format parsing.
29   * </p>
30   *
31   * @since 1.3.0
32   */
33  public abstract class AbstractFormatValidator implements Serializable {
34  
35      private static final long serialVersionUID = -4690687565200568258L;
36  
37      /**
38       * Whether to use strict format.
39       */
40      private final boolean strict;
41  
42      /**
43       * Constructs an instance with the specified strict setting.
44       *
45       * @param strict {@code true} if strict {@code Format} parsing should be used.
46       */
47      public AbstractFormatValidator(final boolean strict) {
48          this.strict = strict;
49      }
50  
51      /**
52       * Formats an object into a {@link String} using the default Locale.
53       *
54       * @param value The value validation is being performed on.
55       * @return The value formatted as a {@link String}.
56       */
57      public String format(final Object value) {
58          return format(value, (String) null, (Locale) null);
59      }
60  
61      /**
62       * Formats a value with the specified {@code Format}.
63       *
64       * @param value     The value to be formatted.
65       * @param formatter The Format to use.
66       * @return The formatted value.
67       */
68      protected String format(final Object value, final Format formatter) {
69          return formatter.format(value);
70      }
71  
72      /**
73       * Formats an object into a {@link String} using the specified Locale.
74       *
75       * @param value  The value validation is being performed on.
76       * @param locale The locale to use for the Format.
77       * @return The value formatted as a {@link String}.
78       */
79      public String format(final Object value, final Locale locale) {
80          return format(value, (String) null, locale);
81      }
82  
83      /**
84       * Formats an object into a {@link String} using the specified pattern.
85       *
86       * @param value   The value validation is being performed on.
87       * @param pattern The pattern used to format the value.
88       * @return The value formatted as a {@link String}.
89       */
90      public String format(final Object value, final String pattern) {
91          return format(value, pattern, (Locale) null);
92      }
93  
94      /**
95       * Formats an object using the specified pattern and/or {@link Locale}.
96       *
97       * @param value   The value validation is being performed on.
98       * @param pattern The pattern used to format the value.
99       * @param locale  The locale to use for the Format.
100      * @return The value formatted as a {@link String}.
101      */
102     public String format(final Object value, final String pattern, final Locale locale) {
103         return format(value, getFormat(pattern, locale));
104     }
105 
106     /**
107      * get a {@code Format} for the specified <em>pattern</em> and/or {@link Locale}.
108      *
109      * @param pattern The pattern used to validate the value against or {@code null} to use the default for the {@link Locale}.
110      * @param locale  The locale to use for the currency format, system default if null.
111      * @return The {@code NumberFormat} to created.
112      */
113     protected abstract Format getFormat(String pattern, Locale locale);
114 
115     /**
116      * Tests whether validated values should adhere strictly to the {@code Format} used.
117      * <p>
118      * Typically implementations of {@code Format} ignore invalid characters at the end of the value and just stop parsing. For example parsing a date value of
119      * {@code 01/01/20x0} using a pattern of {@code dd/MM/yyyy} will result in a year of {@code 20} if {@code strict} is set to {@code false}, whereas setting
120      * {@code strict} to {@code true} will cause this value to fail validation.
121      * </p>
122      *
123      * @return {@code true} if strict {@code Format} parsing should be used.
124      */
125     public boolean isStrict() {
126         return strict;
127     }
128 
129     /**
130      * Validates using the default {@link Locale}.
131      *
132      * @param value The value validation is being performed on.
133      * @return {@code true} if the value is valid.
134      */
135     public boolean isValid(final String value) {
136         return isValid(value, (String) null, (Locale) null);
137     }
138 
139     /**
140      * Validates using the specified {@link Locale}.
141      *
142      * @param value  The value validation is being performed on.
143      * @param locale The locale to use for the Format, defaults to the default
144      * @return {@code true} if the value is valid.
145      */
146     public boolean isValid(final String value, final Locale locale) {
147         return isValid(value, (String) null, locale);
148     }
149 
150     /**
151      * Validates using the specified <em>pattern</em>.
152      *
153      * @param value   The value validation is being performed on.
154      * @param pattern The pattern used to validate the value against.
155      * @return {@code true} if the value is valid.
156      */
157     public boolean isValid(final String value, final String pattern) {
158         return isValid(value, pattern, (Locale) null);
159     }
160 
161     /**
162      * Validates using the specified pattern and/or {@link Locale}.
163      *
164      * @param value   The value validation is being performed on.
165      * @param pattern The pattern used to format the value.
166      * @param locale  The locale to use for the Format, defaults to the default
167      * @return {@code true} if the value is valid.
168      */
169     public abstract boolean isValid(String value, String pattern, Locale locale);
170 
171     /**
172      * Parses the value with the specified {@code Format}.
173      *
174      * @param value     The value to be parsed.
175      * @param formatter The Format to parse the value with.
176      * @return The parsed value if valid or {@code null} if invalid.
177      */
178     protected Object parse(final String value, final Format formatter) {
179         final ParsePosition pos = new ParsePosition(0);
180         Object parsedValue = formatter.parseObject(value, pos);
181         if (pos.getErrorIndex() > -1 || isStrict() && pos.getIndex() < value.length()) {
182             return null;
183         }
184         if (parsedValue != null) {
185             parsedValue = processParsedValue(parsedValue, formatter);
186         }
187         return parsedValue;
188     }
189 
190     /**
191      * Processes the parsed value, performing any further validation and type conversion required.
192      *
193      * @param value     The parsed object created.
194      * @param formatter The Format used to parse the value with.
195      * @return The parsed value converted to the appropriate type if valid or {@code null} if invalid.
196      */
197     protected abstract Object processParsedValue(Object value, Format formatter);
198 }