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.io.Serializable;
020
021 import 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: 591497 $ $Date: 2007-11-02 23:25:16 +0100 (Fr, 02. Nov 2007) $
049 * @since Validator 1.4
050 */
051 public final class CodeValidator implements Serializable {
052
053 private final RegexValidator regexValidator;
054 private final int minLength;
055 private final int maxLength;
056 private final CheckDigit checkdigit;
057
058 /**
059 * Construct a code validator with a specified regular
060 * expression and {@link CheckDigit}.
061 *
062 * @param regex The format regular expression
063 * @param checkdigit The check digit validation routine
064 */
065 public CodeValidator(String regex, CheckDigit checkdigit) {
066 this(regex, -1, -1, checkdigit);
067 }
068
069 /**
070 * Construct a code validator with a specified regular
071 * expression, length and {@link CheckDigit}.
072 *
073 * @param regex The format regular expression.
074 * @param length The length of the code
075 * (sets the mimimum/maximum to the same)
076 * @param checkdigit The check digit validation routine
077 */
078 public CodeValidator(String regex, int length, CheckDigit checkdigit) {
079 this(regex, length, length, checkdigit);
080 }
081
082 /**
083 * Construct a code validator with a specified regular
084 * expression, minimum/maximum length and {@link CheckDigit} validation.
085 *
086 * @param regex The regular expression validator
087 * @param minLength The minimum length of the code
088 * @param maxLength The maximum length of the code
089 * @param checkdigit The check digit validation routine
090 */
091 public CodeValidator(String regex, int minLength, int maxLength,
092 CheckDigit checkdigit) {
093 if (regex != null && regex.length() > 0) {
094 this.regexValidator = new RegexValidator(regex);
095 } else {
096 this.regexValidator = null;
097 }
098 this.minLength = minLength;
099 this.maxLength = maxLength;
100 this.checkdigit = checkdigit;
101 }
102
103 /**
104 * Construct a code validator with a specified regular expression,
105 * validator and {@link CheckDigit} validation.
106 *
107 * @param regexValidator The format regular expression validator
108 * @param checkdigit The check digit validation routine.
109 */
110 public CodeValidator(RegexValidator regexValidator, CheckDigit checkdigit) {
111 this(regexValidator, -1, -1, checkdigit);
112 }
113
114 /**
115 * Construct a code validator with a specified regular expression,
116 * validator, length and {@link CheckDigit} validation.
117 *
118 * @param regexValidator The format regular expression validator
119 * @param length The length of the code
120 * (sets the mimimum/maximum to the same value)
121 * @param checkdigit The check digit validation routine
122 */
123 public CodeValidator(RegexValidator regexValidator, int length, CheckDigit checkdigit) {
124 this(regexValidator, length, length, checkdigit);
125 }
126
127 /**
128 * Construct a code validator with a specified regular expression
129 * validator, minimum/maximum length and {@link CheckDigit} validation.
130 *
131 * @param regexValidator The format regular expression validator
132 * @param minLength The minimum length of the code
133 * @param maxLength The maximum length of the code
134 * @param checkdigit The check digit validation routine
135 */
136 public CodeValidator(RegexValidator regexValidator, int minLength, int maxLength,
137 CheckDigit checkdigit) {
138 this.regexValidator = regexValidator;
139 this.minLength = minLength;
140 this.maxLength = maxLength;
141 this.checkdigit = checkdigit;
142 }
143
144 /**
145 * Return the check digit validation routine.
146 * <p>
147 * <b>N.B.</b> Optional, if not set no Check Digit
148 * validation will be performed on the code.
149 *
150 * @return The check digit validation routine
151 */
152 public CheckDigit getCheckDigit() {
153 return checkdigit;
154 }
155
156 /**
157 * Return the minimum length of the code.
158 * <p>
159 * <b>N.B.</b> Optional, if less than zero the
160 * minimum length will not be checked.
161 *
162 * @return The minimum length of the code or
163 * <code>-1</code> if the code has no minimum length
164 */
165 public int getMinLength() {
166 return minLength;
167 }
168
169 /**
170 * Return the maximum length of the code.
171 * <p>
172 * <b>N.B.</b> Optional, if less than zero the
173 * maximum length will not be checked.
174 *
175 * @return The maximum length of the code or
176 * <code>-1</code> if the code has no maximum length
177 */
178 public int getMaxLength() {
179 return maxLength;
180 }
181
182 /**
183 * Return the <i>regular expression</i> validator.
184 * <p>
185 * <b>N.B.</b> Optional, if not set no regular
186 * expression validation will be performed on the code.
187 *
188 * @return The regular expression validator
189 */
190 public RegexValidator getRegexValidator() {
191 return regexValidator;
192 }
193
194 /**
195 * Validate the code returning either <code>true</code>
196 * or <code>false</code>.
197 *
198 * @param input The code to validate
199 * @return <code>true</code> if valid, otherwise
200 * <code>false</code>
201 */
202 public boolean isValid(String input) {
203 return (validate(input) != null);
204 }
205
206 /**
207 * Validate the code returning either the valid code or
208 * <code>null</code> if invalid.
209 *
210 * @param input The code to validate
211 * @return The code if valid, otherwise <code>null</code>
212 * if invalid
213 */
214 public Object validate(String input) {
215
216 String code = (input == null ? null : input.trim());
217 if (code != null && code.length() == 0) {
218 return null;
219 }
220
221 // validate/reformat using regular expression
222 if (regexValidator != null) {
223 code = regexValidator.validate(code);
224 if (code == null) {
225 return null;
226 }
227 }
228
229 // check the length
230 if ((minLength >= 0 && code.length() < minLength) ||
231 (maxLength >= 0 && code.length() > maxLength)) {
232 return null;
233 }
234
235 // validate the check digit
236 if (checkdigit != null && !checkdigit.isValid(code)) {
237 return null;
238 }
239
240 return code;
241
242 }
243
244 }