<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Here is the proposal I integrated in the spec. Main changes are in the email, I cannot attach the whole spec (too big for the mailing list) but if you ask me I will send it to you by email.</div><div><br></div><div>Review very much welcome.</div><div><br></div><div><br></div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h2 class="title" style="clear: both; font-family: sans-serif; color: rgb(0, 51, 153); font-size: 140%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">2.1. Constraint annotation</h2></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A constraint on a JavaBean is expressed through one or more annotations. An annotation is considered a constraint definition if its retention policy contains <tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">RUNTIME</tt> and if the annotation itself is annotated with <tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">javax.validation.Constraint</tt>.</p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">/**
* Link between a constraint annotation and its constraint validation implementations.
* <p/>
* A given constraint annotation should be annotated by a @Constraint
* annotation which refers to its list of constraint validation implementation.
*
* @author Emmanuel Bernard (emmanuel at hibernate.org)
* @author Gavin King
* @author Hardy Ferentschik
*/
@Documented
@Target({ ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Constraint {
        /**
         * ConstraintValidator classes must reference distinct target types.
         * If two validators refer to the same type, an exception will occur
         *
         * @return aray of ConstraintValidator classes implementing the constraint
         */
        public Class<? extends ConstraintValidator<?,?>>[] validatedBy();
}</pre><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Constraint annotations can target any of the following <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ElementType</tt>s:</p><div class="itemizedlist" style="font-family: sans-serif; font-size: 14px; "><ul type="disc" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">FIELD</tt> for constrained attributes</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">METHOD</tt> for constrained getters</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">TYPE</tt> for constrained beans</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ANNOTATION_TYPE</tt> for constraints composing other constraints</p></li></ul></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">While other <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ElementType</tt>s are not forbidden, the provider does not have to recognize and process constraints placed on such types.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Since a given constraint definition applies to one or more specific Java types, the JavaDoc for the constraint annotation should clearly state which types are supported. Applying a constraint annotation to an incompatible type will raise a <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">UnexpectedTypeForConstraintException</tt>. Care should be taken on defining the list of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt>. The type resolution algorithm (see <a href="file:///Users/manu/projects/specs/303/specbook/build/en/html_single/index.html#typevalidatorresolution" title="3.5.3. ConstraintValidator resolution algorithm" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Section 3.5.3, “ConstraintValidator resolution algorithm”</a>) could lead to exceptions due to ambiguity.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><br></p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">[...]</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><br></p><div style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><br class="webkit-block-placeholder"></div><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h2 class="title" style="clear: both; font-family: sans-serif; color: rgb(0, 51, 153); font-size: 140%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">2.4. Constraint validation implementation</h2></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A constraint validation implementation performs the validation of a given constraint annotation for a given type. The implementation classes are specified by the <tt class="literal" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">validatedBy</tt> element of the<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Contraint</tt> annotation that decorates the constraint definition. The constraint validation implementation implements the <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> interface.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="d0e560" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example 2.10. ConstraintValidator interface</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">/**
* Defines the logic to validate a given constraint A
* for a given object type T.
* Implementations must comply to the following restriction:
* T must resolve to a non parameterized type
*
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*/
public interface ConstraintValidator<A extends Annotation, T> {
        /**
         * Validator parameters for a given constraint definition
         * Annotations parameters are passed as key/value into parameters
         * <p/>
         * This method is guaranteed to be called before any of the other Constraint
         * implementation methods
         *
         * @param constraintAnnotation parameters for a given constraint definition
         */
        void initialize(A constraintAnnotation);
        /**
         * Implement the validation constraint.
         * <code>object</code> state must not be changed by a Constraint implementation
         *
         * @param object object to validate
         * @param constraintValidatorContext context in which the constraint is evaluated
         *
         * @return false if <code>object</code> does not pass the constraint
         */
        boolean isValid(T object, ConstraintValidatorContext constraintValidatorContext);
}</pre></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Some restrictions apply on the generic type <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> (used in the <tt class="methodname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">isValid</tt> method). T must resolve in a non parameterized type:</p><div class="itemizedlist" style="font-family: sans-serif; font-size: 14px; "><ul type="disc" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">the type is not using generics</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">because the raw type is used instead of the generic version</p></li></ul></div><div class="warning" style="margin-left: 0.5in; margin-right: 0.5in; font-family: sans-serif; font-size: 14px; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; background-color: rgb(251, 218, 218); "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">Warning</h3><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Should we support unbounded wildcards?</p></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Here are some examples of valid definitions in <a href="file:///Users/manu/projects/specs/303/specbook/build/en/html_single/index.html#example-constraintsdefinitionimplementation-validationimplementation-validdef" title="Example 2.11. Valid ConstraintValidator definitions" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Example 2.11, “Valid ConstraintValidator definitions”</a>.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="example-constraintsdefinitionimplementation-validationimplementation-validdef" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example 2.11. Valid ConstraintValidator definitions</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">//String is not making use of generics
public class SizeValidatorForString implements<Size, String> {...}
//Collection uses generics but the raw type is used
public class SizeValidatorForCollection implements<Size, Collection> {...}</pre></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">And some invalid definitions in <a href="file:///Users/manu/projects/specs/303/specbook/build/en/html_single/index.html#example-constraintsdefinitionimplementation-validationimplementation-invaliddef" title="Example 2.12. Invalid ConstraintValidator definitions" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Example 2.12, “Invalid ConstraintValidator definitions”</a>.</p><div class="example" style="font-family: sans-serif; font-size: 14px; "><a name="example-constraintsdefinitionimplementation-validationimplementation-invaliddef" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Example 2.12. Invalid ConstraintValidator definitions</b></p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">//parameterized type
public class SizeValidatorForString implements<Size, Collection<String> {...}
//parameterized type using unbounded wildcard
public class SizeValidatorForCollection implements<Size, Collection<?>> {...}
//parameterized type using bounded wildcard
public class SizeValidatorForCollection implements<Size, Collection<? extends Address>> {...}</pre></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in; font-family: sans-serif; font-size: 14px; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; background-color: rgb(255, 255, 204); "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">Note</h3><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">This restriction is not a theoretical limitation and a future version of the specification will likely allow that in the future.</p><div><br></div><div><br></div><div><br></div></div><div><br class="webkit-block-placeholder"></div></span></div><div><br></div><div>[...]</div><div><br></div><div><br></div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 14px; "><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">3.5.3. ConstraintValidator resolution algorithm</h3></div></div><div style="font-family: sans-serif; font-size: 14px; "></div></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A constraint is associated to one or more <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> implementations. Each <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, T></tt> accepts the type <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt>. The <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> executed depends on the type declared by the target hosting the constraint. For a given constraint evaluation, a single <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> is considered.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">If the constraint is hosted on a class or an interface, the targeted type is the class or the interface. If the constraint is hosted on a class attribute, the type of the attribute is the targeted type. If the constraint is hosted on a getter, the return type of the getter is the targeted type.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The rules written below describe formally the following statement: the <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> chosen to validate a declared type <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is the one where the type supported by the<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> is a supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> and where there is no other <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> whose supported type is a supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> and not a supertype of the chosen<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> supported type.</p><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">When validating a constraint A placed on a target declaring the type <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt>, the following resolution rules apply.</p><div class="itemizedlist" style="font-family: sans-serif; font-size: 14px; "><ul type="disc" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Primitive types are considered equivalent to their respective primitive wrapper class.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, U></tt> is said to be <span class="emphasis" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><em style="font-family: sans-serif; font-size: 14px; ">compliant</em></span> with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> if <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is a subtype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> (according to the<a href="http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10" target="_top" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "> Java Language Specification 3rd edition chapter 4.10 Subtyping</a>). Note that <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is a subtype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> if <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> = <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt>.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">If no <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> compliant with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is found amongst the <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt>s listed by the constraint <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">A</tt>, a <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">UnexpectedTypeForConstraintException</tt> is raised.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, U></tt> compliant with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is considered <span class="emphasis" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><em style="font-family: sans-serif; font-size: 14px; ">strictly more specific</em></span> than a <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, V></tt> compliant with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> if <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> is a strict subtype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">V</tt>. <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> is a strict subtype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">V</tt> if <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> is a subtype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">V</tt> and <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">U</tt> != <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">V</tt> (according to the<a href="http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10" target="_top" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); ">Java Language Specification 3rd edition chapter 4.10 Subtyping</a>).</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">A <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, U></tt> compliant with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is considered maximally specific if no other <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, V></tt> compliant with <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">T</tt> is strictly more specific than<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator<A, U></tt>.</p></li><li style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); "><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">If more than one maximally specific <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> is found, a <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">AmbiguousConstraintUsageException</tt> is raised.</p></li></ul></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in; font-family: sans-serif; font-size: 14px; padding-bottom: 5px; padding-left: 5px; padding-right: 5px; background-color: rgb(255, 255, 204); "><h3 class="title" style="font-family: sans-serif; color: rgb(0, 51, 153); font-size: 120%; margin-top: 10px; padding-top: 5px; font-weight: bold; ">Note</h3><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">While the Java compiler itself cannot determine if a constraint declaration will lead to a <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">UnexpectedTypeForConstraintException</tt> or a<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">AmbiguousConstraintUsageException</tt>, rules can be statically checked. A tool such as an IDE or a Java 6 annotation processor can apply these rules and prevent a compilation in case of ambiguity. The specification encourages Bean Validation provider to provide such a tool to their users.</p></div><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Let's see a couple of declaration their respective <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> resolution. Assuming the following definitions:</p><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; ">[...]
@Constraint(validatedBy={
SizeValidatorForCollection.class,
SizeValidatorForSet.class,
SizeValidatorForSerializable.class })
public @interface Size { ...}
public class SizeValidatorForCollection implements ConstraintValidator<Size, Collection> { ... }
public class SizeValidatorForSet implements ConstraintValidator<Size, Set> { ... }
public class SizeValidatorForSerializable implements ConstraintValidator<Size, Serializable> { ... }
public interface SerializableCollection extends Serializable, Collection {}</pre><p style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">The following resolutions occur.</p><div class="table" style="font-family: sans-serif; font-size: 14px; "><a name="d0e1999" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 204); "></a><p class="title" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); margin-top: 10px; padding-top: 5px; font-weight: bold; "><b style="font-family: sans-serif; font-size: 14px; ">Table 3.1. Resolution of ConstraintValidator for various constraints declarations</b></p><table summary="Resolution of ConstraintValidator for various constraints
declarations" border="1" style="font-family: sans-serif; font-size: 14px; border-collapse: collapse; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; empty-cells: hide; width: 100%; "><colgroup style="font-family: sans-serif; font-size: 14px; "><col align="center" style="font-family: sans-serif; font-size: 14px; "><col style="font-family: sans-serif; font-size: 14px; "></colgroup><thead style="font-family: sans-serif; font-size: 14px; "><tr style="font-family: sans-serif; font-size: 14px; "><th align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Declaration</th><th style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); ">Resolution</th></tr></thead><tbody style="font-family: sans-serif; font-size: 14px; "><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size Collection getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SizeValidatorForCollection</tt>: direct match</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size Collection<?> getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SizeValidatorForCollection</tt>: <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection</tt> is a direct supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection<?></tt></td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size Collection<Address> getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SizeValidatorForCollection</tt>: <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection</tt> is a direct supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection<Address></tt></td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size Set<Address> getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SizeValidatorForSet</tt>: direct supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Set<Address></tt></td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size SortedSet<Address> getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SizeValidatorForSet</tt>: <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Set</tt> is the closest supertype of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SortedSet<Address></tt></td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size SerializableCollection getAddresses() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">AmbiguousConstraintUsageException</tt><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">SerializableCollection</tt> is a subtype of both <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection</tt> and <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Serializable</tt> and neither<tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Collection</tt> nor <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">Serializable</tt> are subtypes of each other.</td></tr><tr style="font-family: sans-serif; font-size: 14px; "><td align="center" style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="code" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">@Size String getName() { ... }</tt></td><td style="font-family: sans-serif; font-size: 14px; color: rgb(0, 0, 0); padding-top: 4pt; padding-right: 4pt; padding-bottom: 4pt; padding-left: 4pt; "><tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">UnexpectedTypeForConstraintException</tt> none of the <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">ConstraintValidator</tt> types are supertypes of <tt class="classname" style="font-size: 100%; color: rgb(17, 17, 17); font-family: monospace; ">String</tt>.</td></tr></tbody></table></div></div></div><div class="section" lang="en" style="font-family: sans-serif; font-size: 14px; "><div class="titlepage" style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "><div style="font-family: sans-serif; font-size: 14px; "></div></div></div></div></span></div><div><br></div><div><br></div><div><br></div><div>[...]</div><div><br></div><div><span class="Apple-style-span" style="font-family: -webkit-sans-serif; font-size: 14px; "><pre class="programlisting" style="font-size: 100%; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); background-color: rgb(244, 244, 244); font-family: monospace; width: auto; position: static; z-index: auto; ">public interface ConstraintDescriptor {
        /**
         * Returns the annotation describing the constraint declaration.
         * If a composing constraint, parameter values are reflecting
         * the overridden parameters from the main constraint
         *
         * @return The annotation for this constraint.
         */
        Annotation getAnnotation();
        /**
         * @return The groups the constraint is applied on.
         */
        Set<Class<?>> getGroups();
        /**
         * @return the constraint validation implementation class
         */
        Class<? extends ConstraintValidator<?,?>>[]
         getConstraintValidatorClasses();</pre></span></div><div><div>On Jan 23, 2009, at 15:13, Emmanuel Bernard wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Today, ConstraintValidator accepts Object and the implementation is responsible for handling the casting and raise an exception if the type is not supported.</div><div><br></div><div>The idea is to get type-safe validator and a discovery mechanism to associate a validator to a given runtime type being validated. The resolution is not 100% complete, you might end up with:</div><div> - no valid validator</div><div> - no way to decide between two or more validators</div><div>and get exceptions at runtime.</div><div><br></div><div>I would really like feedback on it as we could arrange some of these rules to not fail (at least in the latter case):</div><div> - do we want this type-safe + auto resolution algorithm strategy or should we stick with the untyped solution</div><div> - do we want to fail in case of ambiguity or rather choose the first compatible provider?</div><div><br></div><div>Personally I find the feature quite elegant and the metadata can be used by tools to warn a user if a constraint does not match the static type it is applied on.</div><div><br></div><div><b>API and declaration<br></b><div><br></div><div>A more typesafe proposal would be:</div><div><br></div><div>public interface ConstraintValidator<A extends Annotation, T> {</div><div> void initialize(A annotation);</div><div> boolean isValid(T object, ConstraintValidationContext context);</div><div>}</div><div><br></div><div>public class StringSizeValidator implements ConstraintValidator<Size, String> {</div><div> ...</div><div>}</div><div><br></div><div><div>public class CollectionSizeValidator implements ConstraintValidator<Size, Collection> {</div><div> ...</div><div>}</div><div><br></div><div><div>public class MapSizeValidator implements ConstraintValidator<Size, Map> {</div><div> ...</div><div>}</div></div><div><br></div><div><div>public class ArraySizeValidator implements ConstraintValidator<Size, Object[]> {</div><div> ...</div><div>}</div><br></div></div><div><br></div><div>@Constraint(validatedBy={</div><div> StringSizeValidator.class, CollectionSizeValidator.class, </div><div> MapSizeValidator.class, ArraySizeValidator.class} )</div><div>public @interface Size { ... }</div><div><br></div><div>We then need to decide at runtime, which validator needs to be executed.</div><div>Here is a proposed algorithm heavily based on the Java Language Specification (boy it's hard to read it).</div><div><br></div><div><b>Resolution algorithm</b></div><div>The type T of a ConstraintValidator must not make direct use of generics itself.</div><div><br></div><div><i>This is because the algorithm compare the actual type at runtime and such notion would be lost. So you can do ConstraintValidator<Size, Collection> but not ConstraintValidator<Size, Collection<String>>.</i></div><div><br></div><div>For a given runtime object t of type T about to be validated for a given constraint:</div><div>if t is null the first validator in the array of available validators is used.</div><div>otherwise</div><div><br></div><div>A validator accepting U is said to be compliant with the type T if T is a subtype of U according to the JLS chapter 4.10.</div><div><br></div><div>If no compliant validator is found for T, a UnexpectedTypeForConstraint exception is raised.</div><div><i>If a validator is taking the responsibility to dispatch types (ie ConstraintValidator<Size,Object>), it must use the same exception in the same circumstances.</i></div><div><br></div><div>If one compliant validator is found, it is used.</div><div><br></div><div>If more than one compliant validator is found, the one with the most specific parameter is used. The informal intuition is that one parameter is more specific than another if any assignment handled by the first parameter could be passed on to the other one without a compile-time type error.</div><div><br></div><div>Of a given type T, a compliant validator accepting U is considered maximally specific if no other T compliant validator accepting V is such as V is a strict subtype of U. String subtype is defined by JSL chapter 4.10.</div><div><br></div><div>If more than one maximally specific validator is found, a AmbiguousValidatorException is raised.</div><div><br></div><div>WDYT?</div></div></div>_______________________________________________<br>hibernate-dev mailing list<br><a href="mailto:hibernate-dev@lists.jboss.org">hibernate-dev@lists.jboss.org</a><br>https://lists.jboss.org/mailman/listinfo/hibernate-dev<br></blockquote></div><br></body></html>