/* * Hibernate Validator, declare and validate application constraints * * License: Apache License, Version 2.0 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>. */ package org.hibernate.validator.test.internal.engine.messageinterpolation; import java.io.ByteArrayInputStream; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import javax.validation.Configuration; import javax.validation.Constraint; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintViolation; import javax.validation.Payload; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; import org.hibernate.validator.testutil.TestForIssue; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.testng.Assert.assertEquals; /** * @author Hardy Ferentschik * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI */ public class MessageInterpolationTest { private Validator validator; @BeforeClass public void createValidator() throws Exception { final StringBuilder lines = new StringBuilder(); lines.append( "bar=Message is \\\\{escaped\\\\}" ).append( "\r\n" ); lines.append( "baz=Message is US\\$ {value}" ).append( "\r\n" ); lines.append( "buz=Message is {values}" ).append( "\r\n" ); lines.append( "qux=Message is {missing}" ).append( "\r\n" ); lines.append( "zap=Message is \\\\${value}" ).append( "\r\n" ); lines.append( "escaped=wrong" ).append( "\r\n" ); final ResourceBundle bundle = new PropertyResourceBundle( new ByteArrayInputStream( lines.toString().getBytes() ) ); Configuration<?> config = Validation.byDefaultProvider() .configure() .messageInterpolator( new ResourceBundleMessageInterpolator( new ResourceBundleLocator() { @Override public ResourceBundle getResourceBundle( Locale locale) { return bundle; } } ) ); ValidatorFactory factory = config.buildValidatorFactory(); validator = factory.getValidator(); } @Test @TestForIssue(jiraKey = "HV-184") public void testCurlyBracesEscapingShouldBeRespected() { final ConstraintViolation<Foo> violation = validator.validate( new Foo(), Bar.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is {escaped}" ); } @Test @TestForIssue(jiraKey = "HV-184") public void testAppendReplacementNeedsToEscapeBackslashAndDollarSign() { final ConstraintViolation<Foo> violation = validator.validate( new Foo(), Baz.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is US$ 5" ); } @Test @TestForIssue(jiraKey = "HV-184") public void testUnknownParametersShouldBePreserved() { final ConstraintViolation<Foo> violation = validator.validate( new Foo(), Qux.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is {missing}" ); } @Test @TestForIssue(jiraKey = "HV-506") public void testInterpolationOfArrayParameter() { final ConstraintViolation<Foo> violation = validator.validate( new Foo(), Buz.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is [bar, baz, qux]" ); } @Test @TestForIssue(jiraKey = "HV-729") public void testDollarSignEscapingShouldBeRespected() { final ConstraintViolation<Foo> violation = validator.validate( new Foo(), Zap.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is $10" ); } public interface Bar { } public interface Baz { } public interface Buz { } public interface Qux { } public interface Zap { } @Target(METHOD) @Retention(RUNTIME) @Constraint(validatedBy = AllowedValuesValidator.class) public static @interface AllowedValues { String[] values(); String message() default "{buz}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } public static class AllowedValuesValidator implements ConstraintValidator<AllowedValues, String> { private List<String> values; @Override public void initialize(AllowedValues values) { this.values = Arrays.asList( values.values() ); } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if ( value == null ) { return true; } return values.contains( value ); } } public static class Foo { @NotNull(message = "{bar}", groups = Bar.class) public String getBar() { return null; } @Min(value = 5, message = "{baz}", groups = Baz.class) public int getBaz() { return 0; } @AllowedValues(values = { "bar", "baz", "qux" }, groups = Buz.class) public String getBuz() { return "buz"; } @NotNull(message = "{qux}", groups = Qux.class) public String getQux() { return null; } @Min(value = 10, message = "{zap}", groups = Zap.class) public int getZap() { return 0; } } }