<?xml version="1.0" encoding="UTF-8"?>
<!--
	~ JBoss, Home of Professional Open Source
	~ Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
	~ by the @authors tag. See the copyright.txt in the distribution for a
	~ full listing of individual contributors.
	~
	~ 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.
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../hv.ent">
%BOOK_ENTITIES;
]>
<chapter id="validator-specifics">
  <title>Hibernate Validator Specifics</title>

  <para>In the following sections we are having a closer look at some of the
  Hibernate Validator specific features (features which are not part of the
  Bean Validation specification). This includes the fail fast mode, the
  programmatic constraint configuration API and boolean composition of
  composing constraints.</para>

  <note>
    <para>The features described in the following sections are not portable
    between Bean Validation providers/implementations.</para>
  </note>

  <section>
    <title>Public API</title>

    <para>Let's start, however, with a look at the public API of Hibernate
    Validator. <xref linkend="validator-public-api"/> lists all packages
    belonging to this API and describes their purpose.</para>

    <para>Any packages not listed in that table are internal packages of
    Hibernate Validator and are not intended to be accessed by clients. The
    contents of these internal packages can change from release to release
    without notice, thus possibly breaking any client code relying on
    it.</para>

    <note>
      <para>In the following table, when a package is public its not
      necessarily true for its nested packages.</para>
    </note>

    <table id="validator-public-api">
      <title>Hibernate Validator public API</title>

      <tgroup cols="2">
        <thead>
          <row>
            <entry>Packages</entry>

            <entry>Description</entry>
          </row>
        </thead>

        <tbody valign="top">
          <row>
            <entry><package>org.hibernate.validator</package></entry>

            <entry>This package contains the classes used by the Bean
            Validation bootstrap mechanism (eg. validation provider,
            configuration class). For more details see <xref
            linkend="validator-bootstrapping"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.cfg</package>,
            <package>org.hibernate.validator.cfg.context</package>,
            <package>org.hibernate.validator.cfg.defs</package></entry>

            <entry>With Hibernate Validator you can define constraints via a
            fluent API. These packages contain all classes needed to use this
            feature. In the package
            <package>org.hibernate.validator.cfg</package> you will find the
            <classname>ConstraintMapping</classname> class and in package
            <package>org.hibernate.validator.cfg.defs</package> all constraint
            definitions. For more details see <xref
            linkend="programmaticapi"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.constraints</package>,
            <package>org.hibernate.validator.constraints.br</package></entry>

            <entry>In addition to Bean Validation constraints, Hibernate
            Validator provides some useful custom constraints. These packages
            contain all custom annotation classes. For more details see <xref
            linkend="validator-defineconstraints-hv-constraints"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.group</package>,
            <package>org.hibernate.validator.spi.group</package></entry>

            <entry>With Hibernate Validator you can define dynamic default
            group sequences in function of the validated object state. These
            packages contain all classes needed to use this feature
            (<classname>GroupSequenceProvider</classname> annotation and
            <classname>DefaultGroupSequenceProvider</classname> contract). For
            more details see <xref
            linkend="section-default-group-class"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.messageinterpolation</package>,
            <package>org.hibernate.validator.resourceloading</package>,
            <package>org.hibernate.validator.spi.resourceloading</package></entry>

            <entry>These packages contain the classes related to constraint
            message interpolation. The first package contains two
            implementations of <classname>MessageInterpolator</classname>. The
            first one,
            <classname>ValueFormatterMessageInterpolator</classname> allows to
            interpolate the validated value into the constraint message, see
            <xref linkend="section-message-interpolator"/>. The second
            implementation named
            <classname>ResourceBundleMessageInterpolator</classname> is the
            implementation used by default by Hibernate Validator. This
            implementation relies on a
            <classname>ResourceBundleLocator</classname>, see <xref
            linkend="section-resource-bundle-locator"/>. Hibernate Validator
            provides different <classname>ResourceBundleLocator</classname>
            implementations located in the package
            <package>org.hibernate.validator.resourceloading</package>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.method</package>,
            <package>org.hibernate.validator.method.metadata</package></entry>

            <entry>Hibernate Validator provides support for method-level
            constraints based on appendix C of the Bean Validation
            specification. The first package contains the
            <classname>MethodValidator</classname> interface allowing you to
            validate method return values and parameters. The second package
            contains meta data for constraints hosted on parameters and
            methods which can be retrieved via the
            <classname>MethodValidator</classname>.</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

    <note>
      <para>The public packages of Hibernate Validator fall into two
      categories: while the actual API parts are intended to be
      <emphasis>invoked</emphasis> or <emphasis>used</emphasis> by clients
      (e.g. the API for programmatic constraint declaration or the custom
      constraints), the SPI (service provider interface) packages contain
      interfaces which are intended to be <emphasis>implemented</emphasis> by
      clients (e.g. <classname>ResourceBundleLocator</classname>).</para>
    </note>
  </section>

  <section>
    <title>Fail fast mode</title>

    <para>First off, the fail fast mode. Hibernate Validator allows to return
    from the current validation as soon as the first constraint violation
    occurs. This is called the <emphasis>fail fast mode</emphasis> and can be
    useful for validation of large object graphs where one is only interested
    whether there is a constraint violation or not. <xref
    linkend="example-fail-fast-property"/>, <xref
    linkend="example-fail-fast-configuration"/> and <xref
    linkend="example-fail-fast-factory"/> show multiple ways to enable the
    fail fast mode.</para>

    <example floatstyle="" id="example-fail-fast-property">
      <title>Enabling <option>failFast</option> via a property</title>

      <programlisting language="" role="">HibernateValidatorConfiguration configuration = Validation.byProvider( HibernateValidator.class ).configure();
ValidatorFactory factory = configuration.addProperty( "hibernate.validator.fail_fast", "true" ).buildValidatorFactory();
Validator validator = factory.getValidator();

// do some actual fail fast validation
...</programlisting>
    </example>

    <example id="example-fail-fast-configuration">
      <title>Enabling <option>failFast</option> at the
      <classname>Configuration</classname> level</title>

      <programlisting lang="">HibernateValidatorConfiguration configuration = Validation.byProvider( HibernateValidator.class ).configure();
ValidatorFactory factory = configuration.failFast( true ).buildValidatorFactory();
Validator validator = factory.getValidator();

// do some actual fail fast validation
...</programlisting>
    </example>

    <example id="example-fail-fast-factory">
      <title>Enabling <option>failFast</option> at the
      <classname>ValidatorFactory</classname> level</title>

      <programlisting language="" role="">HibernateValidatorConfiguration configuration = Validation.byProvider( HibernateValidator.class ).configure();
ValidatorFactory factory = configuration.buildValidatorFactory();

Validator validator = factory.getValidator();

// do some non fail fast validation
...

validator = factory.unwrap( HibernateValidatorFactory.class )
            .usingContext()
            .failFast( true )
            .getValidator();

// do fail fast validation
...</programlisting>
    </example>
  </section>

  <section id="validator-customoptions-methodvalidation">
    <title>Method validation</title>

    <para>The Bean Validation API allows to specify constraints for fields,
    properties and types. Hibernate Validator goes one step further and allows
    to place contraint annotations also on method parameters and method return
    values, thus enabling a programming style known as "Programming by
    Contract".</para>

    <para>More specifically this means that Bean Validation constraints can be
    used to specify</para>

    <itemizedlist>
      <listitem>
        <para>the preconditions that must be met before a method invocation
        (by annotating method parameters with constraints) and</para>
      </listitem>

      <listitem>
        <para>the postconditions that are guaranteed after a method invocation
        (by annotating methods)</para>
      </listitem>
    </itemizedlist>

    <para>This approach has several advantages over traditional ways of
    parameter and return value checking:</para>

    <itemizedlist>
      <listitem>
        <para>The checks don't have to be performed manually (e.g. by throwing
        <classname>IllegalArgumentExceptions</classname> or similar),
        resulting in less code to write and maintain.</para>
      </listitem>

      <listitem>
        <para>A method's pre- and postconditions don't have to be expressed
        again in the method's JavaDoc, since the constraint annotations will
        automatically be included in the generated JavaDoc. This avoids
        redundancy and reduces the chance of inconsistencies between
        implementation and documentation.</para>
      </listitem>
    </itemizedlist>

    <note>
      <para>Method validation was also considered to be included in the Bean
      Validation API as defined by JSR 303, but it didn't become part of the
      1.0 version. A basic draft is outlined in appendix C of the
      specification, and the implementation in Hibernate Validator is largely
      influenced by this draft. The feature is considered again for inclusion
      in BV 1.1.</para>
    </note>

    <section>
      <title>Defining method-level constraints</title>

      <para><xref lang="" linkend="example-method-constraints"/> demonstrates
      the definition of method-level constraints.<example
          id="example-method-constraints">
          <title>Using method-level constraints</title>

          <programlisting language="" role="">public class RentalStation {

    @NotNull 
    public Car rentCar(@NotNull Customer customer, @NotNull @Future Date startDate, @Min(1) int durationInDays) { 
        //...
    }
}</programlisting>
        </example></para>

      <para>Here the following pre- and postconditions for the
      <methodname>rentCar()</methodname> method are declared:</para>

      <itemizedlist>
        <listitem>
          <para>The renting customer may not be null</para>
        </listitem>

        <listitem>
          <para>The rental's start date must not be null and must be in the
          future</para>
        </listitem>

        <listitem>
          <para>The rental duration must be at least one day</para>
        </listitem>

        <listitem>
          <para>The returned <classname>Car</classname> instance may not be
          null</para>
        </listitem>
      </itemizedlist>

      <para>Using the <classname>@Valid</classname> annotation it's also
      possible to define that a cascaded validation of parameter or return
      value objects shall be performed. An example can be found in <xref
      lang="" linkend="example-cascaded-method-constraints"/>.</para>

      <example id="example-cascaded-method-constraints">
        <title>Cascaded validation of method-level constraints</title>

        <programlisting language="" role="">public class RentalStation {

    @Valid
    public Set&lt;Rental&gt; getRentalsByCustomer(@Valid Customer customer) { 
        //...
    }
}</programlisting>
      </example>

      <para>Here all the constraints declared at the
      <classname>Customer</classname> type will be evaluated when validating
      the method parameter and all constraints declared at the returned
      <classname>Rental</classname> objects will be evaluated when validating
      the method's return value.</para>

      <section>
        <title>Using method constraints in type hierarchies</title>

        <para>Special care must be taken when defining parameter constraints
        in inheritance hierarchies.</para>

        <para>When a method is overridden in sub-types method parameter
        constraints can only be declared at the base type. The reason for this
        restriction is that the preconditions to be fulfilled by a type's
        client must not be strengthened in sub-types (which may not even be
        known to the base type's client). Note that also if the base method
        doesn't declare any parameter constraints at all, no parameter
        constraints may be added in overriding methods.</para>

        <para>The same restriction applies to interface methods: no parameter
        constraints may be defined at the implementing method (or the same
        method declared in sub-interfaces).</para>

        <para>If a violation of this rule is detected by the validation
        engine, a
        <classname>javax.validation.ConstraintDeclarationException</classname>
        will be thrown. In <xref lang=""
        linkend="example-illegal-method-constraints"/> some examples for
        illegal parameter constraints declarations are shown.</para>

        <example id="example-illegal-method-constraints">
          <title>Illegal parameter constraint declarations</title>

          <programlisting>public class Car {

    public void drive(Person driver) { ... }

}

public class RentalCar extends Car {

    //not allowed, parameter constraint added in overriding method
    public void drive(@NotNull Person driver) { ... }

}

public interface ICar {

    void drive(Person driver);

}

public class CarImpl implements ICar {

    //not allowed, parameter constraint added in implementation of interface method
    public void drive(@NotNull Person driver) { ... }

}</programlisting>
        </example>

        <para>This rule only applies to parameter constraints, return value
        constraints may be added in sub-types without any restrictions as it
        is alright to strengthen the postconditions guaranteed to a type's
        client.</para>
      </section>
    </section>

    <section>
      <title>Evaluating method-level constraints</title>

      <para>To validate method-level constraints Hibernate Validator provides
      the interface
      <classname>org.hibernate.validator.method.MethodValidator</classname>.</para>

      <para>As shown in <xref lang="" linkend="example-methodvalidator"/> this
      interface defines methods for the evaluation of parameter as well as
      return value constraints and for retrieving an extended type descriptor
      providing method constraint related meta data.</para>

      <example id="example-methodvalidator">
        <title>The <classname>MethodValidator</classname> interface</title>

        <programlisting language="" role="">public interface MethodValidator {

    &lt;T&gt; Set&lt;MethodConstraintViolation&lt;T&gt;&gt; validateParameter(T object, Method method, Object parameterValue, int parameterIndex, Class&lt;?&gt;... groups);
    
    &lt;T&gt; Set&lt;MethodConstraintViolation&lt;T&gt;&gt; validateAllParameters(T object, Method method, Object[] parameterValues, Class&lt;?&gt;... groups);
    
    &lt;T&gt; Set&lt;MethodConstraintViolation&lt;T&gt;&gt; validateReturnValue(T object, Method method, Object returnValue, Class&lt;?&gt;... groups);
 
    TypeDescriptor getConstraintsForType(Class&lt;?&gt; clazz);
}    </programlisting>
      </example>

      <para>To retrieve a method validator get hold of an instance of HV's
      <classname>javax.validation.Validator</classname> implementation and
      unwrap it to <classname>MethodValidator</classname> as shown in <xref
      lang="" linkend="example-retrieving-methodvalidator"/>.</para>

      <example id="example-retrieving-methodvalidator">
        <title>Retrieving a <classname>MethodValidator</classname>
        instance</title>

        <programlisting language="" role="">MethodValidator methodValidator = Validation.byProvider( HibernateValidator.class )
    .configure()
    .buildValidatorFactory()
    .getValidator()
    .unwrap( MethodValidator.class ); </programlisting>
      </example>

      <para>The validation methods defined on
      <classname>MethodValidator</classname> each return a
      <classname>Set&lt;MethodConstraintViolation&gt;</classname>. The type
      <classname>MethodConstraintViolation</classname> (see <xref lang=""
      linkend="example-methodconstraintviolation"/>) extends
      <classname>javax.validation.ConstraintViolation</classname> and provides
      additional method level validation specific information such as the
      method and index of the parameter which caused the constraint
      violation.</para>

      <example id="example-methodconstraintviolation">
        <title>The <classname>MethodConstraintViolation</classname>
        type</title>

        <programlisting language="" role="">public interface MethodConstraintViolation&lt;T&gt; extends ConstraintViolation&lt;T&gt; {
    
    public static enum Kind { PARAMETER, RETURN_VALUE }

    Method getMethod();

    Integer getParameterIndex();

    String getParameterName();

    Kind getKind();
}</programlisting>
      </example>

      <note>
        <para>The method <methodname>getParameterName()</methodname> currently
        returns synthetic parameter identifiers such as "arg0", "arg1" etc. In
        a future version of Hibernate Validator support for specifying
        parameter identifiers might be added.</para>
      </note>

      <para>Typically the validation of method-level constraints is not
      invoked manually but automatically upon method invocation by an
      integration layer using AOP (aspect-oriented programming) or similar
      method interception facilities such as the JDK's
      <classname>java.lang.reflect.Proxy</classname> API or CDI ("JSR 299:
      Contexts and Dependency Injection for the
      Java<superscript>TM</superscript> EE platform").</para>

      <para>If a parameter or return value constraint can't be validated
      sucessfully such an integration layer typically will throw a
      <classname>MethodConstraintViolationException</classname> which similar
      to <classname>javax.validation.ConstraintViolationException</classname>
      contains a set with the occurred constraint violations.</para>

      <tip>
        <para>If you are using CDI you might be interested in the <ulink
        url="http://seamframework.org/Seam3/ValidationModule">Seam
        Validation</ulink> project. This Seam module provides an interceptor
        which integrates the method validation functionality with CDI.</para>
      </tip>
    </section>

    <section>
      <title>Retrieving method-level constraint meta data</title>

      <para>As outlined in <xref lang="" linkend="validator-metadata-api"/>
      the Bean Validation API provides rich capabilities for retrieving
      constraint related meta data. Hibernate Validator extends this API and
      allows to retrieve constraint meta data also for method-level
      constraints.</para>

      <para><xref lang="" linkend="example-method-level-meta-data"/> shows how
      to use this extended API to retrieve constraint meta data for the
      <methodname>rentCar()</methodname> method from the
      <classname>RentalStation</classname> type.</para>

      <example id="example-method-level-meta-data">
        <title>Retrieving meta data for method-level constraints</title>

        <programlisting language="" role="">TypeDescriptor typeDescriptor = methodValidator.getConstraintsForType(RentalStation.class)

//retrieve a descriptor for the rentCar() method
MethodDescriptor rentCarMethod = typeDescriptor.getConstraintsForMethod("rentCar", Customer.class, Date.class, int.class);
assertEquals(rentCarMethod.getMethodName(), "rentCar");
assertTrue(rentCarMethod.hasConstraints());
assertFalse(rentCarMethod.isCascaded());

//retrieve constraints from the return value
Set&lt;ConstraintDescriptor&lt;?&gt;&gt; returnValueConstraints = rentCarMethod.findConstraints().getConstraintDescriptors();
assertEquals(returnValueConstraints.size(), 1);
assertEquals(returnValueConstraints.iterator().next().getAnnotation().annotationType(), NotNull.class);

List&lt;ParameterDescriptor&gt; allParameters = rentCarMethod.getParameterDescriptors();
assertEquals(allParameters.size(), 3);

//retrieve a descriptor for the startDate parameter
ParameterDescriptor startDateParameter = allParameters.get(1);
assertEquals(startDateParameter.getIndex(), 1);
assertFalse(startDateParameter.isCascaded());
assertEquals(startDateParameter.findConstraints().getConstraintDescriptors().size(), 2);</programlisting>
      </example>

      <para>Refer to the <ulink
      url="http://docs.jboss.org/hibernate/validator/4.2/api/index.html?org/hibernate/validator/method/metadata/package-summary.html">JavaDoc</ulink>
      of the package
      <classname>org.hibernate.validator.method.metadata</classname> for more
      details on the extended meta data API.</para>
    </section>
  </section>

  <section id="programmaticapi">
    <title>Programmatic constraint definition</title>

    <para>Another addition to the Bean Validation specification is the ability
    to configure constraints via a fluent API. This API can be used
    exclusively or in combination with annotations and xml. If used in
    combination programmatic constraints are additive to constraints
    configured via the standard configuration capabilities.</para>

    <para>The API is centered around the
    <classname>ConstraintMapping</classname> class which can be found in the
    package<package> org.hibernate.validator.cfg</package>. Starting with the
    instantiation of a new <classname>ConstraintMapping</classname>,
    constraints can be defined in a fluent manner as shown in <xref lang=""
    linkend="example-constraint-mapping"/>.</para>

    <para><example id="example-constraint-mapping">
        <title>Programmatic constraint definition</title>

        <programlisting language="" role="">ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Car.class )
    .property( "manufacturer", FIELD )
        .constraint( new NotNullDef() )
    .property( "licensePlate", FIELD )
        .constraint( new NotNullDef() )
        .constraint( new SizeDef().min( 2 ).max( 14 ) )
    .property( "seatCount", FIELD )
        .constraint( new MinDef()value ( 2 ) )
.type( RentalCar.class )
    .property( "rentalStation", METHOD )
        .constraint( new NotNullDef() );      </programlisting>
      </example></para>

    <para>As you can see constraints can be configured on multiple classes and
    properties using method chaining. The constraint definition classes
    <classname>NotNullDef</classname>, <classname>SizeDef</classname> and
    <classname>MinDef</classname> are helper classes which allow to configure
    constraint parameters in a type-safe fashion. Definition classes exist for
    all built-in constraints in the
    <classname>org.hibernate.validator.cfg.defs</classname> package.</para>

    <para>For custom constraints you can either create your own definition
    classes extending <classname>ConstraintDef</classname> or you can use
    <classname>GenericConstraintDef</classname> as seen in <xref
    linkend="example-generic-constraint-mapping"/>.</para>

    <para><example id="example-generic-constraint-mapping">
        <title>Programmatic constraint definition using
        <methodname>createGeneric()</methodname></title>

        <programlisting language="" role="">ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Car.class )
    .property( "licensePlate", FIELD )
        .constraint( new GenericConstraintDef&lt;CheckCase.class&gt;( CheckCase.class ).param( "value", CaseMode.UPPER ) );   </programlisting>
      </example></para>

    <para>Not only standard class- and property-level constraints but also
    method constraints can be configured using the API. As shown in <xref
    lang="" linkend="example-method-constraint-mapping"/> methods are
    identified by their name and their parameters (if there are any). Having
    selected a method, constraints can be placed on the method's parameters
    and/or return value.</para>

    <example id="example-method-constraint-mapping">
      <title>Programmatic definition of method constraints</title>

      <programlisting language="" role="">ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Car.class )
    .method( "drive", String.class, Integer.class )
        .parameter( 0 )
            .constraint( new NotNullDef() )
            .constraint( new MinDef().value ( 1 ) )
        .parameter( 1 )
            .constraint( new NotNullDef() )
        .returnValue()
            .constraint( new NotNullDef() )
    .method( "check" )
        .returnValue()
            .constraint( new NotNullDef() );      </programlisting>
    </example>

    <para>Using the API it's also possible to mark properties, method
    parameters and method return values as cascading (equivalent to annotating
    them with <classname>@Valid</classname>). An example can be found in <xref
    lang="" linkend="example-cascading-constraints"/>.</para>

    <para><example id="example-cascading-constraints">
        <title>Marking constraints for cascaded validation</title>

        <programlisting language="" role="">ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Car.class )
    .property( "manufacturer", FIELD )
        .valid()
    .property( "licensePlate", METHOD )
        .valid()
    .method( "drive", String.class, Integer.class )
        .parameter( 0 )
            .valid()
        .parameter( 1 )
            .valid()
        .returnValue()
            .valid()
.type( RentalCar.class )
    .property( "rentalStation", METHOD )
        .valid();</programlisting>
      </example></para>

    <para>Last but not least you can configure the default group sequence or
    the default group sequence provider of a type as shown in <xref lang=""
    linkend="example-sequences"/>.<example id="example-sequences">
        <title>Configuration of default group sequence and default group
        sequence provider</title>

        <programlisting language="" role="">ConstraintMapping mapping = new ConstraintMapping();
mapping.type( Car.class )
    .defaultGroupSequence( Car.class, CarChecks.class )
.type( RentalCar.class )
    .defaultGroupSequenceProvider( RentalCarGroupSequenceProvider.class ); </programlisting>
      </example></para>

    <para>Once a <classname>ConstraintMapping</classname> is set up it has to
    be passed to the configuration. Since the programmatic API is not part of
    the official Bean Validation specification you need to get hold of a
    <classname>HibernateValidatorConfiguration</classname> instance as shown
    in <xref linkend="example-hibernate-specific-config"/>.</para>

    <para><example id="example-hibernate-specific-config">
        <title>Creating a Hibernate Validator specific configuration</title>

        <programlisting lang="" language="" role="">ConstraintMapping mapping = new ConstraintMapping();
// configure mapping instance

HibernateValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure();
config.addMapping( mapping );
ValidatorFactory factory = config.buildValidatorFactory();
Validator validator = factory.getValidator();</programlisting>
      </example></para>
  </section>

  <section>
    <title>Boolean composition for constraint composition</title>

    <para>As per Bean Validation specification the constraints of a composed
    constraint (see <xref linkend="section-constraint-composition"/>) are all
    combined via a logical <emphasis>AND</emphasis>. This means all of the
    composing constraints need to return <constant>true</constant> in order
    for an overall successful validation. Hibernate Validator offers an
    extension to this logical <emphasis>AND</emphasis> combination which
    allows you to compose constraints via a logical <emphasis>OR</emphasis> or
    <emphasis>NOT</emphasis>. To do so you have to use the
    <classname>ConstraintComposition</classname> annotation and the enum
    <classname>CompositionType</classname> with its values
    <emphasis>AND</emphasis>, <emphasis>OR</emphasis> and
    <emphasis>ALL_FALSE</emphasis>. <xref
    linkend="example-boolean-constraint-composition"/> shows how to build a
    composing constraint where only one of the constraints has to be
    successful in order to pass the validation. Either the validated string is
    all lowercased or it is between two and three characters long.</para>

    <example id="example-boolean-constraint-composition">
      <title>OR composition of constraints</title>

      <programlisting language="JAVA" role="JAVA"><emphasis role="bold">@ConstraintComposition(OR)</emphasis>
@Pattern(regexp = "[a-z]")
@Size(min = 2, max = 3)
@ReportAsSingleViolation
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = { })
public @interface PatternOrSize {
   public abstract String message() default "{PatternOrSize.message}";
   public abstract Class&lt;?&gt;[] groups() default { };
   public abstract Class&lt;? extends Payload&gt;[] payload() default { };
}</programlisting>
    </example>

    <tip>
      <para>Using <emphasis>ALL_FALSE</emphasis> as composition type
      implicitly enforces that only a single violation will get reported in
      case validation of the constraint composition fails.</para>
    </tip>
  </section>
</chapter>
