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 }