/*
* Copyright 2011 Martin Grotzke
*
* Licensed 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 de.hashcode.validation;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
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;
/**
* Validate that 2 fields have the same value. An array of fields and their
* matching confirmation fields can be supplied.
*
* Example, compare 1 pair of fields:
* <pre>
* @FieldsMatch(first = "password", second = "confirmPassword", message = "The password fields must match")
* </pre>
* Example, compare more than 1 pair of fields:
* <pre>
* @FieldsMatch.List({
* @FieldsMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
* @FieldsMatch(first = "email", second = "confirmEmail", message = "The email fields must match")
* })
* </pre>
* <p>
* This constraint is based on this
* <a href="http://stackoverflow.com/questions/1972933/cross-field-validation-with-hibernate-validator-jsr-303">stackoverflow post</a>
* with these modifications:
* <ul>
* <li>there's no dependency on commons beanutils</li>
* <li>if an Exception occurs when comparing the specified fields the exception is rethrown
* as RuntimeException (instead of silently dropping it)</li>
* <li>the thrown ConstraintValidationException (when fields don't match) contains the path of the second field so that
* it's highlighted correctly and the error message goes to that field.</li>
* </ul>
* </p>
*/
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = FieldsMatchValidator.class)
@Documented
public @interface FieldsMatch {
String message() default "{validation.constraints.FieldMatch.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* @return The first field
*/
String first();
/**
* @return The second field
*/
String second();
/**
* Defines several <code>@FieldMatch</code> annotations on the same element
*
* @see FieldsMatch
*/
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Documented
@interface List {
FieldsMatch[] value();
}
}