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   * </p>
32   * <pre>
33   * <code>
34   * String[] regexs = new String[] {...};
35   * RegexValidator validator = new RegexValidator(regexs, false);
36   * </code>
37   * </pre>
38   *
39   * <ul>
40   *   <li>Validate <code>true</code> or <code>false</code>:</li>
41   *   <li>
42   *     <ul>
43   *       <li><code>boolean valid = validator.isValid(value);</code></li>
44   *     </ul>
45   *   </li>
46   *   <li>Validate returning an aggregated String of the matched groups:</li>
47   *   <li>
48   *     <ul>
49   *       <li><code>String result = validator.validate(value);</code></li>
50   *     </ul>
51   *   </li>
52   *   <li>Validate returning the matched groups:</li>
53   *   <li>
54   *     <ul>
55   *       <li><code>String[] result = validator.match(value);</code></li>
56   *     </ul>
57   *   </li>
58   * </ul>
59   *
60   * <b>Note that patterns are matched against the entire input.</b>
61   *
62   * <p>
63   * Cached instances pre-compile and re-use {@link Pattern}(s) - which according
64   * to the {@link Pattern} API are safe to use in a multi-threaded environment.
65   * </p>
66   *
67   * @version $Revision: 1739356 $
68   * @since Validator 1.4
69   */
70  public class RegexValidator implements Serializable {
71  
72      private static final long serialVersionUID = -8832409930574867162L;
73  
74      private final Pattern[] patterns;
75  
76      /**
77       * Construct a <i>case sensitive</i> validator for a single
78       * regular expression.
79       *
80       * @param regex The regular expression this validator will
81       * validate against
82       */
83      public RegexValidator(String regex) {
84          this(regex, true);
85      }
86  
87      /**
88       * Construct a validator for a single regular expression
89       * with the specified case sensitivity.
90       *
91       * @param regex The regular expression this validator will
92       * validate against
93       * @param caseSensitive when <code>true</code> matching is <i>case
94       * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
95       */
96      public RegexValidator(String regex, boolean caseSensitive) {
97          this(new String[] {regex}, caseSensitive);
98      }
99  
100     /**
101      * Construct a <i>case sensitive</i> validator that matches any one
102      * of the set of regular expressions.
103      *
104      * @param regexs The set of regular expressions this validator will
105      * validate against
106      */
107     public RegexValidator(String[] regexs) {
108         this(regexs, true);
109     }
110 
111     /**
112      * Construct a validator that matches any one of the set of regular
113      * expressions with the specified case sensitivity.
114      *
115      * @param regexs The set of regular expressions this validator will
116      * validate against
117      * @param caseSensitive when <code>true</code> matching is <i>case
118      * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
119      */
120     public RegexValidator(String[] regexs, boolean caseSensitive) {
121         if (regexs == null || regexs.length == 0) {
122             throw new IllegalArgumentException("Regular expressions are missing");
123         }
124         patterns = new Pattern[regexs.length];
125         int flags =  (caseSensitive ? 0: Pattern.CASE_INSENSITIVE);
126         for (int i = 0; i < regexs.length; i++) {
127             if (regexs[i] == null || regexs[i].length() == 0) {
128                 throw new IllegalArgumentException("Regular expression[" + i + "] is missing");
129             }
130             patterns[i] =  Pattern.compile(regexs[i], flags);
131         }
132     }
133 
134     /**
135      * Validate a value against the set of regular expressions.
136      *
137      * @param value The value to validate.
138      * @return <code>true</code> if the value is valid
139      * otherwise <code>false</code>.
140      */
141     public boolean isValid(String value) {
142         if (value == null) {
143             return false;
144         }
145         for (int i = 0; i < patterns.length; i++) {
146             if (patterns[i].matcher(value).matches()) {
147                 return true;
148             }
149         }
150         return false;
151     }
152 
153     /**
154      * Validate a value against the set of regular expressions
155      * returning the array of matched groups.
156      *
157      * @param value The value to validate.
158      * @return String array of the <i>groups</i> matched if
159      * valid or <code>null</code> if invalid
160      */
161     public String[] match(String value) {
162         if (value == null) {
163             return null;
164         }
165         for (int i = 0; i < patterns.length; i++) {
166             Matcher matcher = patterns[i].matcher(value);
167             if (matcher.matches()) {
168                 int count = matcher.groupCount();
169                 String[] groups = new String[count];
170                 for (int j = 0; j < count; j++) {
171                     groups[j] = matcher.group(j+1);
172                 }
173                 return groups;
174             }
175         }
176         return null;
177     }
178 
179 
180     /**
181      * Validate a value against the set of regular expressions
182      * returning a String value of the aggregated groups.
183      *
184      * @param value The value to validate.
185      * @return Aggregated String value comprised of the
186      * <i>groups</i> matched if valid or <code>null</code> if invalid
187      */
188     public String validate(String value) {
189         if (value == null) {
190             return null;
191         }
192         for (int i = 0; i < patterns.length; i++) {
193             Matcher matcher = patterns[i].matcher(value);
194             if (matcher.matches()) {
195                 int count = matcher.groupCount();
196                 if (count == 1) {
197                     return matcher.group(1);
198                 }
199                 StringBuilder buffer = new StringBuilder();
200                 for (int j = 0; j < count; j++) {
201                     String component = matcher.group(j+1);
202                     if (component != null) {
203                         buffer.append(component);
204                     }
205                 }
206                 return buffer.toString();
207             }
208         }
209         return null;
210     }
211 
212     /**
213      * Provide a String representation of this validator.
214      * @return A String representation of this validator
215      */
216     @Override
217     public String toString() {
218         StringBuilder buffer = new StringBuilder();
219         buffer.append("RegexValidator{");
220         for (int i = 0; i < patterns.length; i++) {
221             if (i > 0) {
222                 buffer.append(",");
223             }
224             buffer.append(patterns[i].pattern());
225         }
226         buffer.append("}");
227         return buffer.toString();
228     }
229 
230 }