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 */ 017package org.apache.wicket.validation.validator; 018 019import java.util.regex.Pattern; 020 021import org.apache.wicket.markup.html.form.FormComponent; 022import org.apache.wicket.util.parse.metapattern.MetaPattern; 023import org.apache.wicket.validation.IValidatable; 024import org.apache.wicket.validation.IValidationError; 025import org.apache.wicket.validation.IValidator; 026import org.apache.wicket.validation.ValidationError; 027 028/** 029 * Validates an {@link IValidatable} by matching the value against a regular expression pattern. A 030 * <code>PatternValidator</code> can be constructed with either a Java regular expression (compiled 031 * or not) or a {@link MetaPattern}. If the pattern matches against the value then it is considered 032 * valid. If the pattern does not match, the an {@link IValidationError} will be reported on the 033 * {@link IValidatable}. 034 * <p> 035 * For example, to restrict a field to only digits, you might add a <code>PatternValidator</code> 036 * constructed with the pattern "\d+". Another way to do the same thing would be to construct the 037 * <code>PatternValidator</code> passing in {@link MetaPattern#DIGITS}. The advantages of using 038 * {@link MetaPattern} over straight Java regular expressions are that the patterns are easier to 039 * construct and easier to combine into complex patterns. They are also more readable and more 040 * reusable. See {@link MetaPattern} for details. 041 * <p> 042 * The error message will be generated with the key "PatternValidator" and one additional message 043 * key ${pattern} for the pattern which failed to match. See {@link FormComponent} for a list of 044 * further messages keys. 045 * 046 * @see java.util.regex.Pattern 047 * 048 * @author Jonathan Locke 049 * @author Igor Vaynberg (ivaynberg) 050 * @since 1.2.6 051 */ 052public class PatternValidator implements IValidator<String> 053{ 054 private static final long serialVersionUID = 1L; 055 056 /** the pattern to match */ 057 private final Pattern pattern; 058 059 /** whether to exclude matching input **/ 060 private boolean reverse = false; 061 062 /** 063 * Constructor that accepts a <code>String</code> regular expression pattern. 064 * 065 * @param pattern 066 * a regular expression pattern 067 */ 068 public PatternValidator(final String pattern) 069 { 070 this(Pattern.compile(pattern)); 071 } 072 073 /** 074 * Constructor that accepts a <code>String</code> pattern and Java <code>regex</code> compile 075 * flags as arguments. 076 * 077 * @param pattern 078 * a regular expression pattern 079 * @param flags 080 * compile flags for <code>java.util.regex.Pattern</code> 081 */ 082 public PatternValidator(final String pattern, final int flags) 083 { 084 this(Pattern.compile(pattern, flags)); 085 } 086 087 /** 088 * Constructor that accepts a compiled pattern. 089 * 090 * @param pattern 091 * a compiled pattern 092 */ 093 public PatternValidator(final Pattern pattern) 094 { 095 this.pattern = pattern; 096 } 097 098 /** 099 * Constructor that accepts a <code>MetaPattern</code> argument. 100 * 101 * @param pattern 102 * a <code>MetaPattern</code> 103 */ 104 public PatternValidator(final MetaPattern pattern) 105 { 106 this(pattern.pattern()); 107 } 108 109 /** 110 * Gets the regexp pattern. 111 * 112 * @return the regexp pattern 113 */ 114 public final Pattern getPattern() 115 { 116 return pattern; 117 } 118 119 /** 120 * If set to true then input that matches the pattern is considered invalid. 121 * 122 * @param reverse 123 * @return itself 124 */ 125 public PatternValidator setReverse(boolean reverse) 126 { 127 this.reverse = reverse; 128 return this; 129 } 130 131 /** 132 * @see java.lang.Object#toString() 133 */ 134 @Override 135 public String toString() 136 { 137 return "[PatternValidator pattern = " + pattern + "]"; 138 } 139 140 /** 141 * Checks a value against this <code>PatternValidator</code>'s {@link Pattern}. 142 * 143 * @param validatable 144 * the <code>IValidatable</code> to check 145 */ 146 @Override 147 public void validate(IValidatable<String> validatable) 148 { 149 // Check value against pattern 150 if (pattern.matcher(validatable.getValue()).matches() == reverse) 151 { 152 ValidationError error = new ValidationError(this); 153 error.setVariable("pattern", pattern.pattern()); 154 validatable.error(decorate(error, validatable)); 155 } 156 } 157 158 /** 159 * Allows subclasses to decorate reported errors 160 * 161 * @param error 162 * @param validatable 163 * @return decorated error 164 */ 165 protected IValidationError decorate(IValidationError error, IValidatable<String> validatable) 166 { 167 return error; 168 } 169}