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 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 <em>Format</em> based Validation.</p> 26 * 27 * <p>This is a <em>base</em> 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} 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 {@link String} using 53 * the default Locale.</p> 54 * 55 * @param value The value validation is being performed on. 56 * @return The value formatted as a {@link String}. 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}.</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 {@link String} 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 {@link String}. 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 {@link String} 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 {@link String}. 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 * {@link Locale}. 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 {@link String}. 105 */ 106 public String format(final Object value, final String pattern, final Locale locale) { 107 return format(value, getFormat(pattern, locale)); 108 } 109 110 /** 111 * <p>Returns a {@code Format} for the specified <em>pattern</em> 112 * and/or {@link Locale}.</p> 113 * 114 * @param pattern The pattern used to validate the value against or 115 * {@code null} to use the default for the {@link Locale}. 116 * @param locale The locale to use for the currency format, system default if null. 117 * @return The {@code NumberFormat} to created. 118 */ 119 protected abstract Format getFormat(String pattern, Locale locale); 120 121 /** 122 * <p>Indicates whether validated values should adhere 123 * strictly to the {@code Format} used.</p> 124 * 125 * <p>Typically implementations of {@code Format} 126 * ignore invalid characters at the end of the value 127 * and just stop parsing. For example parsing a date 128 * value of {@code 01/01/20x0} using a pattern 129 * of {@code dd/MM/yyyy} will result in a year 130 * of {@code 20} if {@code strict} is set 131 * to {@code false}, whereas setting {@code strict} 132 * to {@code true} will cause this value to fail 133 * validation.</p> 134 * 135 * @return {@code true} if strict {@code Format} 136 * parsing should be used. 137 */ 138 public boolean isStrict() { 139 return strict; 140 } 141 142 /** 143 * <p>Validate using the default {@link Locale}. 144 * 145 * @param value The value validation is being performed on. 146 * @return {@code true} if the value is valid. 147 */ 148 public boolean isValid(final String value) { 149 return isValid(value, (String) null, (Locale) null); 150 } 151 152 /** 153 * <p>Validate using the specified {@link Locale}. 154 * 155 * @param value The value validation is being performed on. 156 * @param locale The locale to use for the Format, defaults to the default 157 * @return {@code true} if the value is valid. 158 */ 159 public boolean isValid(final String value, final Locale locale) { 160 return isValid(value, (String) null, locale); 161 } 162 163 /** 164 * <p>Validate using the specified <em>pattern</em>. 165 * 166 * @param value The value validation is being performed on. 167 * @param pattern The pattern used to validate the value against. 168 * @return {@code true} if the value is valid. 169 */ 170 public boolean isValid(final String value, final String pattern) { 171 return isValid(value, pattern, (Locale) null); 172 } 173 174 /** 175 * <p>Validate using the specified pattern and/or {@link Locale}. 176 * 177 * @param value The value validation is being performed on. 178 * @param pattern The pattern used to format the value. 179 * @param locale The locale to use for the Format, defaults to the default 180 * @return {@code true} if the value is valid. 181 */ 182 public abstract boolean isValid(String value, String pattern, Locale locale); 183 184 /** 185 * <p>Parse the value with the specified {@code Format}.</p> 186 * 187 * @param value The value to be parsed. 188 * @param formatter The Format to parse the value with. 189 * @return The parsed value if valid or {@code null} if invalid. 190 */ 191 protected Object parse(final String value, final Format formatter) { 192 final ParsePosition pos = new ParsePosition(0); 193 Object parsedValue = formatter.parseObject(value, pos); 194 if (pos.getErrorIndex() > -1 || isStrict() && pos.getIndex() < value.length()) { 195 return null; 196 } 197 if (parsedValue != null) { 198 parsedValue = processParsedValue(parsedValue, formatter); 199 } 200 return parsedValue; 201 202 } 203 204 /** 205 * <p>Process the parsed value, performing any further validation 206 * and type conversion required.</p> 207 * 208 * @param value The parsed object created. 209 * @param formatter The Format used to parse the value with. 210 * @return The parsed value converted to the appropriate type 211 * if valid or {@code null} if invalid. 212 */ 213 protected abstract Object processParsedValue(Object value, Format formatter); 214 215 }