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