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