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 import java.util.regex.Pattern; 021 import java.util.regex.Matcher; 022 023 /** 024 * <b>Regular Expression</b> validation (using JDK 1.4+ regex support). 025 * <p> 026 * Construct the validator either for a single regular expression or a set (array) of 027 * regular expressions. By default validation is <i>case sensitive</i> but constructors 028 * are provided to allow <i>case in-sensitive</i> validation. For example to create 029 * a validator which does <i>case in-sensitive</i> validation for a set of regular 030 * expressions: 031 * <pre> 032 * String[] regexs = new String[] {...}; 033 * RegexValidator validator = new RegexValidator(regexs, false); 034 * </pre> 035 * <p> 036 * <ul> 037 * <li>Validate <code>true</code> or <code>false</code>:</li> 038 * <ul> 039 * <li><code>boolean valid = validator.isValid(value);</code></li> 040 * </ul> 041 * <li>Validate returning an aggregated String of the matched groups:</li> 042 * <ul> 043 * <li><code>String result = validator.validate(value);</code></li> 044 * </ul> 045 * <li>Validate returning the matched groups:</li> 046 * <ul> 047 * <li><code>String[] result = validator.match(value);</code></li> 048 * </ul> 049 * </ul> 050 * <p> 051 * Cached instances pre-compile and re-use {@link Pattern}(s) - which according 052 * to the {@link Pattern} API are safe to use in a multi-threaded environment. 053 * 054 * @version $Revision: 595023 $ $Date: 2007-11-14 20:49:23 +0100 (Mi, 14. Nov 2007) $ 055 * @since Validator 1.4 056 */ 057 public class RegexValidator implements Serializable { 058 059 private final Pattern[] patterns; 060 061 /** 062 * Construct a <i>case sensitive</i> validator for a single 063 * regular expression. 064 * 065 * @param regex The regular expression this validator will 066 * validate against 067 */ 068 public RegexValidator(String regex) { 069 this(regex, true); 070 } 071 072 /** 073 * Construct a validator for a single regular expression 074 * with the specified case sensitivity. 075 * 076 * @param regex The regular expression this validator will 077 * validate against 078 * @param caseSensitive when <code>true</code> matching is <i>case 079 * sensitive</i>, otherwise matching is <i>case in-sensitive</i> 080 */ 081 public RegexValidator(String regex, boolean caseSensitive) { 082 this(new String[] {regex}, caseSensitive); 083 } 084 085 /** 086 * Construct a <i>case sensitive</i> validator that matches any one 087 * of the set of regular expressions. 088 * 089 * @param regexs The set of regular expressions this validator will 090 * validate against 091 */ 092 public RegexValidator(String[] regexs) { 093 this(regexs, true); 094 } 095 096 /** 097 * Construct a validator that matches any one of the set of regular 098 * expressions with the specified case sensitivity. 099 * 100 * @param regexs The set of regular expressions this validator will 101 * validate against 102 * @param caseSensitive when <code>true</code> matching is <i>case 103 * sensitive</i>, otherwise matching is <i>case in-sensitive</i> 104 */ 105 public RegexValidator(String[] regexs, boolean caseSensitive) { 106 if (regexs == null || regexs.length == 0) { 107 throw new IllegalArgumentException("Regular expressions are missing"); 108 } 109 patterns = new Pattern[regexs.length]; 110 int flags = (caseSensitive ? 0: Pattern.CASE_INSENSITIVE); 111 for (int i = 0; i < regexs.length; i++) { 112 if (regexs[i] == null || regexs[i].length() == 0) { 113 throw new IllegalArgumentException("Regular expression[" + i + "] is missing"); 114 } 115 patterns[i] = Pattern.compile(regexs[i], flags); 116 } 117 } 118 119 /** 120 * Validate a value against the set of regular expressions. 121 * 122 * @param value The value to validate. 123 * @return <code>true</code> if the value is valid 124 * otherwise <code>false</code>. 125 */ 126 public boolean isValid(String value) { 127 if (value == null) { 128 return false; 129 } 130 for (int i = 0; i < patterns.length; i++) { 131 if (patterns[i].matcher(value).matches()) { 132 return true; 133 } 134 } 135 return false; 136 } 137 138 /** 139 * Validate a value against the set of regular expressions 140 * returning the array of matched groups. 141 * 142 * @param value The value to validate. 143 * @return String array of the <i>groups</i> matched if 144 * valid or <code>null</code> if invalid 145 */ 146 public String[] match(String value) { 147 if (value == null) { 148 return null; 149 } 150 for (int i = 0; i < patterns.length; i++) { 151 Matcher matcher = patterns[i].matcher(value); 152 if (matcher.matches()) { 153 int count = matcher.groupCount(); 154 String[] groups = new String[count]; 155 for (int j = 0; j < count; j++) { 156 groups[j] = matcher.group(j+1); 157 } 158 return groups; 159 } 160 } 161 return null; 162 } 163 164 165 /** 166 * Validate a value against the set of regular expressions 167 * returning a String value of the aggregated groups. 168 * 169 * @param value The value to validate. 170 * @return Aggregated String value comprised of the 171 * <i>groups</i> matched if valid or <code>null</code> if invalid 172 */ 173 public String validate(String value) { 174 if (value == null) { 175 return null; 176 } 177 for (int i = 0; i < patterns.length; i++) { 178 Matcher matcher = patterns[i].matcher(value); 179 if (matcher.matches()) { 180 int count = matcher.groupCount(); 181 if (count == 1) { 182 return matcher.group(1); 183 } 184 StringBuffer buffer = new StringBuffer(); 185 for (int j = 0; j < count; j++) { 186 String component = matcher.group(j+1); 187 if (component != null) { 188 buffer.append(component); 189 } 190 } 191 return buffer.toString(); 192 } 193 } 194 return null; 195 } 196 197 /** 198 * Provide a String representation of this validator. 199 * @return A String representation of this validator 200 */ 201 public String toString() { 202 StringBuffer buffer = new StringBuffer(); 203 buffer.append("RegexValidator{"); 204 for (int i = 0; i < patterns.length; i++) { 205 if (i > 0) { 206 buffer.append(","); 207 } 208 buffer.append(patterns[i].pattern()); 209 } 210 buffer.append("}"); 211 return buffer.toString(); 212 } 213 214 }