View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.validator.routines;
18  
19  import java.io.Serializable;
20  import java.util.regex.Pattern;
21  import java.util.regex.Matcher;
22  
23  /**
24   * <b>Regular Expression</b> validation (using JDK 1.4+ regex support).
25   * <p>
26   * Construct the validator either for a single regular expression or a set (array) of
27   * regular expressions. By default validation is <i>case sensitive</i> but constructors
28   * are provided to allow  <i>case in-sensitive</i> validation. For example to create
29   * a validator which does <i>case in-sensitive</i> validation for a set of regular
30   * expressions:
31   * <pre>
32   *         String[] regexs = new String[] {...};
33   *         RegexValidator validator = new RegexValidator(regexs, false);
34   * </pre>
35   * <p>
36   * <ul>
37   *   <li>Validate <code>true</code> or <code>false</code>:</li>
38   *   <ul>
39   *     <li><code>boolean valid = validator.isValid(value);</code></li>
40   *   </ul>
41   *   <li>Validate returning an aggregated String of the matched groups:</li>
42   *   <ul>
43   *     <li><code>String result = validator.validate(value);</code></li>
44   *   </ul>
45   *   <li>Validate returning the matched groups:</li>
46   *   <ul>
47   *     <li><code>String[] result = validator.match(value);</code></li>
48   *   </ul>
49   * </ul>
50   * <p>
51   * Cached instances pre-compile and re-use {@link Pattern}(s) - which according
52   * to the {@link Pattern} API are safe to use in a multi-threaded environment.
53   *
54   * @version $Revision: 1227719 $ $Date: 2012-01-05 18:45:51 +0100 (Do, 05 Jan 2012) $
55   * @since Validator 1.4
56   */
57  public class RegexValidator implements Serializable {
58  
59      private static final long serialVersionUID = -8832409930574867162L;
60  
61      private final Pattern[] patterns;
62  
63      /**
64       * Construct a <i>case sensitive</i> validator for a single
65       * regular expression.
66       *
67       * @param regex The regular expression this validator will
68       * validate against
69       */
70      public RegexValidator(String regex) {
71          this(regex, true);
72      }
73  
74      /**
75       * Construct a validator for a single regular expression
76       * with the specified case sensitivity.
77       *
78       * @param regex The regular expression this validator will
79       * validate against
80       * @param caseSensitive when <code>true</code> matching is <i>case
81       * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
82       */
83      public RegexValidator(String regex, boolean caseSensitive) {
84          this(new String[] {regex}, caseSensitive);
85      }
86  
87      /**
88       * Construct a <i>case sensitive</i> validator that matches any one
89       * of the set of regular expressions.
90       *
91       * @param regexs The set of regular expressions this validator will
92       * validate against
93       */
94      public RegexValidator(String[] regexs) {
95          this(regexs, true);
96      }
97  
98      /**
99       * Construct a validator that matches any one of the set of regular
100      * expressions with the specified case sensitivity.
101      *
102      * @param regexs The set of regular expressions this validator will
103      * validate against
104      * @param caseSensitive when <code>true</code> matching is <i>case
105      * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
106      */
107     public RegexValidator(String[] regexs, boolean caseSensitive) {
108         if (regexs == null || regexs.length == 0) {
109             throw new IllegalArgumentException("Regular expressions are missing");
110         }
111         patterns = new Pattern[regexs.length];
112         int flags =  (caseSensitive ? 0: Pattern.CASE_INSENSITIVE);
113         for (int i = 0; i < regexs.length; i++) {
114             if (regexs[i] == null || regexs[i].length() == 0) {
115                 throw new IllegalArgumentException("Regular expression[" + i + "] is missing");
116             }
117             patterns[i] =  Pattern.compile(regexs[i], flags);
118         }
119     }
120 
121     /**
122      * Validate a value against the set of regular expressions.
123      *
124      * @param value The value to validate.
125      * @return <code>true</code> if the value is valid
126      * otherwise <code>false</code>.
127      */
128     public boolean isValid(String value) {
129         if (value == null) {
130             return false;
131         }
132         for (int i = 0; i < patterns.length; i++) {
133             if (patterns[i].matcher(value).matches()) {
134                 return true;
135             }
136         }
137         return false;
138     }
139 
140     /**
141      * Validate a value against the set of regular expressions
142      * returning the array of matched groups.
143      *
144      * @param value The value to validate.
145      * @return String array of the <i>groups</i> matched if
146      * valid or <code>null</code> if invalid
147      */
148     public String[] match(String value) {
149         if (value == null) {
150             return null;
151         }
152         for (int i = 0; i < patterns.length; i++) {
153             Matcher matcher = patterns[i].matcher(value);
154             if (matcher.matches()) {
155                 int count = matcher.groupCount();
156                 String[] groups = new String[count];
157                 for (int j = 0; j < count; j++) {
158                     groups[j] = matcher.group(j+1);
159                 }
160                 return groups;
161             }
162         }
163         return null;
164     }
165 
166 
167     /**
168      * Validate a value against the set of regular expressions
169      * returning a String value of the aggregated groups.
170      *
171      * @param value The value to validate.
172      * @return Aggregated String value comprised of the
173      * <i>groups</i> matched if valid or <code>null</code> if invalid
174      */
175     public String validate(String value) {
176         if (value == null) {
177             return null;
178         }
179         for (int i = 0; i < patterns.length; i++) {
180             Matcher matcher = patterns[i].matcher(value);
181             if (matcher.matches()) {
182                 int count = matcher.groupCount();
183                 if (count == 1) {
184                     return matcher.group(1);
185                 }
186                 StringBuffer buffer = new StringBuffer();
187                 for (int j = 0; j < count; j++) {
188                     String component = matcher.group(j+1);
189                     if (component != null) {
190                         buffer.append(component);
191                     }
192                 }
193                 return buffer.toString();
194             }
195         }
196         return null;
197     }
198 
199     /**
200      * Provide a String representation of this validator.
201      * @return A String representation of this validator
202      */
203     public String toString() {
204         StringBuffer buffer = new StringBuffer();
205         buffer.append("RegexValidator{");
206         for (int i = 0; i < patterns.length; i++) {
207             if (i > 0) {
208                 buffer.append(",");
209             }
210             buffer.append(patterns[i].pattern());
211         }
212         buffer.append("}");
213         return buffer.toString();
214     }
215 
216 }