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