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 */ 017package org.apache.commons.validator.routines; 018 019import java.io.Serializable; 020 021import org.apache.commons.validator.routines.checkdigit.CheckDigit; 022 023/** 024 * Generic <b>Code Validation</b> providing format, minimum/maximum 025 * length and {@link CheckDigit} validations. 026 * <p> 027 * Performs the following validations on a code: 028 * <ul> 029 * <li>Check the <i>format</i> of the code using a <i>regular expression.</i> (if specified)</li> 030 * <li>Check the <i>minimum</i> and <i>maximum</i> length (if specified) of the <i>parsed</i> code 031 * (i.e. parsed by the <i>regular expression</i>).</li> 032 * <li>Performs {@link CheckDigit} validation on the parsed code (if specified).</li> 033 * </ul> 034 * <p> 035 * Configure the validator with the appropriate regular expression, minimum/maximum length 036 * and {@link CheckDigit} validator and then call one of the two validation 037 * methods provided:</p> 038 * <ul> 039 * <li><code>boolean isValid(code)</code></li> 040 * <li><code>String validate(code)</code></li> 041 * </ul> 042 * <p> 043 * Codes often include <i>format</i> characters - such as hyphens - to make them 044 * more easily human readable. These can be removed prior to length and check digit 045 * validation by specifying them as a <i>non-capturing</i> group in the regular 046 * expression (i.e. use the <code>(?: )</code> notation). 047 * 048 * @version $Revision: 1227719 $ $Date: 2012-01-05 12:45:51 -0500 (Thu, 05 Jan 2012) $ 049 * @since Validator 1.4 050 */ 051public final class CodeValidator implements Serializable { 052 053 private static final long serialVersionUID = 446960910870938233L; 054 055 private final RegexValidator regexValidator; 056 private final int minLength; 057 private final int maxLength; 058 private final CheckDigit checkdigit; 059 060 /** 061 * Construct a code validator with a specified regular 062 * expression and {@link CheckDigit}. 063 * 064 * @param regex The format regular expression 065 * @param checkdigit The check digit validation routine 066 */ 067 public CodeValidator(String regex, CheckDigit checkdigit) { 068 this(regex, -1, -1, checkdigit); 069 } 070 071 /** 072 * Construct a code validator with a specified regular 073 * expression, length and {@link CheckDigit}. 074 * 075 * @param regex The format regular expression. 076 * @param length The length of the code 077 * (sets the mimimum/maximum to the same) 078 * @param checkdigit The check digit validation routine 079 */ 080 public CodeValidator(String regex, int length, CheckDigit checkdigit) { 081 this(regex, length, length, checkdigit); 082 } 083 084 /** 085 * Construct a code validator with a specified regular 086 * expression, minimum/maximum length and {@link CheckDigit} validation. 087 * 088 * @param regex The regular expression validator 089 * @param minLength The minimum length of the code 090 * @param maxLength The maximum length of the code 091 * @param checkdigit The check digit validation routine 092 */ 093 public CodeValidator(String regex, int minLength, int maxLength, 094 CheckDigit checkdigit) { 095 if (regex != null && regex.length() > 0) { 096 this.regexValidator = new RegexValidator(regex); 097 } else { 098 this.regexValidator = null; 099 } 100 this.minLength = minLength; 101 this.maxLength = maxLength; 102 this.checkdigit = checkdigit; 103 } 104 105 /** 106 * Construct a code validator with a specified regular expression, 107 * validator and {@link CheckDigit} validation. 108 * 109 * @param regexValidator The format regular expression validator 110 * @param checkdigit The check digit validation routine. 111 */ 112 public CodeValidator(RegexValidator regexValidator, CheckDigit checkdigit) { 113 this(regexValidator, -1, -1, checkdigit); 114 } 115 116 /** 117 * Construct a code validator with a specified regular expression, 118 * validator, length and {@link CheckDigit} validation. 119 * 120 * @param regexValidator The format regular expression validator 121 * @param length The length of the code 122 * (sets the mimimum/maximum to the same value) 123 * @param checkdigit The check digit validation routine 124 */ 125 public CodeValidator(RegexValidator regexValidator, int length, CheckDigit checkdigit) { 126 this(regexValidator, length, length, checkdigit); 127 } 128 129 /** 130 * Construct a code validator with a specified regular expression 131 * validator, minimum/maximum length and {@link CheckDigit} validation. 132 * 133 * @param regexValidator The format regular expression validator 134 * @param minLength The minimum length of the code 135 * @param maxLength The maximum length of the code 136 * @param checkdigit The check digit validation routine 137 */ 138 public CodeValidator(RegexValidator regexValidator, int minLength, int maxLength, 139 CheckDigit checkdigit) { 140 this.regexValidator = regexValidator; 141 this.minLength = minLength; 142 this.maxLength = maxLength; 143 this.checkdigit = checkdigit; 144 } 145 146 /** 147 * Return the check digit validation routine. 148 * <p> 149 * <b>N.B.</b> Optional, if not set no Check Digit 150 * validation will be performed on the code. 151 * 152 * @return The check digit validation routine 153 */ 154 public CheckDigit getCheckDigit() { 155 return checkdigit; 156 } 157 158 /** 159 * Return the minimum length of the code. 160 * <p> 161 * <b>N.B.</b> Optional, if less than zero the 162 * minimum length will not be checked. 163 * 164 * @return The minimum length of the code or 165 * <code>-1</code> if the code has no minimum length 166 */ 167 public int getMinLength() { 168 return minLength; 169 } 170 171 /** 172 * Return the maximum length of the code. 173 * <p> 174 * <b>N.B.</b> Optional, if less than zero the 175 * maximum length will not be checked. 176 * 177 * @return The maximum length of the code or 178 * <code>-1</code> if the code has no maximum length 179 */ 180 public int getMaxLength() { 181 return maxLength; 182 } 183 184 /** 185 * Return the <i>regular expression</i> validator. 186 * <p> 187 * <b>N.B.</b> Optional, if not set no regular 188 * expression validation will be performed on the code. 189 * 190 * @return The regular expression validator 191 */ 192 public RegexValidator getRegexValidator() { 193 return regexValidator; 194 } 195 196 /** 197 * Validate the code returning either <code>true</code> 198 * or <code>false</code>. 199 * 200 * @param input The code to validate 201 * @return <code>true</code> if valid, otherwise 202 * <code>false</code> 203 */ 204 public boolean isValid(String input) { 205 return (validate(input) != null); 206 } 207 208 /** 209 * Validate the code returning either the valid code or 210 * <code>null</code> if invalid. 211 * 212 * @param input The code to validate 213 * @return The code if valid, otherwise <code>null</code> 214 * if invalid 215 */ 216 public Object validate(String input) { 217 218 if (input == null) { 219 return null; 220 } 221 222 String code = input.trim(); 223 if (code.length() == 0) { 224 return null; 225 } 226 227 // validate/reformat using regular expression 228 if (regexValidator != null) { 229 code = regexValidator.validate(code); 230 if (code == null) { 231 return null; 232 } 233 } 234 235 // check the length 236 if ((minLength >= 0 && code.length() < minLength) || 237 (maxLength >= 0 && code.length() > maxLength)) { 238 return null; 239 } 240 241 // validate the check digit 242 if (checkdigit != null && !checkdigit.isValid(code)) { 243 return null; 244 } 245 246 return code; 247 248 } 249 250}