You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by ad...@apache.org on 2014/08/20 12:46:43 UTC
git commit: WICKET-5654 DefaultViolationTranslator should maybe use
getMessage()
Repository: wicket
Updated Branches:
refs/heads/master 70368f123 -> 6b62b86ae
WICKET-5654 DefaultViolationTranslator should maybe use getMessage()
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/6b62b86a
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/6b62b86a
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/6b62b86a
Branch: refs/heads/master
Commit: 6b62b86ae853150fda617e393d269c9fb9e17a77
Parents: 70368f1
Author: adelbene <an...@gmail.com>
Authored: Wed Aug 20 12:36:24 2014 +0200
Committer: adelbene <an...@gmail.com>
Committed: Wed Aug 20 12:46:22 2014 +0200
----------------------------------------------------------------------
wicket-bean-validation/pom.xml | 6 +
.../validation/DefaultViolationTranslator.java | 71 +++++++---
.../validation/DefaultPropertyResolverTest.java | 129 +++++++++++++++++--
.../PasswordConstraintAnnotation.java | 45 +++++++
.../customconstraint/PasswordValidator.java | 58 +++++++++
5 files changed, 278 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-bean-validation/pom.xml b/wicket-bean-validation/pom.xml
index 0b52e32..b91e4e7 100644
--- a/wicket-bean-validation/pom.xml
+++ b/wicket-bean-validation/pom.xml
@@ -37,5 +37,11 @@
<version>5.1.2.Final</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.glassfish.web</groupId>
+ <artifactId>el-impl</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
----------------------------------------------------------------------
diff --git a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
index feec4f3..7b006aa 100644
--- a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
+++ b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
@@ -1,5 +1,8 @@
package org.apache.wicket.bean.validation;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.validation.ConstraintViolation;
import javax.validation.metadata.ConstraintDescriptor;
@@ -24,37 +27,69 @@ public class DefaultViolationTranslator implements IViolationTranslator
ValidationError error = new ValidationError();
error.setMessage(violation.getMessage());
- String messageKey = getMessageKey(desc);
- if (messageKey != null)
- {
- if (violation.getInvalidValue() != null)
- {
- error.addKey(messageKey + "." +
- violation.getInvalidValue().getClass().getSimpleName());
- }
- error.addKey(messageKey);
- }
+ List<String> messages = getViolationMessages(violation, desc);
+ addErrorKeys(error, violation.getInvalidValue(), messages);
for (String key : desc.getAttributes().keySet())
{
error.setVariable(key, desc.getAttributes().get(key));
}
+
return error;
}
- private String getMessageKey(ConstraintDescriptor<?> desc)
+ private List<String> getViolationMessages(ConstraintViolation<?> violation,
+ ConstraintDescriptor<?> desc)
{
- final Object val = desc.getAttributes().get("message");
- if (val != null)
+ String defaultMessage = (String)desc.getAttributes().get("message");
+ String violationMessage = violation.getMessage();
+ String violationMessageTemplate = violation.getMessageTemplate();
+ List<String> messages = new ArrayList<String>();
+
+ //violation message is considered only if it is different from
+ //the interpolated message
+ if (!Strings.isEqual(violationMessage, violationMessageTemplate))
{
- String str = val.toString();
- if (!Strings.isEmpty(str) && str.startsWith("{") && str.endsWith("}"))
+ messages.add(violationMessageTemplate);
+ }
+
+ messages.add(violationMessage);
+
+ //the default message is considered only if it is different from
+ //the violation message template
+ if (!Strings.isEqual(defaultMessage, violationMessageTemplate))
+ {
+ messages.add(defaultMessage);
+ }
+
+ return messages;
+ }
+
+ private void addErrorKeys(ValidationError error, Object invalidValue, List<String> messages)
+ {
+ for (String message : messages)
+ {
+ String messageKey = getMessageKey(message);
+
+ if (messageKey != null)
{
- return str.substring(1, str.length() - 1);
+ if (invalidValue != null)
+ {
+ error.addKey(messageKey + "." + invalidValue.getClass().getSimpleName());
+ }
+
+ error.addKey(messageKey);
}
}
- return null;
}
-
+ private String getMessageKey(String message)
+ {
+ if (!Strings.isEmpty(message) && message.startsWith("{") && message.endsWith("}"))
+ {
+ return message.substring(1, message.length() - 1);
+ }
+
+ return null;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
----------------------------------------------------------------------
diff --git a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
index 2ef498f..1dc6802 100644
--- a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
+++ b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
@@ -16,12 +16,28 @@
*/
package org.apache.wicket.bean.validation;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
+import static org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation.CUSTOM_BUNDLE_KEY;
+import static org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation.DEFAULT_BUNDLE_KEY;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+import org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.util.tester.WicketTesterScope;
+import org.apache.wicket.validation.ValidationError;
import org.junit.Rule;
import org.junit.Test;
@@ -45,8 +61,7 @@ public class DefaultPropertyResolverTest
{
DefaultPropertyResolver resolver = new DefaultPropertyResolver();
- TextField<?> component = new TextField<>("id", new PropertyModel<Bean1>(new Bean1(),
- "foo"));
+ TextField<?> component = new TextField<>("id", new PropertyModel<Bean1>(new Bean1(), "foo"));
Property property = resolver.resolveProperty(component);
assertThat(property, not(nullValue()));
assertThat(property.getName(), is("foo"));
@@ -61,8 +76,8 @@ public class DefaultPropertyResolverTest
{
DefaultPropertyResolver resolver = new DefaultPropertyResolver();
- TextField<?> component = new TextField<>("id", new PropertyModel<BooleanBean>(new BooleanBean(),
- "foo"));
+ TextField<?> component = new TextField<>("id", new PropertyModel<BooleanBean>(
+ new BooleanBean(), "foo"));
Property property = resolver.resolveProperty(component);
assertThat(property, not(nullValue()));
assertThat(property.getName(), is("foo"));
@@ -74,8 +89,7 @@ public class DefaultPropertyResolverTest
{
DefaultPropertyResolver resolver = new DefaultPropertyResolver();
- TextField<?> component = new TextField<>("id", new PropertyModel<Bean2>(new Bean2(),
- "foo"));
+ TextField<?> component = new TextField<>("id", new PropertyModel<Bean2>(new Bean2(), "foo"));
Property property = resolver.resolveProperty(component);
assertThat(property, not(nullValue()));
assertThat(property.getName(), is("foo"));
@@ -92,8 +106,7 @@ public class DefaultPropertyResolverTest
{
DefaultPropertyResolver resolver = new DefaultPropertyResolver();
- TextField<?> component = new TextField<>("id", new PropertyModel<Bean3>(new Bean3(),
- "foo"));
+ TextField<?> component = new TextField<>("id", new PropertyModel<Bean3>(new Bean3(), "foo"));
Property property = resolver.resolveProperty(component);
assertThat(property, not(nullValue()));
assertThat(property.getName(), is("foo"));
@@ -108,14 +121,83 @@ public class DefaultPropertyResolverTest
{
DefaultPropertyResolver resolver = new DefaultPropertyResolver();
- TextField<?> component = new TextField<>("id", new PropertyModel<Bean4>(new Bean4(),
- "foo"));
+ TextField<?> component = new TextField<>("id", new PropertyModel<Bean4>(new Bean4(), "foo"));
Property property = resolver.resolveProperty(component);
assertThat(property, not(nullValue()));
assertThat(property.getName(), is("foo"));
assertThat(property.getOwner().getName(), is(Bean4.class.getName()));
}
+ /**
+ * Test custom bundle mechanism of jsr 303
+ *
+ * https://issues.apache.org/jira/browse/WICKET-5654
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testBundleKeysResolution() throws Exception
+ {
+ ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+ Validator validator = factory.getValidator();
+ DefaultViolationTranslator translator = new DefaultViolationTranslator();
+
+ // test with a too short password
+ BeanWithPassword bean = new BeanWithPassword("short");
+
+ Set<ConstraintViolation<BeanWithPassword>> constraintViolations = validator.validate(bean);
+ assertEquals(1, constraintViolations.size());
+
+ @SuppressWarnings("unchecked")
+ ConstraintViolation<BeanWithPassword> shortViolation = (ConstraintViolation<BeanWithPassword>)constraintViolations
+ .toArray()[0];
+
+ ValidationError error = translator.convert(shortViolation);
+
+ checkErrorBundleKeys(error, DEFAULT_BUNDLE_KEY + ".String", DEFAULT_BUNDLE_KEY);
+
+ // test with a password containing non-word chars
+ bean.setPassword("notWord&%$£");
+
+ constraintViolations = validator.validate(bean);
+ assertEquals(1, constraintViolations.size());
+
+ @SuppressWarnings("unchecked")
+ ConstraintViolation<BeanWithPassword> nonWordviolation = (ConstraintViolation<BeanWithPassword>)constraintViolations.toArray()[0];
+
+ error = translator.convert(nonWordviolation);
+
+ checkErrorBundleKeys(error, CUSTOM_BUNDLE_KEY + ".String", CUSTOM_BUNDLE_KEY,
+ DEFAULT_BUNDLE_KEY + ".String", DEFAULT_BUNDLE_KEY);
+
+ // test with a valid password
+ bean.setPassword("aValidPassword1234");
+
+ constraintViolations = validator.validate(bean);
+ assertEquals(0, constraintViolations.size());
+ }
+
+ /**
+ * Checks that validation error has the expected keys as bundle keys, in the order they are
+ * specified in {@code expectedKeys}.
+ *
+ * @param error
+ * @param expectedKeys
+ */
+ private void checkErrorBundleKeys(ValidationError error, String... expectedKeys)
+ {
+ List<String> keys = error.getKeys();
+
+ assertEquals("The expected number for bundle keys is '" + expectedKeys.length
+ + "' but we have '" + keys.size() + "'", expectedKeys.length, keys.size());
+
+ for (int i = 0; i < expectedKeys.length; i++)
+ {
+ String expectedKey = expectedKeys[i];
+
+ assertTrue(keys.get(i).equals(expectedKey));
+ }
+ }
public static class Bean3
{
@@ -143,4 +225,25 @@ public class DefaultPropertyResolverTest
return "foo4";
}
}
+
+ public static class BeanWithPassword
+ {
+ @PasswordConstraintAnnotation
+ private String password;
+
+ public BeanWithPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
----------------------------------------------------------------------
diff --git a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
new file mode 100644
index 0000000..73f0ab1
--- /dev/null
+++ b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.bean.validation.customconstraint;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ METHOD, FIELD, ANNOTATION_TYPE })
+@Retention(RUNTIME)
+@Constraint(validatedBy = PasswordValidator.class)
+@Documented
+public @interface PasswordConstraintAnnotation
+{
+ public static final String DEFAULT_BUNDLE_KEY = "default.bundle.key";
+ public static final String CUSTOM_BUNDLE_KEY = "custom.bundle.key";
+
+ String message() default "{" + DEFAULT_BUNDLE_KEY +"}";
+
+ Class<?>[] groups() default { };
+
+ Class<? extends Payload>[] payload() default { };
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
----------------------------------------------------------------------
diff --git a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
new file mode 100644
index 0000000..a319953
--- /dev/null
+++ b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.bean.validation.customconstraint;
+
+import java.util.regex.Matcher;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+import org.apache.wicket.util.parse.metapattern.MetaPattern;
+import org.apache.wicket.util.string.Strings;
+
+public class PasswordValidator implements ConstraintValidator<PasswordConstraintAnnotation, String>
+{
+
+ @Override
+ public void initialize(PasswordConstraintAnnotation constraintAnnotation)
+ {
+ }
+
+ @Override
+ public boolean isValid(String value, ConstraintValidatorContext context)
+ {
+ // password must be at least 8 chars long.
+ if (Strings.isEmpty(value) || value.length() < 8)
+ {
+ return false;
+ }
+
+ Matcher matcher = MetaPattern.NON_WORD.matcher(value);
+
+ // password must not contain non-word characters.
+ if (matcher.find())
+ {
+ context.disableDefaultConstraintViolation();
+ context.buildConstraintViolationWithTemplate("{" +
+ PasswordConstraintAnnotation.CUSTOM_BUNDLE_KEY + "}").addConstraintViolation();
+ return false;
+ }
+
+ return true;
+ }
+
+}
Re: git commit: WICKET-5654 DefaultViolationTranslator should maybe
use getMessage()
Posted by Martin Grigorov <mg...@apache.org>.
On Wed, Aug 20, 2014 at 1:46 PM, <ad...@apache.org> wrote:
> Repository: wicket
> Updated Branches:
> refs/heads/master 70368f123 -> 6b62b86ae
>
>
> WICKET-5654 DefaultViolationTranslator should maybe use getMessage()
>
>
> Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
> Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/6b62b86a
> Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/6b62b86a
> Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/6b62b86a
>
> Branch: refs/heads/master
> Commit: 6b62b86ae853150fda617e393d269c9fb9e17a77
> Parents: 70368f1
> Author: adelbene <an...@gmail.com>
> Authored: Wed Aug 20 12:36:24 2014 +0200
> Committer: adelbene <an...@gmail.com>
> Committed: Wed Aug 20 12:46:22 2014 +0200
>
> ----------------------------------------------------------------------
> wicket-bean-validation/pom.xml | 6 +
> .../validation/DefaultViolationTranslator.java | 71 +++++++---
> .../validation/DefaultPropertyResolverTest.java | 129 +++++++++++++++++--
> .../PasswordConstraintAnnotation.java | 45 +++++++
> .../customconstraint/PasswordValidator.java | 58 +++++++++
> 5 files changed, 278 insertions(+), 31 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/pom.xml
> ----------------------------------------------------------------------
> diff --git a/wicket-bean-validation/pom.xml
> b/wicket-bean-validation/pom.xml
> index 0b52e32..b91e4e7 100644
> --- a/wicket-bean-validation/pom.xml
> +++ b/wicket-bean-validation/pom.xml
> @@ -37,5 +37,11 @@
> <version>5.1.2.Final</version>
> <scope>test</scope>
> </dependency>
> + <dependency>
> + <groupId>org.glassfish.web</groupId>
> + <artifactId>el-impl</artifactId>
> + <version>2.2</version>
> + <scope>test</scope>
> + </dependency>
> </dependencies>
> </project>
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
> b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
> index feec4f3..7b006aa 100644
> ---
> a/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
> +++
> b/wicket-bean-validation/src/main/java/org/apache/wicket/bean/validation/DefaultViolationTranslator.java
> @@ -1,5 +1,8 @@
> package org.apache.wicket.bean.validation;
>
> +import java.util.ArrayList;
> +import java.util.List;
> +
> import javax.validation.ConstraintViolation;
> import javax.validation.metadata.ConstraintDescriptor;
>
> @@ -24,37 +27,69 @@ public class DefaultViolationTranslator implements
> IViolationTranslator
> ValidationError error = new ValidationError();
> error.setMessage(violation.getMessage());
>
> - String messageKey = getMessageKey(desc);
> - if (messageKey != null)
> - {
> - if (violation.getInvalidValue() != null)
> - {
> - error.addKey(messageKey + "." +
> -
> violation.getInvalidValue().getClass().getSimpleName());
> - }
> - error.addKey(messageKey);
> - }
> + List<String> messages = getViolationMessages(violation,
> desc);
> + addErrorKeys(error, violation.getInvalidValue(), messages);
>
> for (String key : desc.getAttributes().keySet())
> {
> error.setVariable(key,
> desc.getAttributes().get(key));
> }
> +
> return error;
> }
>
> - private String getMessageKey(ConstraintDescriptor<?> desc)
> + private List<String> getViolationMessages(ConstraintViolation<?>
> violation,
> + ConstraintDescriptor<?> desc)
> {
> - final Object val = desc.getAttributes().get("message");
> - if (val != null)
> + String defaultMessage =
> (String)desc.getAttributes().get("message");
> + String violationMessage = violation.getMessage();
> + String violationMessageTemplate =
> violation.getMessageTemplate();
> + List<String> messages = new ArrayList<String>();
> +
> + //violation message is considered only if it is different
> from
> + //the interpolated message
> + if (!Strings.isEqual(violationMessage,
> violationMessageTemplate))
> {
> - String str = val.toString();
> - if (!Strings.isEmpty(str) && str.startsWith("{")
> && str.endsWith("}"))
> + messages.add(violationMessageTemplate);
> + }
> +
> + messages.add(violationMessage);
> +
> + //the default message is considered only if it is
> different from
> + //the violation message template
> + if (!Strings.isEqual(defaultMessage,
> violationMessageTemplate))
> + {
> + messages.add(defaultMessage);
> + }
> +
> + return messages;
> + }
> +
> + private void addErrorKeys(ValidationError error, Object
> invalidValue, List<String> messages)
> + {
> + for (String message : messages)
> + {
> + String messageKey = getMessageKey(message);
> +
> + if (messageKey != null)
> {
> - return str.substring(1, str.length() - 1);
> + if (invalidValue != null)
> + {
> + error.addKey(messageKey + "." +
> invalidValue.getClass().getSimpleName());
>
Use Classes.simpleName(invalidValue.getClass()) instead.
It is smarter when dealing with anonymous classes.
> + }
> +
> + error.addKey(messageKey);
> }
> }
> - return null;
> }
>
> -
> + private String getMessageKey(String message)
> + {
> + if (!Strings.isEmpty(message) && message.startsWith("{")
> && message.endsWith("}"))
> + {
> + return message.substring(1, message.length() - 1);
> + }
> +
> + return null;
> + }
> }
> \ No newline at end of file
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
> index 2ef498f..1dc6802 100644
> ---
> a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
> +++
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/DefaultPropertyResolverTest.java
> @@ -16,12 +16,28 @@
> */
> package org.apache.wicket.bean.validation;
>
> -import static org.hamcrest.CoreMatchers.*;
> -import static org.junit.Assert.*;
> -
> +import static
> org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation.CUSTOM_BUNDLE_KEY;
> +import static
> org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation.DEFAULT_BUNDLE_KEY;
> +import static org.hamcrest.CoreMatchers.is;
> +import static org.hamcrest.CoreMatchers.not;
> +import static org.hamcrest.CoreMatchers.nullValue;
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertThat;
> +import static org.junit.Assert.assertTrue;
> +
> +import java.util.List;
> +import java.util.Set;
> +
> +import javax.validation.ConstraintViolation;
> +import javax.validation.Validation;
> +import javax.validation.Validator;
> +import javax.validation.ValidatorFactory;
> +
> +import
> org.apache.wicket.bean.validation.customconstraint.PasswordConstraintAnnotation;
> import org.apache.wicket.markup.html.form.TextField;
> import org.apache.wicket.model.PropertyModel;
> import org.apache.wicket.util.tester.WicketTesterScope;
> +import org.apache.wicket.validation.ValidationError;
> import org.junit.Rule;
> import org.junit.Test;
>
> @@ -45,8 +61,7 @@ public class DefaultPropertyResolverTest
> {
> DefaultPropertyResolver resolver = new
> DefaultPropertyResolver();
>
> - TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean1>(new Bean1(),
> - "foo"));
> + TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean1>(new Bean1(), "foo"));
> Property property = resolver.resolveProperty(component);
> assertThat(property, not(nullValue()));
> assertThat(property.getName(), is("foo"));
> @@ -61,8 +76,8 @@ public class DefaultPropertyResolverTest
> {
> DefaultPropertyResolver resolver = new
> DefaultPropertyResolver();
>
> - TextField<?> component = new TextField<>("id", new
> PropertyModel<BooleanBean>(new BooleanBean(),
> - "foo"));
> + TextField<?> component = new TextField<>("id", new
> PropertyModel<BooleanBean>(
> + new BooleanBean(), "foo"));
> Property property = resolver.resolveProperty(component);
> assertThat(property, not(nullValue()));
> assertThat(property.getName(), is("foo"));
> @@ -74,8 +89,7 @@ public class DefaultPropertyResolverTest
> {
> DefaultPropertyResolver resolver = new
> DefaultPropertyResolver();
>
> - TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean2>(new Bean2(),
> - "foo"));
> + TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean2>(new Bean2(), "foo"));
> Property property = resolver.resolveProperty(component);
> assertThat(property, not(nullValue()));
> assertThat(property.getName(), is("foo"));
> @@ -92,8 +106,7 @@ public class DefaultPropertyResolverTest
> {
> DefaultPropertyResolver resolver = new
> DefaultPropertyResolver();
>
> - TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean3>(new Bean3(),
> - "foo"));
> + TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean3>(new Bean3(), "foo"));
> Property property = resolver.resolveProperty(component);
> assertThat(property, not(nullValue()));
> assertThat(property.getName(), is("foo"));
> @@ -108,14 +121,83 @@ public class DefaultPropertyResolverTest
> {
> DefaultPropertyResolver resolver = new
> DefaultPropertyResolver();
>
> - TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean4>(new Bean4(),
> - "foo"));
> + TextField<?> component = new TextField<>("id", new
> PropertyModel<Bean4>(new Bean4(), "foo"));
> Property property = resolver.resolveProperty(component);
> assertThat(property, not(nullValue()));
> assertThat(property.getName(), is("foo"));
> assertThat(property.getOwner().getName(),
> is(Bean4.class.getName()));
> }
>
> + /**
> + * Test custom bundle mechanism of jsr 303
> + *
> + * https://issues.apache.org/jira/browse/WICKET-5654
> + *
> + * @throws Exception
> + */
> + @Test
> + public void testBundleKeysResolution() throws Exception
> + {
> + ValidatorFactory factory =
> Validation.buildDefaultValidatorFactory();
> + Validator validator = factory.getValidator();
> + DefaultViolationTranslator translator = new
> DefaultViolationTranslator();
> +
> + // test with a too short password
> + BeanWithPassword bean = new BeanWithPassword("short");
> +
> + Set<ConstraintViolation<BeanWithPassword>>
> constraintViolations = validator.validate(bean);
> + assertEquals(1, constraintViolations.size());
> +
> + @SuppressWarnings("unchecked")
> + ConstraintViolation<BeanWithPassword> shortViolation =
> (ConstraintViolation<BeanWithPassword>)constraintViolations
> + .toArray()[0];
> +
> + ValidationError error = translator.convert(shortViolation);
> +
> + checkErrorBundleKeys(error, DEFAULT_BUNDLE_KEY +
> ".String", DEFAULT_BUNDLE_KEY);
> +
> + // test with a password containing non-word chars
> + bean.setPassword("notWord&%$£");
> +
> + constraintViolations = validator.validate(bean);
> + assertEquals(1, constraintViolations.size());
> +
> + @SuppressWarnings("unchecked")
> + ConstraintViolation<BeanWithPassword> nonWordviolation =
> (ConstraintViolation<BeanWithPassword>)constraintViolations.toArray()[0];
> +
> + error = translator.convert(nonWordviolation);
> +
> + checkErrorBundleKeys(error, CUSTOM_BUNDLE_KEY + ".String",
> CUSTOM_BUNDLE_KEY,
> + DEFAULT_BUNDLE_KEY + ".String",
> DEFAULT_BUNDLE_KEY);
> +
> + // test with a valid password
> + bean.setPassword("aValidPassword1234");
> +
> + constraintViolations = validator.validate(bean);
> + assertEquals(0, constraintViolations.size());
> + }
> +
> + /**
> + * Checks that validation error has the expected keys as bundle
> keys, in the order they are
> + * specified in {@code expectedKeys}.
> + *
> + * @param error
> + * @param expectedKeys
> + */
> + private void checkErrorBundleKeys(ValidationError error, String...
> expectedKeys)
> + {
> + List<String> keys = error.getKeys();
> +
> + assertEquals("The expected number for bundle keys is '" +
> expectedKeys.length
> + + "' but we have '" + keys.size() + "'",
> expectedKeys.length, keys.size());
> +
> + for (int i = 0; i < expectedKeys.length; i++)
> + {
> + String expectedKey = expectedKeys[i];
> +
> + assertTrue(keys.get(i).equals(expectedKey));
> + }
> + }
>
> public static class Bean3
> {
> @@ -143,4 +225,25 @@ public class DefaultPropertyResolverTest
> return "foo4";
> }
> }
> +
> + public static class BeanWithPassword
> + {
> + @PasswordConstraintAnnotation
> + private String password;
> +
> + public BeanWithPassword(String password)
> + {
> + this.password = password;
> + }
> +
> + public String getPassword()
> + {
> + return password;
> + }
> +
> + public void setPassword(String password)
> + {
> + this.password = password;
> + }
> + }
> }
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
> new file mode 100644
> index 0000000..73f0ab1
> --- /dev/null
> +++
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordConstraintAnnotation.java
> @@ -0,0 +1,45 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.wicket.bean.validation.customconstraint;
> +
> +import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
> +import static java.lang.annotation.ElementType.FIELD;
> +import static java.lang.annotation.ElementType.METHOD;
> +import static java.lang.annotation.RetentionPolicy.RUNTIME;
> +
> +import java.lang.annotation.Documented;
> +import java.lang.annotation.Retention;
> +import java.lang.annotation.Target;
> +
> +import javax.validation.Constraint;
> +import javax.validation.Payload;
> +
> +@Target({ METHOD, FIELD, ANNOTATION_TYPE })
> +@Retention(RUNTIME)
> +@Constraint(validatedBy = PasswordValidator.class)
> +@Documented
> +public @interface PasswordConstraintAnnotation
> +{
> + public static final String DEFAULT_BUNDLE_KEY =
> "default.bundle.key";
> + public static final String CUSTOM_BUNDLE_KEY = "custom.bundle.key";
> +
> + String message() default "{" + DEFAULT_BUNDLE_KEY +"}";
> +
> + Class<?>[] groups() default { };
> +
> + Class<? extends Payload>[] payload() default { };
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/wicket/blob/6b62b86a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
> ----------------------------------------------------------------------
> diff --git
> a/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
> new file mode 100644
> index 0000000..a319953
> --- /dev/null
> +++
> b/wicket-bean-validation/src/test/java/org/apache/wicket/bean/validation/customconstraint/PasswordValidator.java
> @@ -0,0 +1,58 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements. See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License. You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.wicket.bean.validation.customconstraint;
> +
> +import java.util.regex.Matcher;
> +
> +import javax.validation.ConstraintValidator;
> +import javax.validation.ConstraintValidatorContext;
> +
> +import org.apache.wicket.util.parse.metapattern.MetaPattern;
> +import org.apache.wicket.util.string.Strings;
> +
> +public class PasswordValidator implements
> ConstraintValidator<PasswordConstraintAnnotation, String>
> +{
> +
> + @Override
> + public void initialize(PasswordConstraintAnnotation
> constraintAnnotation)
> + {
> + }
> +
> + @Override
> + public boolean isValid(String value, ConstraintValidatorContext
> context)
> + {
> + // password must be at least 8 chars long.
> + if (Strings.isEmpty(value) || value.length() < 8)
> + {
> + return false;
> + }
> +
> + Matcher matcher = MetaPattern.NON_WORD.matcher(value);
> +
> + // password must not contain non-word characters.
> + if (matcher.find())
> + {
> + context.disableDefaultConstraintViolation();
> + context.buildConstraintViolationWithTemplate("{" +
> +
> PasswordConstraintAnnotation.CUSTOM_BUNDLE_KEY +
> "}").addConstraintViolation();
> + return false;
> + }
> +
> + return true;
> + }
> +
> +}
>
>