001// Licensed under the Apache License, Version 2.0 (the "License");
002// you may not use this file except in compliance with the License.
003// You may obtain a copy of the License at
004//
005//     http://www.apache.org/licenses/LICENSE-2.0
006//
007// Unless required by applicable law or agreed to in writing, software
008// distributed under the License is distributed on an "AS IS" BASIS,
009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
010// See the License for the specific language governing permissions and
011// limitations under the License.
012
013package org.apache.tapestry5.validator;
014
015import org.apache.tapestry5.Field;
016import org.apache.tapestry5.MarkupWriter;
017import org.apache.tapestry5.ValidationException;
018import org.apache.tapestry5.ioc.MessageFormatter;
019import org.apache.tapestry5.services.FormSupport;
020import org.apache.tapestry5.services.javascript.DataConstants;
021import org.apache.tapestry5.services.javascript.JavaScriptSupport;
022
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025
026/**
027 * Enforces that the input matches a provided regular expression.
028 * <p/>
029 * Starting in 5.4, this always writes the pattern and title attribute, even when client validation is not enabled.
030 * The title attribute is used specially by modern browsers, in concert with pattern.
031 */
032public class Regexp extends AbstractValidator<Pattern, String>
033{
034    public Regexp(JavaScriptSupport javaScriptSupport)
035    {
036        super(Pattern.class, String.class, "regexp", javaScriptSupport);
037    }
038
039    private String buildMessage(MessageFormatter formatter, Field field, Pattern constraintValue)
040    {
041        return formatter.format(constraintValue.toString(), field.getLabel());
042    }
043
044    public void render(Field field, Pattern constraintValue, MessageFormatter formatter, MarkupWriter writer,
045                       FormSupport formSupport)
046    {
047        String message = buildMessage(formatter, field, constraintValue);
048
049        if (formSupport.isClientValidationEnabled())
050        {
051            javaScriptSupport.require("t5/core/validation");
052
053            writer.attributes(DataConstants.VALIDATION_ATTRIBUTE, true,
054                    "data-validate-regexp", constraintValue.pattern(),
055                    "data-regexp-message", message,
056                    "pattern", constraintValue.pattern(),
057                    "title", message);
058        }
059
060        writer.attributes("pattern", constraintValue.pattern(),
061                "title", message);
062    }
063
064    public void validate(Field field, Pattern constraintValue, MessageFormatter formatter, String value)
065            throws ValidationException
066    {
067        Matcher matcher = constraintValue.matcher(value);
068
069        if (!matcher.matches()) throw new ValidationException(buildMessage(formatter, field, constraintValue));
070    }
071
072}