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    }