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 * https://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 */ 017package org.apache.commons.validator.routines; 018 019import java.io.Serializable; 020import java.text.Format; 021import java.text.ParsePosition; 022import java.util.Locale; 023 024/** 025 * <p>Abstract class for <em>Format</em> based Validation.</p> 026 * 027 * <p>This is a <em>base</em> class for building Date and Number 028 * Validators using format parsing.</p> 029 * 030 * @since 1.3.0 031 */ 032public abstract class AbstractFormatValidator implements Serializable { 033 034 private static final long serialVersionUID = -4690687565200568258L; 035 036 /** 037 * Whether to use strict format. 038 */ 039 private final boolean strict; 040 041 /** 042 * Constructs an instance with the specified strict setting. 043 * 044 * @param strict {@code true} if strict 045 * {@code Format} parsing should be used. 046 */ 047 public AbstractFormatValidator(final boolean strict) { 048 this.strict = strict; 049 } 050 051 /** 052 * <p>Format an object into a {@link String} using 053 * the default Locale.</p> 054 * 055 * @param value The value validation is being performed on. 056 * @return The value formatted as a {@link String}. 057 */ 058 public String format(final Object value) { 059 return format(value, (String) null, (Locale) null); 060 } 061 062 /** 063 * <p>Format a value with the specified {@code Format}.</p> 064 * 065 * @param value The value to be formatted. 066 * @param formatter The Format to use. 067 * @return The formatted value. 068 */ 069 protected String format(final Object value, final Format formatter) { 070 return formatter.format(value); 071 } 072 073 /** 074 * <p>Format an object into a {@link String} using 075 * the specified Locale.</p> 076 * 077 * @param value The value validation is being performed on. 078 * @param locale The locale to use for the Format. 079 * @return The value formatted as a {@link String}. 080 */ 081 public String format(final Object value, final Locale locale) { 082 return format(value, (String) null, locale); 083 } 084 085 /** 086 * <p>Format an object into a {@link String} using 087 * the specified pattern.</p> 088 * 089 * @param value The value validation is being performed on. 090 * @param pattern The pattern used to format the value. 091 * @return The value formatted as a {@link String}. 092 */ 093 public String format(final Object value, final String pattern) { 094 return format(value, pattern, (Locale) null); 095 } 096 097 /** 098 * <p>Format an object using the specified pattern and/or 099 * {@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}