[hibernate-commits] Hibernate SVN: r15247 - in validator/trunk: hibernate-validator and 43 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Oct 2 06:39:46 EDT 2008


Author: hardy.ferentschik
Date: 2008-10-02 06:39:39 -0400 (Thu, 02 Oct 2008)
New Revision: 15247

Added:
   validator/trunk/hibernate-validator/
   validator/trunk/hibernate-validator/pom.xml
   validator/trunk/hibernate-validator/src/
   validator/trunk/hibernate-validator/src/main/
   validator/trunk/hibernate-validator/src/main/java/
   validator/trunk/hibernate-validator/src/main/java/org/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/HibernateValidatorBuilder.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/Version.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmpty.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmptyConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNull.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNullConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Pattern.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/PatternConstraint.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ContextImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProvider.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorMetaData.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintFactoryImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ElementDescriptorImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/InvalidConstraintImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ResourceBundleMessageResolver.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/IdentitySet.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/LoggerFactory.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java
   validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
   validator/trunk/hibernate-validator/src/main/resources/
   validator/trunk/hibernate-validator/src/main/resources/META-INF/
   validator/trunk/hibernate-validator/src/main/resources/META-INF/services/
   validator/trunk/hibernate-validator/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider
   validator/trunk/hibernate-validator/src/main/resources/org/
   validator/trunk/hibernate-validator/src/main/resources/org/hibernate/
   validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/
   validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties
   validator/trunk/hibernate-validator/src/site/
   validator/trunk/hibernate-validator/src/site/site.xml
   validator/trunk/hibernate-validator/src/test/
   validator/trunk/hibernate-validator/src/test/java/
   validator/trunk/hibernate-validator/src/test/java/org/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/LengthConstraintTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotEmptyConstraintTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotNullConstraintTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternConstraintTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Actor.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Address.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Animal.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Author.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Book.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Boy.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Customer.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Engine.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/EnglishDictonary.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Order.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Person.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Unconstraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroups.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroupsConstraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessage.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessageConstraint.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/IdentitySetTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java
   validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java
   validator/trunk/hibernate-validator/src/test/resources/
   validator/trunk/hibernate-validator/src/test/resources/log4j.properties
   validator/trunk/pom.xml
   validator/trunk/src/
   validator/trunk/src/site/
   validator/trunk/src/site/site.xml
   validator/trunk/validation-api/
   validator/trunk/validation-api/pom.xml
   validator/trunk/validation-api/src/
   validator/trunk/validation-api/src/main/
   validator/trunk/validation-api/src/main/java/
   validator/trunk/validation-api/src/main/java/javax/
   validator/trunk/validation-api/src/main/java/javax/validation/
   validator/trunk/validation-api/src/main/java/javax/validation/Constraint.java
   validator/trunk/validation-api/src/main/java/javax/validation/ConstraintDescriptor.java
   validator/trunk/validation-api/src/main/java/javax/validation/ConstraintFactory.java
   validator/trunk/validation-api/src/main/java/javax/validation/ConstraintValidator.java
   validator/trunk/validation-api/src/main/java/javax/validation/Context.java
   validator/trunk/validation-api/src/main/java/javax/validation/ElementDescriptor.java
   validator/trunk/validation-api/src/main/java/javax/validation/GroupSequence.java
   validator/trunk/validation-api/src/main/java/javax/validation/GroupSequences.java
   validator/trunk/validation-api/src/main/java/javax/validation/InvalidConstraint.java
   validator/trunk/validation-api/src/main/java/javax/validation/MessageResolver.java
   validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraint.java
   validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraintDescriptor.java
   validator/trunk/validation-api/src/main/java/javax/validation/Valid.java
   validator/trunk/validation-api/src/main/java/javax/validation/Validation.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidationException.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidationProviderResolver.java
   validator/trunk/validation-api/src/main/java/javax/validation/Validator.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java
   validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java
   validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/
   validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/DefaultValidationProviderResolver.java
   validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/GenericBuilderFactory.java
   validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/SpecializedBuilderFactory.java
   validator/trunk/validation-api/src/main/java/javax/validation/spi/
   validator/trunk/validation-api/src/main/java/javax/validation/spi/BootstrapState.java
   validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidationProvider.java
   validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidatorBuilderImplementor.java
   validator/trunk/validation-api/src/main/resources/
   validator/trunk/validation-api/src/site/
   validator/trunk/validation-api/src/site/site.xml
   validator/trunk/validation-api/src/test/
   validator/trunk/validation-api/src/test/java/
   validator/trunk/validation-api/src/test/resources/
Modified:
   validator/trunk/hibernate-validator-legacy/
Log:
Imported the bean validation code from https://svn.jboss.org/repos/beancheck. I just copied the current state. The history of the bean validation code is not available.


Property changes on: validator/trunk/hibernate-validator
___________________________________________________________________
Name: svn:ignore
   + target


Added: validator/trunk/hibernate-validator/pom.xml
===================================================================
--- validator/trunk/hibernate-validator/pom.xml	                        (rev 0)
+++ validator/trunk/hibernate-validator/pom.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>hibernate-validator-parent</artifactId>
+        <groupId>org.hibernate</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.hibernate</groupId>
+    <artifactId>hibernate-validator</artifactId>
+    <name>Hibernate Validator</name>
+    <distributionManagement>
+        <site>
+          <id>local</id>
+          <url>file:///Users/hardy/Sites/${artifactId}</url>
+        </site>
+    </distributionManagement>
+    <dependencies>
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>runtime</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/HibernateValidatorBuilder.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/HibernateValidatorBuilder.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/HibernateValidatorBuilder.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,12 @@
+package org.hibernate.validation;
+
+import javax.validation.ValidatorBuilder;
+
+/**
+ * Uniquely identify Hibernate Validator in the Bean Validation bootstrap strategy
+ * Also contains Hibernate Validator specific configurations
+ * 
+ * @author Emmanuel Bernard
+ */
+public interface HibernateValidatorBuilder extends ValidatorBuilder<HibernateValidatorBuilder> {
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/Version.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/Version.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/Version.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,61 @@
+// $Id: Version.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation;
+
+import java.net.URL;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+import org.slf4j.Logger;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Version {
+	private static final Logger log = org.hibernate.validation.util.LoggerFactory.make();
+
+	static {
+		Class clazz = Version.class;
+		String classFileName = clazz.getSimpleName() + ".class";
+		String classFilePath = clazz.getCanonicalName().replace( '.', '/' )
+				+ ".class";
+		String pathToThisClass =
+				clazz.getResource( classFileName ).toString();
+		String pathToManifest = pathToThisClass.substring( 0, pathToThisClass.indexOf( classFilePath ) - 1 )
+				+ "/META-INF/MANIFEST.MF";
+		log.trace( "Manifest file {}", pathToManifest );
+		Manifest manifest = null;
+		String version;
+		try {
+			manifest = new Manifest( new URL( pathToManifest ).openStream() );
+		}
+		catch ( Exception e ) {
+			log.warn( "Unable to determine version of Hibernate Validator" );
+		}
+		if ( manifest == null ) {
+			version = "?";
+		}
+		else {
+			version = manifest.getMainAttributes().getValue( Attributes.Name.IMPLEMENTATION_VERSION );
+		}
+		log.info( "Hibernate Commons Annotations {}", version );
+	}
+
+	public static void touch() {
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,46 @@
+// $Id: Length.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * Validate that the string is between min and max included
+ *
+ * @author Emmanuel Bernard
+ */
+ at Documented
+ at ConstraintValidator(LengthConstraint.class)
+ at Target({ METHOD, FIELD, TYPE })
+ at Retention(RUNTIME)
+public @interface Length {
+	public abstract int min() default 0;
+
+	public abstract int max() default Integer.MAX_VALUE;
+
+	public abstract String message() default "{validator.length}";
+
+	public abstract String[] groups() default { };
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/LengthConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,64 @@
+// $Id: LengthConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import javax.validation.Constraint;
+import javax.validation.StandardConstraint;
+import javax.validation.StandardConstraintDescriptor;
+import javax.validation.Context;
+
+/**
+ * Check that a string's length is between min and max.
+ *
+ * @author Emmanuel Bernard
+ * @author Gavin King
+ */
+public class LengthConstraint implements Constraint<Length>, StandardConstraint {
+	private int min;
+	private int max;
+
+	public void initialize(Length parameters) {
+		min = parameters.min();
+		max = parameters.max();
+	}
+
+	public boolean isValid(Object value, Context context) {
+		if ( value == null ) {
+			return true;
+		}
+		if ( !( value instanceof String ) ) {
+			throw new IllegalArgumentException( "Expected String type." );
+		}
+		String string = ( String ) value;
+		int length = string.length();
+		return length >= min && length <= max;
+	}
+
+	public StandardConstraintDescriptor getStandardConstraints() {
+		return new StandardConstraintDescriptor() {
+			public Integer getLength() {
+				if ( max == Integer.MAX_VALUE ) {
+					return null;
+				}
+				else {
+					return max;
+				}
+			}
+		};
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmpty.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmpty.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmpty.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,39 @@
+// $Id: NotEmpty.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Documented
+ at ConstraintValidator(NotEmptyConstraint.class)
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface NotEmpty {
+	public abstract String message() default "{validator.notEmpty}";
+
+	public abstract String[] groups() default { };
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmptyConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmptyConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotEmptyConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,43 @@
+// $Id: NotEmptyConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import javax.validation.Constraint;
+import javax.validation.Context;
+
+/**
+ * @author Hardy Ferentschik
+ * @todo Extend to not only support strings, but also collections and maps. Needs to be specified first though.
+ */
+public class NotEmptyConstraint implements Constraint<NotEmpty> {
+
+	public void initialize(NotEmpty parameters) {
+	}
+
+	public boolean isValid(Object object, Context context) {
+		if ( object == null ) {
+			return true;
+		}
+		if ( !( object instanceof String ) ) {
+			throw new IllegalArgumentException( "Expected String type." );
+		}
+		String string = ( String ) object;
+		int length = string.length();
+		return length > 0;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNull.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNull.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNull.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,39 @@
+// $Id: NotNull.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * @author Emmanuel Bernard
+ */
+ at Documented
+ at ConstraintValidator(NotNullConstraint.class)
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface NotNull {
+	public abstract String message() default "{validator.notNull}";
+
+	public abstract String[] groups() default { };
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNullConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNullConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/NotNullConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+// $Id: NotNullConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import javax.validation.Constraint;
+import javax.validation.Context;
+
+/**
+ * Validate that the object is not <code>null</code>.
+ *
+ * @author Emmanuel Bernard
+ */
+public class NotNullConstraint implements Constraint<NotNull> {
+
+	public void initialize(NotNull parameters) {
+	}
+
+	public boolean isValid(Object object, Context context) {
+		return object != null;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Pattern.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Pattern.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Pattern.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,50 @@
+// $Id: Pattern.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at ConstraintValidator(PatternConstraint.class)
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface Pattern {
+	public abstract String message() default "{validator.pattern}";
+
+	public abstract String[] groups() default { };
+
+	/**
+	 * @return the regular expression the annotated string must match.
+	 */
+	String regex();
+
+	/**
+	 * @return Additioanl regular expression processing flags. Default is 0.
+	 */
+	int flags() default 0;
+}
+

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/PatternConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/PatternConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/PatternConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,49 @@
+// $Id: PatternConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.util.regex.Matcher;
+import javax.validation.Constraint;
+import javax.validation.Context;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class PatternConstraint implements Constraint<Pattern> {
+
+	private java.util.regex.Pattern pattern;
+
+	public void initialize(Pattern parameters) {
+		pattern = java.util.regex.Pattern.compile(
+				parameters.regex(),
+				parameters.flags()
+		);
+	}
+
+	public boolean isValid(Object value, Context context) {
+		if ( value == null ) {
+			return true;
+		}
+		if ( !( value instanceof String ) ) {
+			throw new IllegalArgumentException( "Expected String type." );
+		}
+		String string = ( String ) value;
+		Matcher m = pattern.matcher( string );
+		return m.matches();
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Patterns.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,35 @@
+// $Id: Patterns.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface Patterns {
+	Pattern[] value();
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ContextImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ContextImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,69 @@
+package org.hibernate.validation.engine;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import javax.validation.Context;
+import javax.validation.ConstraintDescriptor;
+
+import org.hibernate.validation.impl.ConstraintDescriptorImpl;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ContextImpl implements Context {
+	private final ConstraintDescriptor constraintDescriptor;
+	private final List<ErrorMessage> errorMessages;
+	private boolean defaultDisabled;
+
+	public ContextImpl(ConstraintDescriptorImpl constraintDescriptor) {
+		this.constraintDescriptor = constraintDescriptor;
+		this.errorMessages = new ArrayList<ErrorMessage>(3);
+	}
+
+	public void disableDefaultError() {
+		defaultDisabled = true;
+	}
+
+	public String getDefaultErrorMessage() {
+		return ( String ) constraintDescriptor.getParameters().get("message");
+	}
+
+	public void addError(String message) {
+		//FIXME get the default property if property-level
+		errorMessages.add( new ErrorMessage( message, null ) );
+	}
+
+	public void addError(String message, String property) {
+		//FIXME: make sure the property is valid
+		errorMessages.add( new ErrorMessage( message, property ) );
+	}
+
+	public List<ErrorMessage> getErrorMessages() {
+		List<ErrorMessage> returnedErrorMessages = new ArrayList<ErrorMessage>( errorMessages.size() + 1 );
+		Collections.copy( returnedErrorMessages, errorMessages );
+		if ( ! defaultDisabled ) {
+			//FIXME get the default property if property-level
+			returnedErrorMessages.add( new ErrorMessage( getDefaultErrorMessage(), null) );
+		}
+		return returnedErrorMessages;
+	}
+
+	public static class ErrorMessage {
+		private final String message;
+		private final String property;
+
+		private ErrorMessage(String message, String property) {
+			this.message = message;
+			this.property = property;
+		}
+
+		public String getMessage() {
+			return message;
+		}
+
+		public String getProperty() {
+			return property;
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProvider.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProvider.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProvider.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,79 @@
+// $Id: MetaDataProvider.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Member;
+import java.util.List;
+import java.util.Map;
+import javax.validation.ElementDescriptor;
+
+/**
+ * Interface defining the meta data about the constraints defined in a given bean.
+ *
+ * @author Hardy Ferentschik
+ */
+public interface MetaDataProvider<T> {
+
+	/**
+	 * @return the class of the bean.
+	 */
+	Class<T> getBeanClass();
+
+	/**
+	 * @return an instance of <code>ElementDescriptor</code> describing the bean this meta data applies for.
+	 */
+	ElementDescriptor getBeanDescriptor();
+
+	/**
+	 * @return A list of all cascaded fields (fields annotated with &#064;Valid).
+	 */
+	List<Field> getCascadedFields();
+
+	/**
+	 * @return A list of all cascaded methods (methods annotated with &#064;Valid).
+	 */
+	List<Method> getCascadedMethods();
+
+	/**
+	 * @return A list of all cascaded methods and fields (methods/fields annotated with &#064;Valid).
+	 */
+	List<Member> getCascadedMembers();
+
+	/**
+	 * @return A map mapping defined group sequence names to a list of groups.
+	 */
+	Map<String, List<String>> getGroupSequences();
+
+	/**
+	 * @return A list of <code>ValidatorMetaData</code> instances encapsulating the information of all the constraints
+	 *         defined on the bean.
+	 */
+	List<ValidatorMetaData> getConstraintMetaDataList();
+
+	/**
+	 * @return A map keying the property name of a constraint to its <code>ElementDescriptor</code>.
+	 *
+	 * @todo Maybe needs to be removed since this data structure is ambigious. There could be conflicts between field and
+	 * methods.
+	 */
+	Map<String, ElementDescriptor> getPropertyDescriptors();
+
+	ElementDescriptor getPropertyDescriptors(String property);
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/MetaDataProviderImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,473 @@
+// $Id: MetaDataProviderImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.validation.Constraint;
+import javax.validation.ConstraintFactory;
+import javax.validation.ConstraintValidator;
+import javax.validation.ElementDescriptor;
+import javax.validation.GroupSequence;
+import javax.validation.GroupSequences;
+import javax.validation.Valid;
+import javax.validation.ValidationException;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.impl.ConstraintDescriptorImpl;
+import org.hibernate.validation.impl.ConstraintFactoryImpl;
+import org.hibernate.validation.impl.ElementDescriptorImpl;
+import org.hibernate.validation.util.LoggerFactory;
+import org.hibernate.validation.util.ReflectionHelper;
+
+
+/**
+ * This class encapsulates all meta data needed for validation. Implementations of <code>Validator</code> interface can
+ * instantiate an instance of this class and delegate the metadata extraction to it.
+ *
+ * @author Hardy Ferentschik
+ */
+
+public class MetaDataProviderImpl<T> implements MetaDataProvider<T> {
+
+	private static final Logger log = LoggerFactory.make();
+
+	/**
+	 * The root bean class for this validator.
+	 */
+	private final Class<T> beanClass;
+
+	/**
+	 * The main element descriptor for <code>beanClass</code>.
+	 */
+	private ElementDescriptorImpl beanDescriptor;
+
+	/**
+	 * List of constraints.
+	 */
+	private List<ValidatorMetaData> constraintMetaDataList = new ArrayList<ValidatorMetaData>();
+
+	/**
+	 * List of cascaded fields.
+	 */
+	private List<Field> cascadedFields = new ArrayList<Field>();
+
+	/**
+	 * List of cascaded methods.
+	 */
+	private List<Method> cascadedMethods = new ArrayList<Method>();
+
+	/**
+	 * Maps field and method names to their <code>ElementDescriptorImpl</code>.
+	 * FIXME This model is problematic as you can have conflicting names for fields and methods
+	 */
+	private Map<String, ElementDescriptor> propertyDescriptors = new HashMap<String, ElementDescriptor>();
+
+	/**
+	 * Factory to create acutal constraint instances from the annotated fields/method/class.
+	 */
+	private ConstraintFactory constraintFactory = new ConstraintFactoryImpl();
+
+	/**
+	 * Maps group sequence names to the list of group/sequence names.
+	 */
+	private Map<String, List<String>> groupSequences = new HashMap<String, List<String>>();
+
+	public MetaDataProviderImpl(Class<T> beanClass, ConstraintFactory constraintFactory) {
+		this.beanClass = beanClass;
+		this.constraintFactory = constraintFactory;
+		createMetaData();
+	}
+
+	/**
+	 * Create bean desciptor, find all classes/subclasses/interfaces which have to be taken in consideration
+	 * for this validator and create meta data.
+	 */
+	private void createMetaData() {
+		beanDescriptor = new ElementDescriptorImpl( ElementType.TYPE, beanClass, false, "" );
+		List<Class> classes = new ArrayList<Class>();
+		computeClassHierarchy( beanClass, classes );
+		for ( Class current : classes ) {
+			initClass( current );
+		}
+	}
+
+	/**
+	 * Get all superclasses and interfaces recursively.
+	 *
+	 * @param clazz The class to start the seatch with.
+	 * @param classes List of classes to which to add all found super classes and interfaces.
+	 */
+	private void computeClassHierarchy(Class clazz, List<Class> classes) {
+		if ( log.isTraceEnabled() ) {
+			log.trace( "Processing: {}", clazz );
+		}
+		for ( Class current = clazz; current != null; current = current.getSuperclass() ) {
+			if ( classes.contains( current ) ) {
+				return;
+			}
+			classes.add( current );
+			for ( Class currentInterface : current.getInterfaces() ) {
+				computeClassHierarchy( currentInterface, classes );
+			}
+		}
+	}
+
+	private void initClass(Class clazz) {
+		initGroupSequences( clazz );
+		initClassConstraints( clazz );
+		initMethodConstraints( clazz );
+		initFieldConstraints( clazz );
+	}
+
+	private void initGroupSequences(Class<?> clazz) {
+		GroupSequence groupSequenceAnnotation = clazz.getAnnotation( GroupSequence.class );
+		if ( groupSequenceAnnotation != null ) {
+			addGroupSequence( groupSequenceAnnotation );
+		}
+
+		GroupSequences groupSequencesAnnotation = clazz.getAnnotation( GroupSequences.class );
+		if ( groupSequencesAnnotation != null ) {
+			for ( GroupSequence group : groupSequencesAnnotation.value() ) {
+				addGroupSequence( group );
+			}
+		}
+
+		for ( Map.Entry<String, List<String>> mapEntry : groupSequences.entrySet() ) {
+			List<String> groupNames = mapEntry.getValue();
+			List<String> expandedGroupNames = new ArrayList<String>();
+			for ( String groupName : groupNames ) {
+				expandedGroupNames.addAll( expandGroupSequenceNames( groupName ) );
+			}
+			groupSequences.put( mapEntry.getKey(), expandedGroupNames );
+		}
+		if ( log.isDebugEnabled() && !groupSequences.isEmpty() ) {
+			log.debug( "Expanded groups sequences: {}", groupSequences );
+		}
+	}
+
+	private List<String> expandGroupSequenceNames(String group) {
+		List<String> groupList = new ArrayList<String>();
+		if ( groupSequences.containsKey( group ) ) {
+			for ( String s : groupSequences.get( group ) ) {
+				groupList.addAll( expandGroupSequenceNames( s ) );
+			}
+		}
+		else {
+			groupList.add( group );
+		}
+		if ( log.isTraceEnabled() ) {
+			log.trace( "Expanded {} to {}", group, groupList.toString() );
+		}
+		return groupList;
+	}
+
+	private void addGroupSequence(GroupSequence groupSequence) {
+		if ( groupSequences.containsKey( groupSequence.name() ) ) {
+			throw new ValidationException( "Encountered duplicate sequence name: " + groupSequence.name() );
+		}
+		groupSequences.put( groupSequence.name(), Arrays.asList( groupSequence.sequence() ) );
+	}
+
+	private void initFieldConstraints(Class clazz) {
+		for ( Field field : clazz.getDeclaredFields() ) {
+			List<ConstraintDescriptorImpl> fieldMetadata = getFieldLevelMetadata( field );
+			for ( ConstraintDescriptorImpl constraintDescription : fieldMetadata ) {
+				ReflectionHelper.setAccessibility( field );
+				ValidatorMetaData metaData = new ValidatorMetaData( field, constraintDescription );
+				constraintMetaDataList.add( metaData );
+			}
+			if ( field.isAnnotationPresent( Valid.class ) ) {
+				cascadedFields.add( field );
+			}
+		}
+	}
+
+	private void initMethodConstraints(Class clazz) {
+		for ( Method method : clazz.getDeclaredMethods() ) {
+			List<ConstraintDescriptorImpl> methodMetadata = getMethodLevelMetadata( method );
+			for ( ConstraintDescriptorImpl constraintDescription : methodMetadata ) {
+				ReflectionHelper.setAccessibility( method );
+				ValidatorMetaData metaData = new ValidatorMetaData( method, constraintDescription );
+				constraintMetaDataList.add( metaData );
+			}
+			if ( method.isAnnotationPresent( Valid.class ) ) {
+				cascadedMethods.add( method );
+			}
+		}
+	}
+
+	private void initClassConstraints(Class clazz) {
+		List<ConstraintDescriptorImpl> classMetadata = getClassLevelMetadata( clazz );
+		for ( ConstraintDescriptorImpl constraintDescription : classMetadata ) {
+			ValidatorMetaData metaData = new ValidatorMetaData( clazz, constraintDescription );
+			constraintMetaDataList.add( metaData );
+		}
+	}
+
+	/**
+	 * Examines the given annotation to see whether it is a single or multi valued constraint annotation.
+	 *
+	 * @param annotation The annotation to examine.
+	 *
+	 * @return A list of constraint descriptors or the empty list in case <code>annotation</code> is neither a
+	 *         single nor multi value annotation.
+	 */
+	private <A extends Annotation> List<ConstraintDescriptorImpl> findConstraintAnnotations(A annotation) {
+		List<ConstraintDescriptorImpl> constraintDescriptors = new ArrayList<ConstraintDescriptorImpl>();
+
+		List<Annotation> constraintCandidates = new ArrayList<Annotation>();
+		constraintCandidates.add( annotation );
+
+		// check if we have a multi value constraint
+		Annotation[] annotations = getMultiValueConstraintsCandidates( annotation );
+		constraintCandidates.addAll( Arrays.asList( annotations ) );
+
+		for ( Annotation constraintCandiate : constraintCandidates ) {
+			ConstraintValidator constraintValidator = constraintCandiate.annotationType()
+					.getAnnotation( ConstraintValidator.class );
+			if ( constraintValidator != null ) {
+				final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor( constraintCandiate );
+				constraintDescriptors.add( constraintDescriptor );
+			}
+		}
+		return constraintDescriptors;
+	}
+
+	@SuppressWarnings("unchecked")
+	private <A extends Annotation> ConstraintDescriptorImpl buildConstraintDescriptor(A annotation) {
+		getMessage( annotation ); // called to make sure there is a message
+		String[] groups = getGroups( annotation );
+		for ( String groupName : groups ) {
+			if ( groupSequences.containsKey( groupName ) ) {
+				throw new ValidationException( groupName + " is illegally used as group and sequence name." );
+			}
+		}
+
+		Constraint<A> constraint;
+		ConstraintValidator constraintValidator = annotation.annotationType()
+				.getAnnotation( ConstraintValidator.class );
+		try {
+			//unchecked
+			constraint = constraintFactory.getInstance( constraintValidator.value() );
+		}
+		catch ( RuntimeException e ) {
+			throw new ValidationException( "Unable to instantiate " + constraintValidator.value(), e );
+		}
+
+		try {
+			constraint.initialize( annotation );
+		}
+		catch ( RuntimeException e ) {
+			throw new ValidationException( "Unable to intialize " + constraintValidator.value(), e );
+		}
+
+		return new ConstraintDescriptorImpl( annotation, groups, constraint );
+	}
+
+	private <A extends Annotation> String getMessage(A annotation) {
+		try {
+			Method m = annotation.getClass().getMethod( "message" );
+			return ( String ) m.invoke( annotation );
+		}
+		catch ( NoSuchMethodException e ) {
+			throw new ValidationException( "Constraint annotation has to define message element." );
+		}
+		catch ( Exception e ) {
+			throw new ValidationException( "Unable to get message from " + annotation.getClass().getName() );
+		}
+	}
+
+	private <A extends Annotation> String[] getGroups(A annotation) {
+		try {
+			Method m = annotation.getClass().getMethod( "groups" );
+			return ( String[] ) m.invoke( annotation );
+		}
+		catch ( NoSuchMethodException e ) {
+			throw new ValidationException( "Constraint annotation has to define groups element." );
+		}
+		catch ( Exception e ) {
+			throw new ValidationException( "Unable to get groups from " + annotation.getClass().getName() );
+		}
+	}
+
+	/**
+	 * Checks whether the given annotation has a value parameter which returns an array of annotations.
+	 *
+	 * @param annotation the annotation to check.
+	 *
+	 * @return The list of potential constraint annotations or the empty array.
+	 *
+	 * @todo Not only check that the return type of value is an array, but an array of annotaitons. Need to check syntax.
+	 */
+	private <A extends Annotation> Annotation[] getMultiValueConstraintsCandidates(A annotation) {
+		try {
+			Method m = annotation.getClass().getMethod( "value" );
+			Class returnType = m.getReturnType();
+			if ( returnType.isArray() ) {
+				return ( Annotation[] ) m.invoke( annotation );
+			}
+			else {
+				return new Annotation[0];
+			}
+		}
+		catch ( Exception e ) {
+			return new Annotation[0];
+		}
+	}
+
+	/**
+	 * Finds all constraint annotations defined for the given class and returns them in a list of
+	 * constraint descriptors.
+	 *
+	 * @param beanClass The class to check for constraints annotations.
+	 *
+	 * @return A list of constraint descriptors for all constraint specified on the given class.
+	 *
+	 * @todo inject XML data here, probably externalizing the process
+	 */
+	private List<ConstraintDescriptorImpl> getClassLevelMetadata(Class beanClass) {
+		List<ConstraintDescriptorImpl> metadata = new ArrayList<ConstraintDescriptorImpl>();
+		for ( Annotation annotation : beanClass.getAnnotations() ) {
+			metadata.addAll( findConstraintAnnotations( annotation ) );
+		}
+		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+			beanDescriptor.addConstraintDescriptor( constraintDescriptor );
+		}
+		return metadata;
+	}
+
+	/**
+	 * Finds all constraint annotations defined for the given methods and returns them in a list of
+	 * constraint descriptors.
+	 *
+	 * @param method The method to check for constraints annotations.
+	 *
+	 * @return A list of constraint descriptors for all constraint specified for the given method.
+	 *
+	 * @todo inject XML data here, probably externalizing the process
+	 */
+	private List<ConstraintDescriptorImpl> getMethodLevelMetadata(Method method) {
+		List<ConstraintDescriptorImpl> metadata = new ArrayList<ConstraintDescriptorImpl>();
+		for ( Annotation annotation : method.getAnnotations() ) {
+			metadata.addAll( findConstraintAnnotations( annotation ) );
+		}
+
+		String methodName = ReflectionHelper.getPropertyName( method );
+		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+			if ( methodName == null ) {
+				throw new ValidationException(
+						"Annoated methods must follow the JavaBeans naming convention. " + method.getName() + "() does not."
+				);
+			}
+			ElementDescriptorImpl elementDescriptor = ( ElementDescriptorImpl ) propertyDescriptors.get( methodName );
+			if ( elementDescriptor == null ) {
+				elementDescriptor = new ElementDescriptorImpl(
+						ElementType.METHOD,
+						method.getReturnType(),
+						method.isAnnotationPresent( Valid.class ),
+						methodName
+				);
+				propertyDescriptors.put( methodName, elementDescriptor );
+			}
+			elementDescriptor.addConstraintDescriptor( constraintDescriptor );
+		}
+		return metadata;
+	}
+
+	/**
+	 * Finds all constraint annotations defined for the given field and returns them in a list of
+	 * constraint descriptors.
+	 *
+	 * @param field The field to check for constraints annotations.
+	 *
+	 * @return A list of constraint descriptors for all constraint specified on the given field.
+	 *
+	 * @todo inject XML data here, probably externalizing the process
+	 */
+	private List<ConstraintDescriptorImpl> getFieldLevelMetadata(Field field) {
+		List<ConstraintDescriptorImpl> metadata = new ArrayList<ConstraintDescriptorImpl>();
+		for ( Annotation annotation : field.getAnnotations() ) {
+			metadata.addAll( findConstraintAnnotations( annotation ) );
+		}
+
+		String fieldName = field.getName();
+		for ( ConstraintDescriptorImpl constraintDescriptor : metadata ) {
+			ElementDescriptorImpl elementDescriptor = ( ElementDescriptorImpl ) propertyDescriptors.get( fieldName );
+			if ( elementDescriptor == null ) {
+				elementDescriptor = new ElementDescriptorImpl(
+						ElementType.FIELD,
+						field.getType(),
+						field.isAnnotationPresent( Valid.class ),
+						fieldName
+				);
+				propertyDescriptors.put( field.getName(), elementDescriptor );
+			}
+			elementDescriptor.addConstraintDescriptor( constraintDescriptor );
+		}
+		return metadata;
+	}
+
+	public Class<T> getBeanClass() {
+		return beanClass;
+	}
+
+	public ElementDescriptor getBeanDescriptor() {
+		return beanDescriptor;
+	}
+
+	public List<Field> getCascadedFields() {
+		return cascadedFields;
+	}
+
+	public List<Method> getCascadedMethods() {
+		return cascadedMethods;
+	}
+
+	public List<Member> getCascadedMembers() {
+		List<Member> cascadedMembers = new ArrayList<Member>();
+		cascadedMembers.addAll( getCascadedFields() );
+		cascadedMembers.addAll( getCascadedMethods() );
+		return cascadedMembers;
+	}
+
+	public Map<String, List<String>> getGroupSequences() {
+		return groupSequences;
+	}
+
+	public List<ValidatorMetaData> getConstraintMetaDataList() {
+		return constraintMetaDataList;
+	}
+
+	public Map<String, ElementDescriptor> getPropertyDescriptors() {
+		return propertyDescriptors;
+	}
+
+	public ElementDescriptor getPropertyDescriptors(String property) {
+		return propertyDescriptors.get( property );
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidationContext.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,184 @@
+// $Id: ValidationContext.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import org.hibernate.validation.impl.InvalidConstraintImpl;
+import org.hibernate.validation.util.IdentitySet;
+
+/**
+ * Context object keeping track of all processed objects and all failing constraints.
+ * At the same time it keeps track of the currently validated object, the current group and property path.
+ * The way the validation works at the moment the validated object and the property path have to be processed
+ * in a stack fashion.
+ *
+ * all sort of information needed  Introduced to reduce the parameters passed around between the different
+ * validate methdods in <code>ValidatorImpl</code>.
+ *
+ * @author Hardy Ferentschik
+ * @author Emmanuel Bernard
+ */
+public class ValidationContext<T> {
+
+	/**
+	 * The root bean of the validation.
+	 */
+	private final T rootBean;
+
+	/**
+	 * Maps for each group name to an identity set to keep track of already validated objects. We have to make sure
+	 * that each object gets only validated once (per group).
+	 */
+	private final Map<String, IdentitySet> processedObjects;
+
+	/**
+	 * A list of all failing constraints so far.
+	 */
+	private final List<InvalidConstraintImpl<T>> failingConstraints;
+
+	/**
+	 * The current property path.
+	 */
+	private String propertyPath;
+
+	/**
+	 * The current group which is getting processed.
+	 */
+	private String currentGroup;
+
+	/**
+	 * Stack for keep track of the currently validated object.
+	 */
+	private Stack<Object> validatedobjectStack = new Stack<Object>();
+
+
+	public ValidationContext(T object) {
+		this( object, object );
+	}
+
+	public ValidationContext(T rootBean, Object object) {
+		this.rootBean = rootBean;
+		validatedobjectStack.push( object );
+		processedObjects = new HashMap<String, IdentitySet>();
+		propertyPath = "";
+		failingConstraints = new ArrayList<InvalidConstraintImpl<T>>();
+	}
+
+	public Object peekValidatedObject() {
+		return validatedobjectStack.peek();
+	}
+
+	public void pushValidatedObject(Object validatedObject) {
+		validatedobjectStack.push( validatedObject );
+	}
+
+	public void popValidatedObject() {
+		validatedobjectStack.pop();
+	}
+
+	public T getRootBean() {
+		return rootBean;
+	}
+
+	public String getCurrentGroup() {
+		return currentGroup;
+	}
+
+	public void setCurrentGroup(String currentGroup) {
+		this.currentGroup = currentGroup;
+	}
+
+	public void markProcessedForCurrentGroup() {
+		if ( processedObjects.containsKey( currentGroup ) ) {
+			processedObjects.get( currentGroup ).add( validatedobjectStack.peek() );
+		}
+		else {
+			IdentitySet set = new IdentitySet();
+			set.add( validatedobjectStack.peek() );
+			processedObjects.put( currentGroup, set );
+		}
+	}
+
+	public boolean isProcessedForCurrentGroup(Object value) {
+		final IdentitySet objectsProcessedInCurrentGroups = processedObjects.get( currentGroup );
+		return objectsProcessedInCurrentGroups != null && objectsProcessedInCurrentGroups.contains( value );
+	}
+
+	public void addConstraintFailure(InvalidConstraintImpl<T> failingConstraint) {
+		int i = failingConstraints.indexOf( failingConstraint );
+		if ( i == -1 ) {
+			failingConstraints.add( failingConstraint );
+		}
+		else {
+			failingConstraints.get( i ).addGroups( failingConstraint.getGroups() );
+		}
+	}
+
+	public List<InvalidConstraintImpl<T>> getFailingConstraints() {
+		return failingConstraints;
+	}
+
+	/**
+	 * Adds a new level to the current property path of this context.
+	 *
+	 * @param property the new property to add to the current path.
+	 */
+	public void pushProperty(String property) {
+		if ( propertyPath.length() == 0 ) {
+			propertyPath = property;
+		}
+		else {
+			propertyPath = propertyPath + "." + property;
+		}
+	}
+
+	/**
+	 * Drops the last level of the current property path of this context.
+	 */
+	public void popProperty() {
+		int lastIndex = propertyPath.lastIndexOf( '.' );
+		if ( lastIndex != -1 ) {
+			propertyPath = propertyPath.substring( 0, lastIndex );
+		}
+		else {
+			propertyPath = "";
+		}
+	}
+
+	public void appendIndexToPropertyPath(String index) {
+		propertyPath += index;
+	}
+
+	public void replacePropertyIndex(String index) {
+		propertyPath = propertyPath.replaceAll( "\\{0\\}", index );
+	}
+
+	public String peekPropertyPath() {
+		return propertyPath;
+	}
+
+	public boolean needsValidation(Set<String> groups) {
+		return groups.contains( currentGroup );
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,575 @@
+// $Id: ValidatorImpl.java 113 2008-09-30 20:00:16Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintFactory;
+import javax.validation.ElementDescriptor;
+import javax.validation.InvalidConstraint;
+import javax.validation.MessageResolver;
+import javax.validation.Validator;
+
+import org.hibernate.validation.Version;
+import org.hibernate.validation.impl.ConstraintDescriptorImpl;
+import org.hibernate.validation.impl.ConstraintFactoryImpl;
+import org.hibernate.validation.impl.InvalidConstraintImpl;
+import org.hibernate.validation.impl.ResourceBundleMessageResolver;
+import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.PropertyIterator;
+
+/**
+ * The main Bean Validation class.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ * @todo Make all properties transient for serializability.
+ */
+public class ValidatorImpl<T> implements Validator<T> {
+
+	/**
+	 * The default group/sequence name when no group parameter is passed to validate().
+	 *
+	 * @todo Is it correct to use this default string and if so is this the correct place to define it?
+	 */
+	private static final String DEFAULT_GROUP_NAME = "default";
+
+	private static final Set<Class> INDEXABLE_CLASS = new HashSet<Class>();
+
+	static {
+		INDEXABLE_CLASS.add( Integer.class );
+		INDEXABLE_CLASS.add( Long.class );
+		INDEXABLE_CLASS.add( String.class );
+	}
+
+	static {
+		Version.touch();
+	}
+
+	@SuppressWarnings("unchecked")
+	private final List<InvalidConstraintImpl<T>> EMPTY_CONSTRAINTS_LIST = Collections.EMPTY_LIST;
+
+	/**
+	 * A map for caching validators for cascaded entities.
+	 */
+	private final Map<Class<?>, ValidatorImpl> subValidators = new ConcurrentHashMap<Class<?>, ValidatorImpl>();
+
+	/**
+	 * Gives access to the required parsed meta data.
+	 */
+	private final MetaDataProvider<T> metaDataProvider;
+
+	/**
+	 * Message resolver used  for interpolating error messages.
+	 */
+	private final MessageResolver messageResolver;
+
+	public ValidatorImpl(Class<T> beanClass, ConstraintFactory constraintFactory, MessageResolver messageResolver) {
+		if ( beanClass == null ) {
+			throw new IllegalArgumentException( "Bean class paramter cannot be null" );
+		}
+
+		metaDataProvider = new MetaDataProviderImpl<T>( beanClass, constraintFactory );
+		this.messageResolver = messageResolver;
+	}
+
+	public ValidatorImpl(Class<T> beanClass) {
+		this( beanClass, new ConstraintFactoryImpl(), new ResourceBundleMessageResolver() );
+	}
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<InvalidConstraint<T>> validate(T object, String... groups) {
+		if ( object == null ) {
+			throw new IllegalArgumentException( "Validation of a null object" );
+		}
+
+		ValidationContext<T> context = new ValidationContext<T>( object );
+		List<InvalidConstraintImpl<T>> list = validate( context, Arrays.asList( groups ) );
+		return new HashSet<InvalidConstraint<T>>( list );
+	}
+
+	/**
+	 * Validates the ovject contained in <code>context</code>.
+	 *
+	 * @param context A context object containing the object to validate together with other state information needed
+	 * for validation.
+	 * @param groups A list of groups to validate.
+	 *
+	 * @return List of invalid constraints.
+	 *
+	 * @todo Currently we iterate the cascaded fields multiple times. Maybe we should change to an approach where we iterate the object graph only once.
+	 * @todo Context root bean can be a different object than the current Validator<T> hence two different generics variables
+	 */
+	private List<InvalidConstraintImpl<T>> validate(ValidationContext<T> context, List<String> groups) {
+		if ( context.peekValidatedObject() == null ) {
+			return EMPTY_CONSTRAINTS_LIST;
+		}
+
+		// if no group is specified use the default
+		if ( groups.size() == 0 ) {
+			groups = Arrays.asList( DEFAULT_GROUP_NAME );
+		}
+
+		List<String> expandedGroups;
+		boolean isGroupSequence;
+		for ( String group : groups ) {
+			expandedGroups = new ArrayList<String>();
+			isGroupSequence = expandGroupName( group, expandedGroups );
+
+			for ( String expandedGroupName : expandedGroups ) {
+				context.setCurrentGroup( expandedGroupName );
+
+				validateConstraints( context );
+				validateCascadedConstraints( context );
+
+				if ( isGroupSequence && context.getFailingConstraints().size() > 0 ) {
+					break;
+				}
+			}
+		}
+		return context.getFailingConstraints();
+	}
+
+	/**
+	 * Validates the non-cascaded constraints.
+	 *
+	 * @param context The current validation context.
+	 */
+	private void validateConstraints(ValidationContext<T> context) {
+		for ( ValidatorMetaData metaData : metaDataProvider.getConstraintMetaDataList() ) {
+			ConstraintDescriptorImpl constraintDescriptor = metaData.getDescriptor();
+			context.pushProperty( metaData.getPropertyName() );
+
+			if ( !context.needsValidation( constraintDescriptor.getGroups() ) ) {
+				context.popProperty();
+				continue;
+			}
+
+			Object value = metaData.getValue( context.peekValidatedObject() );
+			ContextImpl contextImpl = new ContextImpl(constraintDescriptor);
+
+			if ( !constraintDescriptor.getConstraintImplementation().isValid( value, contextImpl ) ) {
+				for ( ContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
+					String message = messageResolver.interpolate(
+							error.getMessage(),
+							constraintDescriptor,
+							context.peekValidatedObject()
+					);
+					InvalidConstraintImpl<T> failingConstraint = new InvalidConstraintImpl<T>(
+							message,
+							context.getRootBean(),
+							metaDataProvider.getBeanClass(),
+							value,
+							context.peekPropertyPath(), //FIXME use error.getProperty()
+							context.getCurrentGroup()
+					);
+					context.addConstraintFailure( failingConstraint );
+				}
+			}
+			context.popProperty();
+		}
+		context.markProcessedForCurrentGroup();
+	}
+
+	private void validateCascadedConstraint(ValidationContext<T> context, Type type, Object value) {
+		if ( value == null ) {
+			return;
+		}
+
+		Iterator<?> iter;
+		if ( ReflectionHelper.isCollection( type ) ) {
+			boolean isIterable = value instanceof Iterable;
+			Map<?, ?> map = !isIterable ? ( Map<?, ?> ) value : null;
+			Iterable<?> elements = isIterable ?
+					( Iterable<?> ) value :
+					map.entrySet();
+			iter = elements.iterator();
+			context.appendIndexToPropertyPath( "[{0}]" );
+		}
+		else if ( ReflectionHelper.isArray( type ) ) {
+			List<?> arrayList = Arrays.asList( value );
+			iter = arrayList.iterator();
+			context.appendIndexToPropertyPath( "[{0}]" );
+		}
+		else {
+			List<Object> list = new ArrayList<Object>();
+			list.add( value );
+			iter = list.iterator();
+		}
+
+		validateCascadedConstraint( context, iter );
+	}
+
+	private void validateCascadedConstraints(ValidationContext<T> context) {
+		List<Member> cascadedMembers = getMetaDataProvider().getCascadedMembers();
+		for ( Member member : cascadedMembers ) {
+			Type type = ReflectionHelper.typeOf( member );
+			context.pushProperty( ReflectionHelper.getPropertyName( member ) );
+			ReflectionHelper.setAccessibility( member );
+			Object value = ReflectionHelper.getValue( member, context.peekValidatedObject() );
+			validateCascadedConstraint( context, type, value );
+			context.popProperty();
+		}
+	}
+
+	private void validateCascadedConstraint(ValidationContext<T> context, Iterator<?> iter) {
+		Object actualValue;
+		String propertyIndex;
+		int i = 0;
+		while ( iter.hasNext() ) {
+			actualValue = iter.next();
+			propertyIndex = String.valueOf( i );
+			if ( actualValue instanceof Map.Entry ) {
+				Object key = ( ( Map.Entry ) actualValue ).getKey();
+				if ( INDEXABLE_CLASS.contains( key.getClass() ) ) {
+					propertyIndex = key.toString();
+				}
+				actualValue = ( ( Map.Entry ) actualValue ).getValue();
+			}
+
+			if ( context.isProcessedForCurrentGroup( actualValue ) ) {
+				i++;
+				continue;
+			}
+
+			context.replacePropertyIndex( propertyIndex );
+
+			Class cascadedClass = actualValue.getClass();
+			ValidatorImpl validatorImpl = getValidatorForClass( cascadedClass );
+			context.pushValidatedObject( actualValue );
+			validatorImpl.validate( context, Arrays.asList( context.getCurrentGroup() ) );
+			context.popValidatedObject();
+			i++;
+		}
+	}
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<InvalidConstraint<T>> validateProperty(T object, String propertyName, String... groups) {
+		List<InvalidConstraintImpl<T>> failingConstraints = new ArrayList<InvalidConstraintImpl<T>>();
+		validateProperty( object, new PropertyIterator( propertyName ), failingConstraints, groups );
+		return new HashSet<InvalidConstraint<T>>( failingConstraints );
+	}
+
+
+	private void validateProperty(T object, PropertyIterator propertyIter, List<InvalidConstraintImpl<T>> failingConstraints, String... groups) {
+		DesrciptorValueWrapper wrapper = getConstraintDescriptorAndValueForPath( this, propertyIter, object );
+
+		if ( wrapper == null ) {
+			return;
+		}
+
+		// if no group is specified use the default
+		if ( groups.length == 0 ) {
+			groups = new String[] { DEFAULT_GROUP_NAME };
+		}
+
+		List<String> expandedGroups;
+		boolean isGroupSequence;
+		for ( String group : groups ) {
+			expandedGroups = new ArrayList<String>();
+			isGroupSequence = expandGroupName( group, expandedGroups );
+
+			for ( String expandedGroupName : expandedGroups ) {
+
+				if ( !wrapper.descriptor.isInGroups( expandedGroupName ) ) {
+					continue;
+				}
+
+				ContextImpl contextImpl = new ContextImpl(wrapper.descriptor);
+				if ( !wrapper.descriptor.getConstraintImplementation().isValid( wrapper.value, contextImpl ) ) {
+
+					for ( ContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
+						String message = messageResolver.interpolate(
+								error.getMessage(),
+								wrapper.descriptor,
+								wrapper.value
+						);
+						InvalidConstraintImpl<T> failingConstraint = new InvalidConstraintImpl<T>(
+								message,
+								object,
+								( Class<T> ) object.getClass(),
+								wrapper.value,
+								propertyIter.getOriginalProperty(), //FIXME use error.getProperty()
+								group
+						);
+						addFailingConstraint( failingConstraints, failingConstraint );
+					}
+				}
+
+				if ( isGroupSequence && failingConstraints.size() > 0 ) {
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<InvalidConstraint<T>> validateValue(String propertyName, Object value, String... groups) {
+		List<InvalidConstraintImpl<T>> failingConstraints = new ArrayList<InvalidConstraintImpl<T>>();
+		validateValue( value, new PropertyIterator( propertyName ), failingConstraints, groups );
+		return new HashSet<InvalidConstraint<T>>( failingConstraints );
+	}
+
+
+	private void validateValue(Object object, PropertyIterator propertyIter, List<InvalidConstraintImpl<T>> failingConstraints, String... groups) {
+		ConstraintDescriptorImpl constraintDescriptor = getConstraintDescriptorForPath( this, propertyIter );
+
+		if ( constraintDescriptor == null ) {
+			return;
+		}
+
+		// if no group is specified use the default
+		if ( groups.length == 0 ) {
+			groups = new String[] { DEFAULT_GROUP_NAME };
+		}
+
+		List<String> expandedGroups;
+		boolean isGroupSequence;
+		for ( String group : groups ) {
+			expandedGroups = new ArrayList<String>();
+			isGroupSequence = expandGroupName( group, expandedGroups );
+
+			for ( String expandedGroupName : expandedGroups ) {
+
+				if ( !constraintDescriptor.isInGroups( expandedGroupName ) ) {
+					continue;
+				}
+
+				ContextImpl contextImpl = new ContextImpl(constraintDescriptor);
+				if ( !constraintDescriptor.getConstraintImplementation().isValid( object, contextImpl ) ) {
+					for ( ContextImpl.ErrorMessage error : contextImpl.getErrorMessages() ) {
+						String message = messageResolver.interpolate(
+								error.getMessage(),
+								constraintDescriptor,
+								object
+						);
+						InvalidConstraintImpl<T> failingConstraint = new InvalidConstraintImpl<T>(
+								message,
+								null,
+								null,
+								object,
+								propertyIter.getOriginalProperty(),  //FIXME use error.getProperty()
+								""
+						);
+						addFailingConstraint( failingConstraints, failingConstraint );
+					}
+				}
+
+				if ( isGroupSequence && failingConstraints.size() > 0 ) {
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Returns the constraint descriptor for the given path relative to the specified validator.
+	 * <p>
+	 * This method does not traverse an actual object, but rather tries to resolve the porperty generically.
+	 * </p>
+	 * <p>
+	 * This method is called recursively. Only if there is a valid 'validation path' through the object graph
+	 * a constraint descriptor will be returned.
+	 * </p>
+	 *
+	 * @param validator the validator to check for constraints.
+	 * @param propertyIter an instance of <code>PropertyIterator</code>
+	 *
+	 * @return The constraint descriptor matching the given path.
+	 */
+	private ConstraintDescriptorImpl getConstraintDescriptorForPath(ValidatorImpl<?> validator, PropertyIterator propertyIter) {
+
+		ConstraintDescriptorImpl matchingConstraintDescriptor = null;
+		propertyIter.split();
+
+		if ( !propertyIter.hasNext() ) {
+			List<ValidatorMetaData> metaDataList = validator.getMetaDataProvider().getConstraintMetaDataList();
+			for ( ValidatorMetaData metaData : metaDataList ) {
+				ConstraintDescriptor constraintDescriptor = metaData.getDescriptor();
+				if ( metaData.getPropertyName().equals( propertyIter.getHead() ) ) {
+					matchingConstraintDescriptor = ( ConstraintDescriptorImpl ) constraintDescriptor;
+				}
+			}
+		}
+		else {
+			List<Member> cascadedMembers = validator.getMetaDataProvider().getCascadedMembers();
+			for ( Member m : cascadedMembers ) {
+				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
+					Type type = ReflectionHelper.typeOf( m );
+
+					if ( propertyIter.isIndexed() ) {
+						type = ReflectionHelper.getIndexedType( type );
+						if ( type == null ) {
+							continue;
+						}
+					}
+
+					ValidatorImpl v = getValidatorForClass( ( Class ) type );
+					matchingConstraintDescriptor = v.getConstraintDescriptorForPath( v, propertyIter );
+				}
+			}
+		}
+
+		return matchingConstraintDescriptor;
+	}
+
+
+	private DesrciptorValueWrapper getConstraintDescriptorAndValueForPath(ValidatorImpl<?> validator, PropertyIterator propertyIter, Object value) {
+
+		DesrciptorValueWrapper wrapper = null;
+		propertyIter.split();
+
+
+		// bottom out - there is only one token left
+		if ( !propertyIter.hasNext() ) {
+			List<ValidatorMetaData> metaDataList = validator.getMetaDataProvider().getConstraintMetaDataList();
+			for ( ValidatorMetaData metaData : metaDataList ) {
+				ConstraintDescriptor constraintDescriptor = metaData.getDescriptor();
+				if ( metaData.getPropertyName().equals( propertyIter.getHead() ) ) {
+					return new DesrciptorValueWrapper(
+							( ConstraintDescriptorImpl ) constraintDescriptor, metaData.getValue( value )
+					);
+				}
+			}
+		}
+		else {
+			List<Member> cascadedMembers = validator.getMetaDataProvider().getCascadedMembers();
+			for ( Member m : cascadedMembers ) {
+				if ( ReflectionHelper.getPropertyName( m ).equals( propertyIter.getHead() ) ) {
+					ReflectionHelper.setAccessibility( m );
+					Object newValue = null;
+					if ( propertyIter.isIndexed() ) {
+						newValue = ReflectionHelper.getValue( m, value );
+					}
+					else {
+						newValue = ReflectionHelper.getIndexedValue( value, propertyIter.getIndex() );
+					}
+					ValidatorImpl cascadedValidator = getValidatorForClass( newValue.getClass() );
+					wrapper = cascadedValidator.getConstraintDescriptorAndValueForPath(
+							cascadedValidator, propertyIter, newValue
+					);
+				}
+			}
+		}
+
+		return wrapper;
+	}
+
+
+	private void addFailingConstraint(List<InvalidConstraintImpl<T>> failingConstraints, InvalidConstraintImpl<T> failingConstraint) {
+		int i = failingConstraints.indexOf( failingConstraint );
+		if ( i == -1 ) {
+			failingConstraints.add( failingConstraint );
+		}
+		else {
+			failingConstraints.get( i ).addGroups( failingConstraint.getGroups() );
+		}
+	}
+
+
+	/**
+	 * @todo add child validation
+	 */
+	public boolean hasConstraints() {
+		return metaDataProvider.getConstraintMetaDataList().size() > 0;
+	}
+
+	public ElementDescriptor getBeanConstraints() {
+		return metaDataProvider.getBeanDescriptor();
+	}
+
+	public ElementDescriptor getConstraintsForProperty(String propertyName) {
+		return metaDataProvider.getPropertyDescriptors().get( propertyName );
+	}
+
+	public String[] getValidatedProperties() {
+		return metaDataProvider.getPropertyDescriptors()
+				.keySet()
+				.toArray( new String[metaDataProvider.getPropertyDescriptors().size()] );
+	}
+
+	public MetaDataProvider<T> getMetaDataProvider() {
+		return metaDataProvider;
+	}
+
+	/**
+	 * Checks whether the provided group name is a group sequence and if so expands the group name and add the expanded
+	 * groups names to <code>expandedGroupName </code>
+	 *
+	 * @param groupName The group name to expand
+	 * @param expandedGroupNames The exanded group names or just a list with the single provided group name id the name
+	 * was not expandable
+	 *
+	 * @return <code>true</code> if an expansion took place, <code>false</code> otherwise.
+	 */
+	private boolean expandGroupName(String groupName, List<String> expandedGroupNames) {
+		if ( expandedGroupNames == null ) {
+			throw new IllegalArgumentException( "List cannot be empty" );
+		}
+
+		boolean isGroupSequence;
+
+		if ( metaDataProvider.getGroupSequences().containsKey( groupName ) ) {
+			expandedGroupNames.addAll( metaDataProvider.getGroupSequences().get( groupName ) );
+			isGroupSequence = true;
+		}
+		else {
+			expandedGroupNames.add( groupName );
+			isGroupSequence = false;
+		}
+		return isGroupSequence;
+	}
+
+	@SuppressWarnings("unchecked")
+	private <V> ValidatorImpl<V> getValidatorForClass(Class<V> cascadedClass) {
+		ValidatorImpl<V> validatorImpl = subValidators.get( cascadedClass );
+		if ( validatorImpl == null ) {
+			validatorImpl = new ValidatorImpl<V>( cascadedClass );
+			subValidators.put( cascadedClass, validatorImpl );
+		}
+		return validatorImpl;
+	}
+
+	private class DesrciptorValueWrapper {
+		final ConstraintDescriptorImpl descriptor;
+		final Object value;
+
+		DesrciptorValueWrapper(ConstraintDescriptorImpl descriptor, Object value) {
+			this.descriptor = descriptor;
+			this.value = value;
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorMetaData.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorMetaData.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorMetaData.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,188 @@
+// $Id: ValidatorMetaData.java 105 2008-09-29 12:37:32Z hardy.ferentschik $// $Id: ValidatorMetaData.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import javax.validation.ValidationException;
+
+import org.hibernate.validation.impl.ConstraintDescriptorImpl;
+import org.hibernate.validation.util.ReflectionHelper;
+
+/**
+ * Instances of this class abstract the constraint type  (class, method or field constraint). This allows
+ * a unified handling of constraints in the validator imlpementation.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ValidatorMetaData {
+
+	/**
+	 * The constraint specific meta data.
+	 */
+	private final ConstraintDescriptorImpl descriptor;
+
+	/**
+	 * The type (class) the constraint was defined on. <code>null</code> if the constraint was specified on method or
+	 * field level.
+	 */
+	private final Type type;
+
+	/**
+	 * The method the constraint was defined on. <code>null</code> if the constraint was specified on class or
+	 * field level.
+	 */
+	private final Method method;
+
+	/**
+	 * The field the constraint was defined on. <code>null</code> if the constraint was specified on class or
+	 * method level.
+	 */
+	private final Field field;
+
+	/**
+	 * The JavaBeans name for this constraint.
+	 */
+	private final String propertyName;
+
+	/**
+	 * Describes on which level (<code>TYPE</code>, <code>METHOD</code>, <code>FIELD</code>) the constraint was
+	 * defined on.
+	 */
+	private final ElementType elementType;
+
+	public ValidatorMetaData(Type t, ConstraintDescriptorImpl constraintDescriptor) {
+		this.type = t;
+		this.method = null;
+		this.field = null;
+		this.descriptor = constraintDescriptor;
+		this.elementType = ElementType.TYPE;
+		this.propertyName = "";
+	}
+
+	public ValidatorMetaData(Method m, ConstraintDescriptorImpl constraintDescriptor) {
+		this.method = m;
+		this.type = null;
+		this.field = null;
+		this.descriptor = constraintDescriptor;
+		this.elementType = ElementType.METHOD;
+		this.propertyName = ReflectionHelper.getPropertyName( m );
+	}
+
+	public ValidatorMetaData(Field f, ConstraintDescriptorImpl constraintDescriptor) {
+		this.field = f;
+		this.method = null;
+		this.type = null;
+		this.descriptor = constraintDescriptor;
+		this.elementType = ElementType.FIELD;
+		this.propertyName = f.getName();
+	}
+
+	/**
+	 * @param o the object from which to retrieve the value.
+	 *
+	 * @return Returns the value for this constraint from the specified object. Depending on the type either the value itself
+	 *         is returned of method or field access is used to access the value.
+	 */
+	public Object getValue(Object o) {
+		switch ( elementType ) {
+			case TYPE: {
+				return o;
+			}
+			case METHOD: {
+				return ReflectionHelper.getValue( method, o );
+			}
+			case FIELD: {
+				return ReflectionHelper.getValue( field, o );
+			}
+			default: {
+				throw new ValidationException(
+						"Invalid state of ValidatorMetaData. Parameter elementType has unexpected value - " + elementType
+				);
+			}
+		}
+	}
+
+	/**
+	 * @return Returns <code>true</code> in case the constraint is defined on a collection, <code>false</code>
+	 *         otherwise.
+	 */
+	public boolean isCollection() {
+		Type t = typeOfAnnoatedElement();
+		return ReflectionHelper.isCollection( t );
+	}
+
+	/**
+	 * @return Returns <code>true</code> in case the constraint is defined on an array, <code>false</code>
+	 *         otherwise.
+	 */
+	public boolean isArray() {
+		Type t = typeOfAnnoatedElement();
+		return ReflectionHelper.isArray( t );
+	}
+
+	public ConstraintDescriptorImpl getDescriptor() {
+		return descriptor;
+	}
+
+	public Method getMethod() {
+		return method;
+	}
+
+	public Field getField() {
+		return field;
+	}
+
+	public Type getType() {
+		return type;
+	}
+
+	public String getPropertyName() {
+		return propertyName;
+	}
+
+	public ElementType getElementType() {
+		return elementType;
+	}
+
+	private Type typeOfAnnoatedElement() {
+		Type t;
+		switch ( elementType ) {
+			case TYPE: {
+				t = type;
+				break;
+			}
+			case METHOD: {
+				t = ReflectionHelper.typeOf( method );
+				break;
+			}
+			case FIELD: {
+				t = ReflectionHelper.typeOf( field );
+				break;
+			}
+			default: {
+				throw new ValidationException(
+						"Invalid state of ValidatorMetaData. Parameter elementType has unexpected value - " + elementType
+				);
+			}
+		}
+		return t;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintDescriptorImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,101 @@
+// $Id: ConstraintDescriptorImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.ValidationException;
+
+/**
+ * Describe a single constraint.
+ *
+ * @author Emmanuel Bernard
+ */
+public class ConstraintDescriptorImpl implements ConstraintDescriptor {
+	private Annotation annotation;
+	private Constraint constraintImplementation;
+	private Set<String> contexts;
+	private Map<String, Object> parameters;
+
+
+	public ConstraintDescriptorImpl(Annotation annotation, String[] contexts, Constraint validator) {
+		this.annotation = annotation;
+		if ( contexts.length == 0 ) {
+			contexts = new String[] { "default" };
+		}
+		this.contexts = new HashSet<String>();
+		this.contexts.addAll( Arrays.asList( contexts ) );
+		this.constraintImplementation = validator;
+		this.parameters = getAnnotationParameters( annotation );
+	}
+
+	/**
+	 * Constraint declaration annotation
+	 */
+	public Annotation getAnnotation() {
+		return annotation;
+	}
+
+	/**
+	 * What are the contexts the constraint is applied on
+	 */
+	public Set<String> getGroups() {
+		return contexts;
+	}
+
+	public boolean isInGroups(String group) {
+		return contexts.contains( group );
+	}
+
+	/**
+	 * Return the constraint implementation routine
+	 */
+	public Constraint getConstraintImplementation() {
+		return constraintImplementation;
+	}
+
+	public Map<String, Object> getParameters() {
+		return parameters;
+	}
+
+	private Map<String, Object> getAnnotationParameters(Annotation annotation) {
+		Method[] declaredMethods = annotation.annotationType().getDeclaredMethods();
+		Map<String, Object> parameters = new HashMap<String, Object>( declaredMethods.length );
+		for ( Method m : declaredMethods ) {
+			try {
+				parameters.put( m.getName(), m.invoke( annotation ) );
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException( "Unable to read annotation parameters: " + annotation.getClass(), e );
+			}
+			catch ( InvocationTargetException e ) {
+				throw new ValidationException( "Unable to read annotation parameters: " + annotation.getClass(), e );
+			}
+		}
+		return Collections.unmodifiableMap( parameters );
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintFactoryImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ConstraintFactoryImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,41 @@
+// $Id: ConstraintFactoryImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintFactory;
+import javax.validation.ValidationException;
+
+/**
+ * Default <code>ConstraintFactory</code> using a no-arg constructor.
+ *
+ * @author Emmanuel Bernard
+ */
+public class ConstraintFactoryImpl implements ConstraintFactory {
+	public <T extends Constraint> T getInstance(Class<T> key) {
+		try {
+			return key.newInstance();
+		}
+		catch ( InstantiationException e ) {
+			throw new ValidationException( "Unable to instanciate " + key, e );
+		}
+		catch ( IllegalAccessException e ) {
+			throw new ValidationException( "Unable to instanciate " + key, e );
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ElementDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ElementDescriptorImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ElementDescriptorImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,90 @@
+// $Id: ElementDescriptorImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.lang.annotation.ElementType;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.ElementDescriptor;
+
+/**
+ * Describe a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ * @todo Should returnType be renamed to type?
+ * @todo Handle problem in descirbing cyclic dependecies for propertyPath
+ */
+public class ElementDescriptorImpl implements ElementDescriptor {
+	private final ElementType elementType;
+	private final Class returnType;
+	private final boolean cascaded;
+	private final List<ConstraintDescriptor> constraintDescriptors = new ArrayList<ConstraintDescriptor>();
+	private final String propertyPath;
+
+
+	public ElementDescriptorImpl(ElementType elementType, Class returnType, boolean cascaded, String propertyPath) {
+		this.elementType = elementType;
+		this.returnType = returnType;
+		this.cascaded = cascaded;
+		this.propertyPath = propertyPath;
+	}
+
+	public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) {
+		constraintDescriptors.add( constraintDescriptor );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ElementType getElementType() {
+		return elementType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @todo Generic type or regular type?
+	 */
+	public Class getReturnType() {
+		return returnType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isCascaded() {
+		return cascaded;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<ConstraintDescriptor> getConstraintDescriptors() {
+		return Collections.unmodifiableList( constraintDescriptors );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getPropertyPath() {
+		return propertyPath;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,65 @@
+// $Id: HibernateValidationProvider.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import javax.validation.ValidationException;
+import javax.validation.ValidatorBuilder;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ValidationProvider;
+import javax.validation.spi.ValidatorBuilderImplementor;
+import javax.validation.spi.BootstrapState;
+
+import org.hibernate.validation.HibernateValidatorBuilder;
+
+/**
+ * Default implementation of <code>ValidationProvider</code> within Hibernate validator.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class HibernateValidationProvider implements ValidationProvider {
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isSuitable(Class<? extends ValidatorBuilder<?>> builderClass) {
+		return builderClass == HibernateValidatorBuilder.class;
+	}
+
+	public <T extends ValidatorBuilder<T>> T createSpecializedValidatorBuilder(BootstrapState state, Class<T> builderClass) {
+		if ( ! isSuitable( builderClass ) ) {
+			throw new ValidationException("Illegal call to createSpecializedValidatorBuilder() for a non suitable provider");
+		}
+		//cast protected  by isSuitable call
+		return builderClass.cast( new ValidatorBuilderImpl( this ) );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ValidatorBuilder<?> createGenericValidatorBuilder(BootstrapState state) {
+		return new ValidatorBuilderImpl( state );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ValidatorFactory buildValidatorFactory(ValidatorBuilderImplementor validatorBuilder) {
+		return new ValidatorFactoryImpl( validatorBuilder );
+	}
+}


Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/HibernateValidationProvider.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/InvalidConstraintImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/InvalidConstraintImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/InvalidConstraintImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,137 @@
+// $Id: InvalidConstraintImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.InvalidConstraint;
+
+/**
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class InvalidConstraintImpl<T> implements InvalidConstraint<T> {
+	private String message;
+	private T rootBean;
+	private Class<T> beanClass;
+	private Object value;
+	private String propertyPath;
+	private HashSet<String> groups;
+
+
+	public InvalidConstraintImpl(String message, T rootBean, Class<T> beanClass, Object value, String propertyPath, String group) {
+		this.message = message;
+		this.rootBean = rootBean;
+		this.beanClass = beanClass;
+		this.value = value;
+		this.propertyPath = propertyPath;
+		groups = new HashSet<String>();
+		groups.add( group );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getMessage() {
+		return message;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public T getRootBean() {
+		return rootBean;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Class<T> getBeanClass() {
+		return beanClass;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Object getValue() {
+		return value;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getPropertyPath() {
+		return propertyPath;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<String> getGroups() {
+		return groups;
+	}
+
+	public void addParent(T parentBean, String parentProperty) {
+		this.propertyPath = parentProperty + "." + propertyPath;
+		this.rootBean = parentBean;
+	}
+
+	public void addGroups(Set<String> groupSet) {
+		groups.addAll( groupSet );
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if ( this == o ) {
+			return true;
+		}
+		if ( !( o instanceof InvalidConstraintImpl ) ) {
+			return false;
+		}
+
+		InvalidConstraintImpl that = ( InvalidConstraintImpl ) o;
+
+		if ( beanClass != null ? !beanClass.equals( that.beanClass ) : that.beanClass != null ) {
+			return false;
+		}
+		if ( message != null ? !message.equals( that.message ) : that.message != null ) {
+			return false;
+		}
+		if ( propertyPath != null ? !propertyPath.equals( that.propertyPath ) : that.propertyPath != null ) {
+			return false;
+		}
+		if ( rootBean != null ? !rootBean.equals( that.rootBean ) : that.rootBean != null ) {
+			return false;
+		}
+		if ( value != null ? !value.equals( that.value ) : that.value != null ) {
+			return false;
+		}
+
+		return true;
+	}
+
+	@Override
+	public int hashCode() {
+		int result = message != null ? message.hashCode() : 0;
+		result = 31 * result + ( rootBean != null ? rootBean.hashCode() : 0 );
+		result = 31 * result + ( beanClass != null ? beanClass.hashCode() : 0 );
+		result = 31 * result + ( value != null ? value.hashCode() : 0 );
+		result = 31 * result + ( propertyPath != null ? propertyPath.hashCode() : 0 );
+		return result;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ResourceBundleMessageResolver.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ResourceBundleMessageResolver.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ResourceBundleMessageResolver.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,151 @@
+// $Id: ResourceBundleMessageResolver.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.MessageResolver;
+
+import org.slf4j.Logger;
+
+import org.hibernate.validation.util.LoggerFactory;
+
+
+/**
+ * Resource bundle backed message resolver.
+ *
+ * @author Emmanuel Bernard
+ */
+public class ResourceBundleMessageResolver implements MessageResolver {
+	private static final String DEFAULT_VALIDATION_MESSAGES = "org.hibernate.validation.ValidationMessages";
+	private static final String USER_VALIDATION_MESSAGES = "ValidationMessages";
+	private static final Logger log = LoggerFactory.make();
+
+	/**
+	 * Regular expression used to do message interpolation.
+	 */
+	private static final Pattern messagePattern = Pattern.compile( "\\{([\\w\\.]+)\\}" );
+	private ResourceBundle defaultResourceBundle;
+	private ResourceBundle userResourceBundle;
+
+	public ResourceBundleMessageResolver() {
+		userResourceBundle = getFileBasedResourceBundle();
+		defaultResourceBundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES );
+	}
+
+	public ResourceBundleMessageResolver(ResourceBundle resourceBundle) {
+		if ( resourceBundle == null ) {
+			userResourceBundle = getFileBasedResourceBundle();
+		}
+		else {
+			this.userResourceBundle = resourceBundle;
+		}
+		defaultResourceBundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES );
+	}
+
+	/**
+	 * Search current thread classloader for the resource bundle. If not found, search validator (this) classloader.
+	 *
+	 * @return the resource bundle or <code>null</code> if none is found.
+	 */
+	private ResourceBundle getFileBasedResourceBundle() {
+		ResourceBundle rb = null;
+		ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+		if ( classLoader != null ) {
+			rb = loadBundle( classLoader, USER_VALIDATION_MESSAGES + " not found by thread local classloader" );
+		}
+		if ( rb == null ) {
+			rb = loadBundle(
+					this.getClass().getClassLoader(), USER_VALIDATION_MESSAGES + " not found by validator classloader"
+			);
+		}
+		if ( log.isDebugEnabled() ) {
+			if ( rb != null ) {
+				log.debug( USER_VALIDATION_MESSAGES + " found" );
+			}
+			else {
+				log.debug( USER_VALIDATION_MESSAGES + " not found. Delegating to " + DEFAULT_VALIDATION_MESSAGES );
+			}
+		}
+		return rb;
+	}
+
+	private ResourceBundle loadBundle(ClassLoader classLoader, String message) {
+		ResourceBundle rb = null;
+		try {
+			rb = ResourceBundle.getBundle( USER_VALIDATION_MESSAGES, Locale.getDefault(), classLoader );
+		}
+		catch ( MissingResourceException e ) {
+			log.trace( message );
+		}
+		return rb;
+	}
+
+	public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value) {
+		//probably no need for caching, but it could be done by parameters since the map
+		//is immutable and uniquely built per Validation definition, the comparaison has to be based on == and not equals though
+		return replace( message, constraintDescriptor.getParameters() );
+	}
+
+
+	private String replace(String message, Map<String, Object> parameters) {
+		Matcher matcher = messagePattern.matcher( message );
+		StringBuffer sb = new StringBuffer();
+		while ( matcher.find() ) {
+			matcher.appendReplacement( sb, resolveParameter( matcher.group( 1 ), parameters ) );
+		}
+		matcher.appendTail( sb );
+		return sb.toString();
+	}
+
+
+	private String resolveParameter(String token, Map<String, Object> parameters) {
+		Object variable = parameters.get( token );
+		if ( variable != null ) {
+			return variable.toString();
+		}
+
+		StringBuffer buffer = new StringBuffer();
+		String string = null;
+		try {
+			string = userResourceBundle != null ? userResourceBundle.getString( token ) : null;
+		}
+		catch ( MissingResourceException e ) {
+			//give a second chance with the default resource bundle
+		}
+		if ( string == null ) {
+			try {
+				string = defaultResourceBundle.getString( token );
+			}
+			catch ( MissingResourceException e ) {
+				//return the unchanged string
+				buffer.append( "{" ).append( token ).append( '}' );
+			}
+		}
+		if ( string != null ) {
+			// call resolve recusively!
+			buffer.append( replace( string, parameters ) );
+		}
+		return buffer.toString();
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,116 @@
+// $Id: ValidatorBuilderImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.io.InputStream;
+import java.util.List;
+import javax.validation.ConstraintFactory;
+import javax.validation.MessageResolver;
+import javax.validation.ValidationException;
+import javax.validation.ValidationProviderResolver;
+import javax.validation.ValidatorBuilder;
+import javax.validation.ValidatorFactory;
+import javax.validation.bootstrap.DefaultValidationProviderResolver;
+import javax.validation.spi.ValidationProvider;
+import javax.validation.spi.ValidatorBuilderImplementor;
+import javax.validation.spi.BootstrapState;
+
+import org.hibernate.validation.HibernateValidatorBuilder;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ValidatorBuilderImpl implements HibernateValidatorBuilder, ValidatorBuilderImplementor {
+	private MessageResolver messageResolver = new ResourceBundleMessageResolver();
+	private ConstraintFactory constraintFactory = new ConstraintFactoryImpl();
+	private String configurationFile = "META-INF/validation.xml";
+	private final ValidationProvider provider;
+	private final ValidationProviderResolver providerResolver;
+
+	public ValidatorBuilderImpl(BootstrapState state) {
+		if (state.getValidationProviderResolver() == null) {
+			this.providerResolver = new DefaultValidationProviderResolver();
+		}
+		else {
+			this.providerResolver = state.getValidationProviderResolver();
+		}
+		this.provider = null;
+	}
+
+	public ValidatorBuilderImpl(ValidationProvider provider) {
+		if ( provider == null ) {
+			throw new ValidationException( "Assertion error: inconsistent ValidatorBuilderImpl construction");
+		}
+		this.provider = provider;
+		this.providerResolver = null;
+	}
+
+	public ValidatorBuilderImpl messageResolver(MessageResolver resolver) {
+		this.messageResolver = resolver;
+		return this;
+	}
+
+	public ValidatorBuilderImpl constraintFactory(ConstraintFactory constraintFactory) {
+		this.constraintFactory = constraintFactory;
+		return this;
+	}
+
+	public ValidatorFactory build() {
+		if ( isSpecificProvider() ) {
+			return provider.buildValidatorFactory( this );
+		}
+		else {
+			//read provider name from configuration
+			Class<? extends ValidatorBuilder<?>> providerClass = null;
+
+			if ( providerClass != null ) {
+				for ( ValidationProvider provider : providerResolver.getValidationProviders() ) {
+					if ( provider.isSuitable( providerClass ) ) {
+						return provider.buildValidatorFactory( this );
+					}
+				}
+				throw new ValidationException( "Unable to find provider: " + providerClass );
+			}
+			else {
+				List<ValidationProvider> providers = providerResolver.getValidationProviders();
+				assert providers.size() != 0; //I run therefore I am
+				return providers.get( 0 ).buildValidatorFactory( this );
+			}
+		}
+	}
+
+	private boolean isSpecificProvider() {
+		return provider != null;
+	}
+
+	public MessageResolver getMessageResolver() {
+		return messageResolver;
+	}
+
+	public ConstraintFactory getConstraintFactory() {
+		return constraintFactory;
+	}
+
+	public ValidatorBuilderImpl configure(InputStream stream) {
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
+	}
+
+	public InputStream getConfigurationStream() {
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
+	}
+}


Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorBuilderImpl.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,50 @@
+// $Id: ValidatorFactoryImpl.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import javax.validation.ConstraintFactory;
+import javax.validation.MessageResolver;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ValidatorBuilderImplementor;
+
+import org.hibernate.validation.engine.ValidatorImpl;
+
+/**
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class ValidatorFactoryImpl implements ValidatorFactory {
+
+	private final MessageResolver messageResolver;
+	private final ConstraintFactory constraintFactory;
+
+
+	public ValidatorFactoryImpl(ValidatorBuilderImplementor validatorBuilder) {
+		this.messageResolver = validatorBuilder.getMessageResolver();
+		this.constraintFactory = validatorBuilder.getConstraintFactory();
+		//do init metadata from XML form
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <T> Validator<T> getValidator(Class<T> clazz) {
+		return new ValidatorImpl<T>( clazz, constraintFactory, messageResolver );
+	}
+}


Property changes on: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/impl/ValidatorFactoryImpl.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/IdentitySet.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/IdentitySet.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/IdentitySet.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,107 @@
+// $Id: IdentitySet.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Set that compares object by identity rather than equality.
+ *
+ * @author Emmanuel Bernard
+ */
+public class IdentitySet implements Set {
+	private Map<Object, Object> map;
+	private Object CONTAINS = new Object();
+
+	public IdentitySet() {
+		this( 10 );
+	}
+
+	public IdentitySet(int size) {
+		this.map = new IdentityHashMap<Object, Object>( size );
+	}
+
+	public int size() {
+		return map.size();
+	}
+
+	public boolean isEmpty() {
+		return map.isEmpty();
+	}
+
+	public boolean contains(Object o) {
+		return map.containsKey( o );
+	}
+
+	public Iterator iterator() {
+		return map.keySet().iterator();
+	}
+
+	public Object[] toArray() {
+		return map.keySet().toArray();
+	}
+
+	public boolean add(Object o) {
+		return map.put( o, CONTAINS ) == null;
+	}
+
+	public boolean remove(Object o) {
+		return map.remove( o ) == CONTAINS;
+	}
+
+	public boolean addAll(Collection c) {
+		boolean doThing = false;
+		for ( Object o : c ) {
+			doThing = doThing || add( o );
+		}
+		return doThing;
+	}
+
+	public void clear() {
+		map.clear();
+	}
+
+	public boolean removeAll(Collection c) {
+		boolean remove = false;
+		for ( Object o : c ) {
+			remove = remove || remove( o );
+		}
+		return remove;
+	}
+
+	public boolean retainAll(Collection c) {
+		throw new UnsupportedOperationException();
+	}
+
+	public boolean containsAll(Collection c) {
+		for ( Object o : c ) {
+			if ( !contains( o ) ) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	public Object[] toArray(Object[] a) {
+		return map.keySet().toArray( a );
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/LoggerFactory.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/LoggerFactory.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/LoggerFactory.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,32 @@
+// :$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import org.slf4j.Logger;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class LoggerFactory {
+	public static Logger make() {
+		Throwable t = new Throwable();
+		StackTraceElement directCaller = t.getStackTrace()[1];
+		return org.slf4j.LoggerFactory.getLogger( directCaller.getClassName() );
+	}
+}
+

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/PropertyIterator.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,102 @@
+// $Id: PropertyIterator.java 112 2008-09-30 08:08:50Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+/**
+ * @author Hardy Ferentschik
+ */
+
+/**
+ * Helper class to iterate over a property. After constructing an instance of this class one can with
+ * successive calls to <code>split()</code> split the property into a head and tail section. The head will contain the
+ * property up to the first '.' and tail the rest. If head is an indexed value it is further seperated into its actual
+ * value and index. For example, <code>new PropertyNavigator("order[2].orderNumer").split()</code> will result into:
+ * <ul>
+ * <li> <code>getHead() == "order"</code> </li>
+ * <li> <code>getIndex() == "2"</code> </li>
+ * <li> <code>getTail() == "orderNumber"</code> </li>
+ * </ul>.
+ */
+public class PropertyIterator {
+	final String originalProperty;
+	String head;
+	String index;
+	String tail;
+
+	public PropertyIterator(String property) {
+		this.originalProperty = property;
+		if ("".equals( property ) ) {
+			this.tail = null;
+		} else {
+			this.tail = property;
+		}
+	}
+
+	public boolean hasNext() {
+		return tail != null;
+	}
+
+	/**
+	 * Splits the property at the next '.'
+	 *
+	 * @todo Add error handling in case the property uses wrong characters or has unbalanced []
+	 */
+	public void split() {
+
+		if ( tail == null ) {
+			return;
+		}
+
+		String[] tokens = tail.split( "\\.", 2 ); // split the property at the first .
+
+		head = tokens[0];
+		index = null;
+
+		if ( head.contains( "[" ) ) {
+			head = tokens[0].substring( 0, tokens[0].indexOf( "[" ) );
+			index = tokens[0].substring( tokens[0].indexOf( "[" ) + 1, tokens[0].indexOf( "]" ) );
+		}
+
+		if ( tokens.length > 1 ) {
+			tail = tokens[1];
+		}
+		else {
+			tail = null;
+		}
+	}
+
+	public String getOriginalProperty() {
+		return originalProperty;
+	}
+
+	public String getHead() {
+		return head;
+	}
+
+	public String getTail() {
+		return tail;
+	}
+
+	public String getIndex() {
+		return index;
+	}
+
+	public boolean isIndexed() {
+		return index != null;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/util/ReflectionHelper.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,309 @@
+// $Id: ReflectionHelper.java 111 2008-09-30 08:00:12Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import java.beans.Introspector;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.util.List;
+import javax.validation.ValidationException;
+
+/**
+ * Some reflection utility methods.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ReflectionHelper {
+
+	private ReflectionHelper() {
+	}
+
+	/**
+	 * Process bean properties getter by applying the JavaBean naming conventions.
+	 *
+	 * @param member the member for which to get the property name.
+	 *
+	 * @return The bean method name with the "is" or "get" prefix stripped off, <code>null</code>
+	 *         the method name id not according to the JavaBeans standard.
+	 *
+	 * @todo reference the JavaBean naming conventions spec here
+	 */
+	public static String getPropertyName(Member member) {
+		String name = null;
+
+		if ( member instanceof Field ) {
+			name = member.getName();
+		}
+
+		if ( member instanceof Method ) {
+			String methodName = member.getName();
+			if ( methodName.startsWith( "is" ) ) {
+				name = Introspector.decapitalize( methodName.substring( 2 ) );
+			}
+			else if ( methodName.startsWith( "get" ) ) {
+				name = Introspector.decapitalize( methodName.substring( 3 ) );
+			}
+		}
+
+		return name;
+	}
+
+	/**
+	 * @param member The <code>Member</code> instance for which to retrieve the type.
+	 *
+	 * @return Retrurns the <code>Type</code> of the given <code>Field</code> or <code>Method</code>.
+	 *
+	 * @throws IllegalArgumentException in case <code>member</code> is not a <code>Field</code> or <code>Method</code>.
+	 */
+	public static Type typeOf(Member member) {
+		if ( member instanceof Field ) {
+			return ( ( Field ) member ).getGenericType();
+		}
+		if ( member instanceof Method ) {
+			return ( ( Method ) member ).getGenericReturnType();
+		}
+		throw new IllegalArgumentException( "Member " + member + " is neither a field nor a method" );
+	}
+
+
+	public static Object getValue(Member member, Object object) {
+		Object value = null;
+
+		if ( member instanceof Method ) {
+			Method method = ( Method ) member;
+			try {
+				value = method.invoke( object );
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException( "Unable to access " + method.getName(), e );
+			}
+			catch ( InvocationTargetException e ) {
+				throw new ValidationException( "Unable to access " + method.getName(), e );
+			}
+		}
+		else if ( member instanceof Field ) {
+			Field field = ( Field ) member;
+			try {
+				value = field.get( object );
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException( "Unable to access " + field.getName(), e );
+			}
+		}
+		return value;
+	}
+
+	public static void setAccessibility(Member member) {
+		if ( !Modifier.isPublic( member.getModifiers() ) ) {
+			//Sun's ease of use, sigh...
+			( ( AccessibleObject ) member ).setAccessible( true );
+		}
+	}
+
+	public static Class<?> loadClass(String name, Class caller) throws ClassNotFoundException {
+		try {
+			//try context classloader, if fails try caller classloader
+			ClassLoader loader = Thread.currentThread().getContextClassLoader();
+			if ( loader != null ) {
+				return loader.loadClass( name );
+			}
+		}
+		catch ( ClassNotFoundException e ) {
+			//trying caller classloader
+			if ( caller == null ) {
+				throw e;
+			}
+		}
+		return Class.forName( name, true, caller.getClassLoader() );
+	}
+
+	/**
+	 * Determines the type of elements of a generic collection or array.
+	 *
+	 * @param type the collection or array type.
+	 *
+	 * @return the element type of the generic collection/array or <code>null</code> in case the specified type is not a collection/array or the
+	 *         element type cannot be determined.
+	 *
+	 * @todo Verify algorithm. Does this hold up in most cases?
+	 */
+	public static Type getIndexedType(Type type) {
+		Type indexedType = null;
+		if ( isCollection( type ) && type instanceof ParameterizedType ) {
+			ParameterizedType paramType = ( ParameterizedType ) type;
+			Class collectionClass = getCollectionClass( type );
+			if ( collectionClass == Collection.class || collectionClass == java.util.List.class || collectionClass == java.util.Set.class || collectionClass == java.util.SortedSet.class ) {
+				indexedType = paramType.getActualTypeArguments()[0];
+			}
+			else if ( collectionClass == Map.class || collectionClass == java.util.SortedMap.class ) {
+				indexedType = paramType.getActualTypeArguments()[1];
+			}
+		}
+		else if ( ReflectionHelper.isArray( type ) && type instanceof GenericArrayType ) {
+			GenericArrayType arrayTye = ( GenericArrayType ) type;
+			indexedType = arrayTye.getGenericComponentType();
+		}
+		return indexedType;
+	}
+
+
+	/**
+	 * @param type the type to check.
+	 *
+	 * @return Returns <code>true</code> if <code>type</code> is an array type or <code>false</code> otherwise.
+	 */
+	public static boolean isArray(Type type) {
+		if ( type instanceof Class ) {
+			return ( ( Class ) type ).isArray();
+		}
+		return type instanceof GenericArrayType;
+	}
+
+
+	/**
+	 * @param type the type to check.
+	 *
+	 * @return Returns <code>true</code> if <code>type</code> is a collection type or <code>false</code> otherwise.
+	 */
+	public static boolean isCollection(Type type) {
+		return getCollectionClass( type ) != null;
+	}
+
+
+	/**
+	 * Returns the collection class for the specified type provided it is a collection.
+	 * <p>
+	 * This is a simplified version of commons annotations </code>TypeUtils.getCollectionClass()</code>.
+	 * </p>
+	 *
+	 * @param type the <code>Type</code> to check.
+	 *
+	 * @return the collection class, or <code>null</code> if type is not a collection class.
+	 */
+	@SuppressWarnings("unchecked")
+	public static Class<? extends Collection> getCollectionClass(Type type) {
+		if ( type instanceof Class && isCollectionClass( ( Class ) type ) ) {
+			return ( Class<? extends Collection> ) type;
+		}
+		if ( type instanceof ParameterizedType ) {
+			return getCollectionClass( ( ( ParameterizedType ) type ).getRawType() );
+		}
+		if ( type instanceof WildcardType ) {
+			Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds();
+			if ( upperBounds.length == 0 ) {
+				return null;
+			}
+			return getCollectionClass( upperBounds[0] );
+		}
+		return null;
+	}
+
+	/**
+	 * Checks whether the specified class parameter is an instance of a collection class.
+	 *
+	 * @param clazz <code>Class</code> to check.
+	 *
+	 * @return <code>true</code> is <code>clazz</code> is instance of a collection class, <code>false</code> otherwise.
+	 */
+	private static boolean isCollectionClass(Class<?> clazz) {
+        Class[] interfaces = clazz.getInterfaces();
+
+        for ( Class interfaceClass : interfaces) {
+            if (interfaceClass == Collection.class
+				|| interfaceClass == java.util.List.class
+				|| interfaceClass == java.util.Set.class
+				|| interfaceClass == java.util.Map.class
+				|| interfaceClass == java.util.SortedSet.class // extension to the specs
+				|| interfaceClass == java.util.SortedMap.class) { // extension to the specs)
+                return true;
+            }
+        }
+
+        return false;
+	}
+
+	/**
+	 * Tries to retrieve the indexed value from the specified object.
+	 *
+	 * @param value The object from which to retrieve the indexed value. The object has to be non <code>null</null> and
+	 * either a collection or array.
+	 * @param index The index. The index does not have to be numerical. <code>value</code> could also be a map in which
+	 * case the index could also be a string key.
+	 * @return The indexed value or <code>null</code> if <code>value</code> is <code>null</code> or not a collection or array.
+	 * <code>null</code> is also returned in case the index does not exist.
+	 */
+	public static Object getIndexedValue(Object value, String index) {
+		if ( value == null ) {
+			return null;
+		}
+
+		// try to create the index
+		int numIndex = -1;
+		try {
+			numIndex = Integer.valueOf( index );
+		}
+		catch ( NumberFormatException nfe ) {
+			// ignore
+		}
+
+		if ( numIndex == -1 ) {  // must be a map indexed by string
+			Map<?, ?> map = ( Map<?, ?> ) value;
+			//noinspection SuspiciousMethodCalls
+			return map.get( index );
+		}
+
+		Iterator<?> iter = null;
+		Type type = value.getClass();
+		if ( isCollection( type ) ) {
+			boolean isIterable = value instanceof Iterable;
+			Map<?, ?> map = !isIterable ? ( Map<?, ?> ) value : null;
+			Iterable<?> elements = isIterable ?
+					( Iterable<?> ) value :
+					map.values();
+			iter = elements.iterator();
+
+		}
+		else if ( isArray( type ) ) {
+			List<?> arrayList = Arrays.asList( value );
+			iter = arrayList.iterator();
+		}
+
+		int i = 0;
+		Object o;
+		while ( iter.hasNext() ) {
+			o = iter.next();
+			if ( i == numIndex ) {
+				return o;
+			}
+			i++;
+		}
+		return null;
+	}
+}

Added: validator/trunk/hibernate-validator/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider
===================================================================
--- validator/trunk/hibernate-validator/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/resources/META-INF/services/javax.validation.spi.ValidationProvider	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1 @@
+org.hibernate.validation.impl.HibernateValidationProvider
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties
===================================================================
--- validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/main/resources/org/hibernate/validation/ValidationMessages.properties	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,4 @@
+validator.notNull=may not be null
+validator.length=length must be between {min} and {max}
+validator.notEmpty=may not be empty
+validator.pattern=must match "{regex}"
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/site/site.xml
===================================================================
--- validator/trunk/hibernate-validator/src/site/site.xml	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/site/site.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="Maven">
+  <bannerLeft>
+    <name>Maven</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/"/>
+    </links>
+
+    <menu ref="reports"/>
+      
+  </body>
+</project>
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/bootstrap/ValidationTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,244 @@
+// $Id: ValidationTest.java 115 2008-10-01 15:33:10Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.bootstrap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import javax.validation.Constraint;
+import javax.validation.ConstraintDescriptor;
+import javax.validation.ConstraintFactory;
+import javax.validation.InvalidConstraint;
+import javax.validation.MessageResolver;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import javax.validation.ValidationProviderResolver;
+import javax.validation.Validator;
+import javax.validation.ValidatorBuilder;
+import javax.validation.ValidatorFactory;
+import javax.validation.Context;
+import javax.validation.bootstrap.SpecializedBuilderFactory;
+import javax.validation.spi.ValidationProvider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import org.hibernate.validation.HibernateValidatorBuilder;
+import org.hibernate.validation.constraints.NotNullConstraint;
+import org.hibernate.validation.eg.Customer;
+import org.hibernate.validation.impl.ConstraintFactoryImpl;
+import org.hibernate.validation.impl.ValidatorBuilderImpl;
+import org.hibernate.validation.impl.ValidatorFactoryImpl;
+import org.hibernate.validation.impl.HibernateValidationProvider;
+
+/**
+ * Tests the validation bootstrapping.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ValidationTest {
+
+	@Test
+	public void testBootstrapAsServiceWithBuilder() {
+		HibernateValidatorBuilder builder = Validation
+				.builderType( HibernateValidatorBuilder.class )
+				.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+	}
+
+	@Test
+	public void testBootstrapAsServiceDefault() {
+		ValidatorBuilder<?> builder = Validation.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+	}
+
+	@Test
+	public void testGetCustomerValiator() {
+		ValidatorBuilder<?> builder = Validation.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+
+		ValidatorFactory factory = builder.build();
+		Validator<Customer> validator = factory.getValidator( Customer.class );
+
+		Customer customer = new Customer();
+		customer.setFirstName( "John" );
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		customer.setLastName( "Doe" );
+
+		invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+
+	@Test
+	public void testCustomMessageResolver() {
+
+		// first try with the default message resolver
+		ValidatorBuilder<?> builder = Validation.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+
+		ValidatorFactory factory = builder.build();
+		Validator<Customer> validator = factory.getValidator( Customer.class );
+
+		Customer customer = new Customer();
+		customer.setFirstName( "John" );
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		InvalidConstraint<Customer> constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong message", "may not be null", constraint.getMessage() );
+
+		//FIXME nothing guarantee that a builder can be reused
+		// now we modify the builder, get a new factory and valiator and try again
+		builder.messageResolver(
+				new MessageResolver() {
+					public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value) {
+						return "my custom message";
+					}
+				}
+		);
+		factory = builder.build();
+		validator = factory.getValidator( Customer.class );
+		invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong message", "my custom message", constraint.getMessage() );
+	}
+
+	@Test
+	public void testCustomConstraintFactory() {
+
+		ValidatorBuilder<?> builder = Validation.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+
+		ValidatorFactory factory = builder.build();
+		Validator<Customer> validator = factory.getValidator( Customer.class );
+
+		Customer customer = new Customer();
+		customer.setFirstName( "John" );
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		InvalidConstraint<Customer> constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong message", "may not be null", constraint.getMessage() );
+
+		//FIXME nothing guarantee that a builder can be reused
+		// now we modify the builder, get a new factory and valiator and try again
+		builder.constraintFactory(
+				new ConstraintFactory() {
+					public <T extends Constraint> T getInstance(Class<T> key) {
+						if ( key == NotNullConstraint.class ) {
+							return ( T ) new BadlyBehavedNotNullConstraint();
+						}
+						return new ConstraintFactoryImpl().getInstance( key );
+					}
+				}
+		);
+		factory = builder.build();
+		validator = factory.getValidator( Customer.class );
+		invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+	@Test
+	public void testCustomResolverAndType() {
+		ValidationProviderResolver resolver = new ValidationProviderResolver() {
+
+			public List<ValidationProvider> getValidationProviders() {
+				List<ValidationProvider> list = new ArrayList<ValidationProvider>();
+				list.add( new HibernateValidationProvider() );
+				return list;
+			}
+		};
+
+
+		HibernateValidatorBuilder builder = Validation
+					.builderType( HibernateValidatorBuilder.class )
+					.providerResolver( resolver )
+					.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+	}
+
+	@Test
+	public void testCustomResolver() {
+		ValidationProviderResolver resolver = new ValidationProviderResolver() {
+
+			public List<ValidationProvider> getValidationProviders() {
+				List<ValidationProvider> list = new ArrayList<ValidationProvider>();
+				list.add( new HibernateValidationProvider() );
+				return list;
+			}
+		};
+
+
+		ValidatorBuilder<?> builder = Validation
+			        .defineBootstrapState()
+					.providerResolver( resolver )
+					.getValidatorBuilder();
+		assertDefaultBuilderAndFactory( builder );
+	}
+
+	@Test
+	public void testFailingCustomResolver() {
+		ValidationProviderResolver resolver = new ValidationProviderResolver() {
+
+			public List<ValidationProvider> getValidationProviders() {
+				return new ArrayList<ValidationProvider>();
+			}
+		};
+
+		final SpecializedBuilderFactory<HibernateValidatorBuilder> specializedBuilderFactory =
+				Validation
+						.builderType(HibernateValidatorBuilder.class)
+						.providerResolver( resolver );
+
+		try {
+			specializedBuilderFactory.getValidatorBuilder();
+			fail();
+		}
+		catch ( ValidationException e ) {
+			assertEquals(
+					"Wrong error message",
+					"Unable to find provider: interface org.hibernate.validation.HibernateValidatorBuilder",
+					e.getMessage()
+			);
+		}
+	}
+
+	private void assertDefaultBuilderAndFactory(ValidatorBuilder builder) {
+		assertNotNull( builder );
+		assertTrue( builder instanceof ValidatorBuilderImpl );
+
+		ValidatorFactory factory = builder.build();
+		assertNotNull( factory );
+		assertTrue( factory instanceof ValidatorFactoryImpl );
+	}
+
+	class BadlyBehavedNotNullConstraint extends NotNullConstraint {
+		@Override
+		public boolean isValid(Object object, Context context) {
+			return true;
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/LengthConstraintTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/LengthConstraintTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/LengthConstraintTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,74 @@
+// $Id: LengthConstraintTest.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Annotation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class LengthConstraintTest {
+	@Test
+	public void testIsValid() {
+		LengthConstraint constraint = new LengthConstraint();
+		constraint.initialize(
+				new Length() {
+
+					public int min() {
+						return 1;
+					}
+
+					public int max() {
+						return 3;
+					}
+
+					public String message() {
+						return "{validator.length}";
+					}
+
+					public String[] groups() {
+						return new String[0];
+					}
+
+					public Class<? extends Annotation> annotationType() {
+						return this.getClass();
+					}
+				}
+		);
+
+		assertTrue( constraint.isValid( null, null ) );
+		assertFalse( constraint.isValid( "", null ) );
+		assertTrue( constraint.isValid( "f", null ) );
+		assertTrue( constraint.isValid( "fo", null ) );
+		assertTrue( constraint.isValid( "foo", null ) );
+		assertFalse( constraint.isValid( "foobar", null ) );
+
+		try {
+			constraint.isValid( new Object(), null );
+			fail();
+		}
+		catch ( IllegalArgumentException e ) {
+			// success
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotEmptyConstraintTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotEmptyConstraintTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotEmptyConstraintTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,48 @@
+// $Id: NotEmptyConstraintTest.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NotEmptyConstraintTest {
+
+	@Test
+	public void testIsValid() {
+		NotEmptyConstraint constraint = new NotEmptyConstraint();
+
+		assertTrue( constraint.isValid( null, null ) );
+		assertTrue( constraint.isValid( "foo", null ) );
+		assertTrue( constraint.isValid( "  ", null ) );
+
+		assertFalse( constraint.isValid( "", null ) );
+
+		try {
+			constraint.isValid( new Object(), null );
+			fail();
+		}
+		catch ( IllegalArgumentException e ) {
+			// success
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotNullConstraintTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotNullConstraintTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/NotNullConstraintTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+// $Id: NotNullConstraintTest.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NotNullConstraintTest {
+
+	@Test
+	public void testIsValid() {
+		NotNullConstraint constraint = new NotNullConstraint();
+
+		assertFalse( constraint.isValid( null, null ) );
+		assertTrue( constraint.isValid( new Object(), null ) );
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternConstraintTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternConstraintTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/PatternConstraintTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,72 @@
+// $Id: PatternConstraintTest.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.constraints;
+
+import java.lang.annotation.Annotation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class PatternConstraintTest {
+	@Test
+	public void testIsValid() {
+		PatternConstraint constraint = new PatternConstraint();
+		constraint.initialize(
+				new Pattern() {
+
+					public String message() {
+						return "{validator.pattern}";
+					}
+
+					public String[] groups() {
+						return new String[0];
+					}
+
+					public String regex() {
+						return "foobar";
+					}
+
+					public int flags() {
+						return 0;
+					}
+
+					public Class<? extends Annotation> annotationType() {
+						return this.getClass();
+					}
+				}
+		);
+
+		assertTrue( constraint.isValid( null, null ) );
+		assertFalse( constraint.isValid( "", null ) );
+		assertFalse( constraint.isValid( "bla bla", null ) );
+		assertFalse( constraint.isValid( "This test is not foobar", null ) );
+
+		try {
+			constraint.isValid( new Object(), null );
+			fail();
+		}
+		catch ( IllegalArgumentException e ) {
+			// success
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Actor.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Actor.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Actor.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,89 @@
+// $Id: Actor.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.Valid;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Actor implements Person {
+
+	private String firstName;
+	private String middleName;
+	private String lastName;
+
+	@Valid
+	private List<Actor> playedWith = new ArrayList<Actor>();
+
+	public Actor() {
+
+	}
+
+	public Actor(String firstName, String lastName) {
+		this.firstName = firstName;
+		this.lastName = lastName;
+	}
+
+	public List<Actor> getPlayedWith() {
+		return playedWith;
+	}
+
+	public void setPlayedWith(List<Actor> playedWith) {
+		this.playedWith = playedWith;
+	}
+
+	public void addPlayedWith(Actor playedWith) {
+		this.playedWith.add( playedWith );
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getMiddleName() {
+		return middleName;
+	}
+
+	public void setMiddleName(String middleName) {
+		this.middleName = middleName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	@Override
+	public String toString() {
+		return "Actor{" +
+				"firstName='" + firstName + '\'' +
+				", middleName='" + middleName + '\'' +
+				", lastName='" + lastName + '\'' +
+				'}';
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Address.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Address.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Address.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,73 @@
+// $Id: Address.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.Length;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Address {
+	@NotNull
+	@Length(max = 30)
+	private String addressline1;
+
+	@NotNull
+	@Length(max = 30)
+	private String addressline2;
+
+	private String zipCode;
+
+	private String city;
+
+	public String getAddressline1() {
+		return addressline1;
+	}
+
+	public void setAddressline1(String addressline1) {
+		this.addressline1 = addressline1;
+	}
+
+	public String getAddressline2() {
+		return addressline2;
+	}
+
+	public void setAddressline2(String addressline2) {
+		this.addressline2 = addressline2;
+	}
+
+	public String getZipCode() {
+		return zipCode;
+	}
+
+	public void setZipCode(String zipCode) {
+		this.zipCode = zipCode;
+	}
+
+	@Length(max = 30)
+	@NotNull
+	public String getCity() {
+		return city;
+	}
+
+	public void setCity(String city) {
+		this.city = city;
+	}
+}
+

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Animal.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Animal.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Animal.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,52 @@
+// $Id: Animal.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.NotEmpty;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Animal {
+	public enum Domain {
+		PROKARYOTA, EUKARYOTA
+	}
+
+	@NotEmpty(groups = { "first", "second" })
+	private String name;
+
+	@NotNull(groups = "first")
+	private Domain domain;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public Domain getDomain() {
+		return domain;
+	}
+
+	public void setDomain(Domain domain) {
+		this.domain = domain;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Author.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Author.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Author.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,62 @@
+// $Id: Author.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.Length;
+import org.hibernate.validation.constraints.NotEmpty;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Author {
+
+	@NotEmpty(groups = "last")
+	private String firstName;
+
+	@NotNull(groups = "first")
+	@NotEmpty(groups = "first")
+	private String lastName;
+
+	@Length(max = 20, groups = "last")
+	private String company;
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	public String getCompany() {
+		return company;
+	}
+
+	public void setCompany(String company) {
+		this.company = company;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Book.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Book.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Book.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,66 @@
+// $Id: Book.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import javax.validation.GroupSequence;
+import javax.validation.Valid;
+
+import org.hibernate.validation.constraints.Length;
+import org.hibernate.validation.constraints.NotEmpty;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at GroupSequence(name = "default", sequence = { "first", "second", "last" })
+public class Book {
+	@NotNull(groups = "first")
+	@NotEmpty(groups = "first")
+	private String title;
+
+	@Length(max = 30, groups = "second")
+	private String subtitle;
+
+	@Valid
+	@NotNull(groups = "first")
+	private Author author;
+
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public String getSubtitle() {
+		return subtitle;
+	}
+
+	public void setSubtitle(String subtitle) {
+		this.subtitle = subtitle;
+	}
+
+	public Author getAuthor() {
+		return author;
+	}
+
+	public void setAuthor(Author author) {
+		this.author = author;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Boy.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Boy.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Boy.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,64 @@
+// $Id: Boy.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Boy implements Person {
+
+	private String firstName;
+	private String middleName;
+	private String lastName;
+	private Integer age;
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getMiddleName() {
+		return middleName;
+	}
+
+	public void setMiddleName(String middleName) {
+		this.middleName = middleName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	public void setAge(Integer age) {
+		this.age = age;
+	}
+
+	@NotNull
+	public Integer age() {
+		return age;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Customer.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Customer.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Customer.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,67 @@
+// $Id: Customer.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.Valid;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Customer implements Person {
+
+	private String firstName;
+	private String middleName;
+	private String lastName;
+
+	@Valid
+	private List<Order> orderList = new ArrayList<Order>();
+
+	public void addOrder(Order order) {
+		orderList.add( order );
+	}
+
+	public List<Order> getOrderList() {
+		return orderList;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getMiddleName() {
+		return middleName;
+	}
+
+	public void setMiddleName(String middleName) {
+		this.middleName = middleName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Dictonary.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,57 @@
+// $Id: Dictonary.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import javax.validation.GroupSequence;
+import javax.validation.GroupSequences;
+
+import org.hibernate.validation.constraints.NotEmpty;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at GroupSequences({
+		@GroupSequence(name = "default-alias", sequence = { "default" }),
+		@GroupSequence(name = "all", sequence = { "default", "translate" })
+})
+public class Dictonary extends Book {
+	@NotNull(groups = "translate")
+	@NotEmpty(groups = "translate")
+	private String translatesTo;
+
+	@NotNull(groups = "translate")
+	@NotEmpty(groups = "translate")
+	private String translatesFrom;
+
+	public String getTranslatesTo() {
+		return translatesTo;
+	}
+
+	public void setTranslatesTo(String translatesTo) {
+		this.translatesTo = translatesTo;
+	}
+
+	public String getTranslatesFrom() {
+		return translatesFrom;
+	}
+
+	public void setTranslatesFrom(String translatesFrom) {
+		this.translatesFrom = translatesFrom;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Engine.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Engine.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Engine.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,41 @@
+// $Id: Engine.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.Pattern;
+import org.hibernate.validation.constraints.Patterns;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Engine {
+	@Patterns({
+			@Pattern(regex = "^[A-Z0-9-]+$",
+					message = "must contain alphabetical characters only"),
+			@Pattern(regex = "^....-....-....$", message = "must match ....-....-....")
+	})
+	private String serialNumber;
+
+	public String getSerialNumber() {
+		return serialNumber;
+	}
+
+	public void setSerialNumber(String serialNumber) {
+		this.serialNumber = serialNumber;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/EnglishDictonary.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/EnglishDictonary.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/EnglishDictonary.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,30 @@
+// $Id: EnglishDictonary.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import javax.validation.GroupSequence;
+import javax.validation.GroupSequences;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at GroupSequences({
+		@GroupSequence(name = "default", sequence = { "first" })  // illegal - default is already defined in Book
+})
+public class EnglishDictonary extends Dictonary {
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Female.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,51 @@
+// $Id: Female.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.eg.constraint.NoGroups;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Female implements Person {
+
+	// @NoGroups is an invalid annotation (missing group paramter)
+	@NoGroups
+	private String firstName;
+	private String lastName;
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	public String getMiddleName() {
+		return null;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Male.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,50 @@
+// $Id: Male.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.eg.constraint.NoMessage;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Male implements Person {
+    // @NoMessage is an invalid annotation (no message paramter)
+	@NoMessage
+	private String firstName;
+	private String lastName;
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	public String getMiddleName() {
+		return null;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Order.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Order.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Order.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+// $Id: Order.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Order {
+	@NotNull
+	Integer orderNumber;
+
+	public Integer getOrderNumber() {
+		return orderNumber;
+	}
+
+	public void setOrderNumber(Integer orderNumber) {
+		this.orderNumber = orderNumber;
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Person.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Person.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Person.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+// $Id: Person.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+import org.hibernate.validation.constraints.NotEmpty;
+import org.hibernate.validation.constraints.NotNull;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public interface Person {
+	@NotNull
+	@NotEmpty
+	String getFirstName();
+
+	String getMiddleName();
+
+	@NotNull
+	@NotEmpty
+	String getLastName();
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Unconstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Unconstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/Unconstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,26 @@
+// : Person.java 69 2008-09-08 11:05:07Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg;
+
+/**
+ * Empty un-constraint test class.
+ *
+ * @author Hardy Ferentschik
+ */
+public class Unconstraint {
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroups.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroups.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroups.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,37 @@
+// $Id: NoGroups.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg.constraint;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at ConstraintValidator(NoGroupsConstraint.class)
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface NoGroups {
+	public abstract String message() default "default message";
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroupsConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroupsConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoGroupsConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,34 @@
+// $Id: NoGroupsConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg.constraint;
+
+import javax.validation.Constraint;
+import javax.validation.Context;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NoGroupsConstraint implements Constraint<NoGroups> {
+
+	public void initialize(NoGroups parameters) {
+	}
+
+	public boolean isValid(Object object, Context context) {
+		return false;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessage.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessage.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessage.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,37 @@
+// $Id: NoMessage.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg.constraint;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.ConstraintValidator;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at ConstraintValidator(NoMessageConstraint.class)
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface NoMessage {
+	public abstract String[] groups() default { };
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessageConstraint.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessageConstraint.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/eg/constraint/NoMessageConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,34 @@
+// $Id: NoMessageConstraint.java 110 2008-09-29 23:46:37Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.eg.constraint;
+
+import javax.validation.Constraint;
+import javax.validation.Context;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class NoMessageConstraint implements Constraint<NoMessage> {
+
+	public void initialize(NoMessage parameters) {
+	}
+
+	public boolean isValid(Object object, Context context) {
+		return false;
+	}
+}
\ No newline at end of file

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/ValidatorImplTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,428 @@
+// $Id: ValidatorImplTest.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.engine;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.validation.InvalidConstraint;
+import javax.validation.ValidationException;
+import javax.validation.Validator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+import org.hibernate.validation.eg.Actor;
+import org.hibernate.validation.eg.Address;
+import org.hibernate.validation.eg.Animal;
+import org.hibernate.validation.eg.Author;
+import org.hibernate.validation.eg.Book;
+import org.hibernate.validation.eg.Boy;
+import org.hibernate.validation.eg.Customer;
+import org.hibernate.validation.eg.Dictonary;
+import org.hibernate.validation.eg.Engine;
+import org.hibernate.validation.eg.EnglishDictonary;
+import org.hibernate.validation.eg.Female;
+import org.hibernate.validation.eg.Male;
+import org.hibernate.validation.eg.Order;
+import org.hibernate.validation.eg.Unconstraint;
+
+/**
+ * Tests for the implementation of <code>Validator</code>.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ValidatorImplTest {
+
+	/**
+	 * JSR 303: Constraint definition properties - message (2.1.1.1)
+	 */
+	@Test
+	public void testConstraintWithNoMessage() {
+		try {
+			new ValidatorImpl<Male>( Male.class );
+			fail();
+		}
+		catch ( ValidationException e ) {
+			assertEquals(
+					"Wrong error message", "Constraint annotation has to define message element.", e.getMessage()
+			);
+		}
+	}
+
+	/**
+	 * JSR 303: Constraint definition properties - groups (2.1.1.2)
+	 */
+	@Test
+	public void testConstraintWithNoGroups() {
+		try {
+			new ValidatorImpl<Female>( Female.class );
+			fail();
+		}
+		catch ( ValidationException e ) {
+			assertEquals(
+					"Wrong error message", "Constraint annotation has to define groups element.", e.getMessage()
+			);
+		}
+	}
+
+	/**
+	 * JSR 303: Requirements on classes to be validates (3.1)
+	 */
+	@Test
+	public void testWrongMethodName() {
+		try {
+			new ValidatorImpl<Boy>( Boy.class );
+			fail();
+		}
+		catch ( ValidationException e ) {
+			assertEquals(
+					"Wrong error message",
+					"Annoated methods must follow the JavaBeans naming convention. age() does not.",
+					e.getMessage()
+			);
+		}
+	}
+
+
+	@Test( expected = IllegalArgumentException.class)
+	public void testNullParamterToValidatorImplConstructor() {
+		new ValidatorImpl<Unconstraint>( null);
+	}
+
+	@Test	
+	public void testUnconstraintClass() {
+		Validator<Unconstraint> validator = new ValidatorImpl<Unconstraint>( Unconstraint.class );
+		assertTrue( "There should be no constraints", !validator.hasConstraints() );
+	}
+
+	@Test
+	public void testHasConstraints() {
+		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
+		assertTrue( "There should be constraints", validatorCustomer.hasConstraints() );
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testValidateWithNull() {
+		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
+		validatorCustomer.validate( null );
+	}
+
+	@Test(expected = IllegalArgumentException.class)
+	public void testValidateWithNullProperty() {
+		Validator<Customer> validatorCustomer = new ValidatorImpl<Customer>( Customer.class );
+		validatorCustomer.validate( null, "firstName" );
+	}
+
+	@Test
+	public void testGroups() {
+		Validator<Book> validator = new ValidatorImpl<Book>( Book.class );
+
+		Author author = new Author();
+		author.setLastName( "" );
+		author.setFirstName( "" );
+		Book book = new Book();
+		book.setTitle( "" );
+		book.setAuthor( author );
+
+		Set<InvalidConstraint<Book>> invalidConstraints = validator.validate( book, "first", "second", "last" );
+		assertEquals( "Wrong number of constraints", 3, invalidConstraints.size() );
+
+		author.setFirstName( "Gavin" );
+		author.setLastName( "King" );
+
+		invalidConstraints = validator.validate( book, "first", "second", "last" );
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "may not be empty", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Book.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", book, constraint.getRootBean() );
+		assertEquals( "Wrong value", book.getTitle(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "title", constraint.getPropertyPath() );
+
+		book.setTitle( "Hibernate Persistence with JPA" );
+		book.setSubtitle( "Revised Edition of Hibernate in Action" );
+
+		invalidConstraints = validator.validate( book, "first", "second", "last" );
+		constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "length must be between 0 and 30", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Book.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", book, constraint.getRootBean() );
+		assertEquals( "Wrong value", book.getSubtitle(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "subtitle", constraint.getPropertyPath() );
+
+		book.setSubtitle( "Revised Edition" );
+		author.setCompany( "JBoss a divison of RedHat" );
+
+		invalidConstraints = validator.validate( book, "first", "second", "last" );
+		constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "length must be between 0 and 20", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Author.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", book, constraint.getRootBean() );
+		assertEquals( "Wrong value", author.getCompany(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "author.company", constraint.getPropertyPath() );
+
+		author.setCompany( "JBoss" );
+
+		invalidConstraints = validator.validate( book, "first", "second", "last" );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+	@Test
+	public void testDefaultGroupSequence() {
+		Validator<Book> validator = new ValidatorImpl<Book>( Book.class );
+
+		Author author = new Author();
+		author.setLastName( "" );
+		author.setFirstName( "" );
+		Book book = new Book();
+		book.setAuthor( author );
+
+		Set<InvalidConstraint<Book>> invalidConstraints = validator.validate( book, "default" );
+		assertEquals( "Wrong number of constraints", 2, invalidConstraints.size() );
+
+		author.setFirstName( "Gavin" );
+		author.setLastName( "King" );
+
+		invalidConstraints = validator.validate( book, "default" );
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "may not be null", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Book.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", book, constraint.getRootBean() );
+		assertEquals( "Wrong value", book.getTitle(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "title", constraint.getPropertyPath() );
+
+		book.setTitle( "Hibernate Persistence with JPA" );
+		book.setSubtitle( "Revised Edition of Hibernate in Action" );
+
+		invalidConstraints = validator.validate( book, "default" );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		book.setSubtitle( "Revised Edition" );
+		author.setCompany( "JBoss a divison of RedHat" );
+
+		invalidConstraints = validator.validate( book, "default" );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		author.setCompany( "JBoss" );
+
+		invalidConstraints = validator.validate( book, "default" );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+	@Test
+	public void testBasicValidation() {
+		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+
+		Customer customer = new Customer();
+		customer.setFirstName( "John" );
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		customer.setLastName( "Doe" );
+
+		invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+	@Test
+	public void testGroupSequences() {
+		Validator<Dictonary> validator = new ValidatorImpl<Dictonary>( Dictonary.class );
+
+		Dictonary dictonary = new Dictonary();
+		dictonary.setTitle( "English - German" );
+		Author author = new Author();
+		author.setLastName( "-" );
+		author.setFirstName( "-" );
+		author.setCompany( "Langenscheidt Publ." );
+		dictonary.setAuthor( author );
+
+		Set<InvalidConstraint<Dictonary>> invalidConstraints = validator.validate( dictonary, "default-alias" );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+	@Test
+	public void testValidationFailureInMultipleGroups() {
+		Validator<Animal> validator = new ValidatorImpl<Animal>( Animal.class );
+		Animal elepfant = new Animal();
+		elepfant.setName( "" );
+		elepfant.setDomain( Animal.Domain.EUKARYOTA );
+
+		Set<InvalidConstraint<Animal>> invalidConstraints = validator.validate( elepfant, "first", "second" );
+		assertEquals(
+				"The should be two invalid constraints since the same propertyName gets validated in both groups",
+				1,
+				invalidConstraints.size()
+		);
+
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		Set<String> expected = new HashSet<String>();
+		expected.add( "first" );
+		expected.add( "second" );
+		assertEquals(
+				"The constraint should be invalid for both groups",
+				expected,
+				constraint.getGroups()
+		);
+	}
+
+	@Test(expected = ValidationException.class)
+	public void testInvalidSequenceName() {
+		new ValidatorImpl<EnglishDictonary>( EnglishDictonary.class );
+	}
+
+	@Test
+	public void testValidationMethod() {
+		Validator<Address> validator = new ValidatorImpl<Address>( Address.class );
+
+		Address address = new Address();
+		address.setAddressline1( null );
+		address.setAddressline2( null );
+		address.setCity( "Llanfairpwllgwyngyllgogerychwyrndrobwyll-llantysiliogogogoch" ); //town in North Wales
+
+		Set<InvalidConstraint<Address>> invalidConstraints = validator.validate( address );
+		assertEquals(
+				"we should have been 2 not null violation for addresslines and one lenth violation for city",
+				3,
+				invalidConstraints.size()
+		);
+
+		invalidConstraints = validator.validateProperty( address, "city" );
+		assertEquals(
+				"only city should be validated",
+				1,
+				invalidConstraints.size()
+		);
+
+		invalidConstraints = validator.validateProperty( address, "city" );
+		assertEquals(
+				"only city should be validated",
+				1,
+				invalidConstraints.size()
+		);
+
+		invalidConstraints = validator.validateValue( "city", "Paris" );
+		assertEquals(
+				"Paris should be a valid city name.",
+				0,
+				invalidConstraints.size()
+		);
+	}
+
+	@Test
+	public void testValidateList() {
+		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+
+		Customer customer = new Customer();
+		customer.setFirstName( "John" );
+		customer.setLastName( "Doe" );
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validate( customer );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+
+		Order order1 = new Order();
+		customer.addOrder( order1 );
+
+		invalidConstraints = validator.validate( customer );
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "may not be null", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Order.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", customer, constraint.getRootBean() );
+		assertEquals( "Wrong value", order1.getOrderNumber(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "orderList[0].orderNumber", constraint.getPropertyPath() );
+
+	}
+
+	/**
+	 * JSR 303: Multi-valued constraints (2.2)
+	 */
+	@Test
+	public void testMultiValueConstraint() {
+		Validator<Engine> validator = new ValidatorImpl<Engine>( Engine.class );
+
+		Engine engine = new Engine();
+		engine.setSerialNumber( "mail at foobar.com" );
+		Set<InvalidConstraint<Engine>> invalidConstraints = validator.validate( engine );
+		assertEquals( "Wrong number of constraints", 2, invalidConstraints.size() );
+
+		engine.setSerialNumber( "ABCDEFGH1234" );
+		invalidConstraints = validator.validate( engine );
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		engine.setSerialNumber( "ABCD-EFGH-1234" );
+		invalidConstraints = validator.validate( engine );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+
+
+	/**
+	 * JSR 303: Object graph validation (3.5.1)
+	 */
+	@Test
+	public void testGraphValidation() {
+		Actor clint = new Actor( "Clint", "Eastwood" );
+		Actor morgan = new Actor( "Morgan", "" );
+		Actor charlie = new Actor( "Charlie", "Sheen" );
+
+		clint.addPlayedWith( charlie );
+		charlie.addPlayedWith( clint );
+		charlie.addPlayedWith( morgan );
+		morgan.addPlayedWith( charlie );
+		morgan.addPlayedWith( clint );
+		clint.addPlayedWith( morgan );
+
+		Validator<Actor> validator = new ValidatorImpl<Actor>( Actor.class );
+		Set<InvalidConstraint<Actor>> invalidConstraints = validator.validate( clint );
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "may not be empty", constraint.getMessage() );
+		assertEquals( "Wrong bean class", Actor.class, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", clint, constraint.getRootBean() );
+		assertEquals( "Wrong value", morgan.getLastName(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "playedWith[0].playedWith[1].lastName", constraint.getPropertyPath() );
+	}
+
+	@Test
+	public void testValidateValue() {
+		Validator<Customer> validator = new ValidatorImpl<Customer>( Customer.class );
+
+		Order order = new Order();
+
+		Set<InvalidConstraint<Customer>> invalidConstraints = validator.validateValue(
+				"orderList[0].orderNumber", null
+		);
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+
+		InvalidConstraint constraint = invalidConstraints.iterator().next();
+		assertEquals( "Wrong number of constraints", 1, invalidConstraints.size() );
+		assertEquals( "Wrong message", "may not be null", constraint.getMessage() );
+		assertEquals( "Wrong bean class", null, constraint.getBeanClass() );
+		assertEquals( "Wrong root entity", null, constraint.getRootBean() );
+		assertEquals( "Wrong value", order.getOrderNumber(), constraint.getValue() );
+		assertEquals( "Wrong propertyName", "orderList[0].orderNumber", constraint.getPropertyPath() );
+
+		invalidConstraints = validator.validateValue( "orderList[0].orderNumber", "1234" );
+		assertEquals( "Wrong number of constraints", 0, invalidConstraints.size() );
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/impl/ResourceBundleMessageResolverTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,186 @@
+// $Id: ResourceBundleMessageResolverTest.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.impl;
+
+import java.lang.annotation.Annotation;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.ResourceBundle;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+
+import org.hibernate.validation.constraints.Length;
+import org.hibernate.validation.constraints.NotNull;
+import org.hibernate.validation.constraints.NotNullConstraint;
+import org.hibernate.validation.util.LoggerFactory;
+
+/**
+ * Tests for message resolution.
+ *
+ * @author Hardy Ferentschik
+ */
+public class ResourceBundleMessageResolverTest {
+	private static final Logger log = LoggerFactory.make();
+
+	private ResourceBundleMessageResolver resolver;
+	private NotNull notNull;
+	private Length length;
+
+	@Before
+	public void setUp() {
+		resolver = new ResourceBundleMessageResolver( new TestResources() );
+		notNull = new NotNull() {
+			public String message() {
+				return "{validator.notNull}";
+			}
+
+			public String[] groups() {
+				return new String[] { };
+			}
+
+			public Class<? extends Annotation> annotationType() {
+				return this.getClass();
+			}
+		};
+
+		length = new Length() {
+			public int min() {
+				return 0;
+			}
+
+			public int max() {
+				return Integer.MAX_VALUE;
+			}
+
+			public String message() {
+				return "{validator.length}";
+			}
+
+			public String[] groups() {
+				return new String[] { };
+			}
+
+			public Class<? extends Annotation> annotationType() {
+				return this.getClass();
+			}
+		};
+	}
+
+	@Test
+	public void testSuccessfulInterpolation() {
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
+				notNull, new String[] { }, new NotNullConstraint()
+		);
+
+		String expected = "replacement worked";
+		String actual = resolver.interpolate( "{foo}", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+
+		expected = "replacement worked replacement worked";
+		actual = resolver.interpolate( "{foo} {foo}", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+
+		expected = "This replacement worked just fine";
+		actual = resolver.interpolate( "This {foo} just fine", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+
+		expected = "{} { replacement worked }";
+		actual = resolver.interpolate( "{} { {foo} }", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+	@Test
+	public void testUnSuccessfulInterpolation() {
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
+				notNull, new String[] { }, new NotNullConstraint()
+		);
+		String expected = "foo";  // missing {}
+		String actual = resolver.interpolate( "foo", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+
+		expected = "#{foo  {}";
+		actual = resolver.interpolate( "#{foo  {}", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+	@Test
+	public void testUnkownTokenInterpolation() {
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
+				notNull, new String[] { }, new NotNullConstraint()
+		);
+		String expected = "{bar}";  // unkown token {}
+		String actual = resolver.interpolate( "{bar}", desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+	@Test
+	public void testDefaultInterpolation() {
+		ConstraintDescriptorImpl desciptor = new ConstraintDescriptorImpl(
+				notNull, new String[] { }, new NotNullConstraint()
+		);
+		String expected = "may not be null";
+		String actual = resolver.interpolate( notNull.message(), desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+
+		desciptor = new ConstraintDescriptorImpl( length, new String[] { }, new NotNullConstraint() );
+		expected = "length must be between 0 and 2147483647";  // unkown token {}
+		actual = resolver.interpolate( length.message(), desciptor, null );
+		assertEquals( "Wrong substitution", expected, actual );
+	}
+
+
+	class TestResources extends ResourceBundle implements Enumeration<String> {
+		private Map<String, String> testResources;
+		Iterator<String> iter;
+
+		public TestResources() {
+			testResources = new HashMap<String, String>();
+			// add some test messages
+			testResources.put( "foo", "replacement worked" );
+
+			iter = testResources.keySet().iterator();
+		}
+
+		public Object handleGetObject(String key) {
+			return testResources.get( key );
+		}
+
+		public Enumeration<String> getKeys() {
+			return this;
+		}
+
+		public boolean hasMoreElements() {
+			return iter.hasNext();
+		}
+
+		public String nextElement() {
+			if ( hasMoreElements() ) {
+				return iter.next();
+			}
+			else {
+				throw new NoSuchElementException();
+			}
+		}
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/IdentitySetTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/IdentitySetTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/IdentitySetTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,76 @@
+// $Id: IdentitySetTest.java 105 2008-09-29 12:37:32Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class IdentitySetTest {
+
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testAddIdenticalInstance() {
+		Set identitySet = new IdentitySet();
+		Set hashSet = new HashSet();
+		assertTrue( identitySet.size() == 0 );
+		assertTrue( hashSet.size() == 0 );
+
+		Object o1 = new Object() {
+			int counter = 0;
+
+			public int hashCode() {
+				return counter++;
+			}
+
+			public boolean equals() {
+				return false;
+			}
+		};
+		identitySet.add( o1 );
+		hashSet.add( o1 );
+		assertTrue( identitySet.size() == 1 );
+		assertTrue( hashSet.size() == 1 );
+
+		identitySet.add( o1 );
+		hashSet.add( o1 );
+		assertTrue( identitySet.size() == 1 );
+		assertTrue( hashSet.size() == 2 );
+
+		Object o2 = new Object() {
+			int counter = 0;
+
+			public int hashCode() {
+				return counter++;
+			}
+
+			public boolean equals() {
+				return false;
+			}
+		};
+		identitySet.add( o2 );
+		hashSet.add( o2 );
+		assertTrue( identitySet.size() == 2 );
+		assertTrue( hashSet.size() == 3 );
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/PropertyIteratorTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,89 @@
+// $Id: PropertyIteratorTest.java 112 2008-09-30 08:08:50Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class PropertyIteratorTest {
+
+	@Test
+	public void testSplit() {
+		String property = "order[3].deliveryAddress.addressline[1]";
+		PropertyIterator propIter = new PropertyIterator( property );
+
+		assertTrue( propIter.hasNext() );
+
+		propIter.split();
+		assertTrue( propIter.hasNext() );
+		assertEquals( "order", propIter.getHead() );
+		assertTrue( propIter.isIndexed() );
+		assertEquals( "3", propIter.getIndex() );
+		assertEquals( "deliveryAddress.addressline[1]", propIter.getTail() );
+		assertEquals( property, propIter.getOriginalProperty() );
+
+		propIter.split();
+		assertTrue( propIter.hasNext() );
+		assertEquals( "deliveryAddress", propIter.getHead() );
+		assertFalse( propIter.isIndexed() );
+		assertEquals( null, propIter.getIndex() );
+		assertEquals( "addressline[1]", propIter.getTail() );
+		assertEquals( property, propIter.getOriginalProperty() );
+
+		propIter.split();
+		assertFalse( propIter.hasNext() );
+		assertEquals( "addressline", propIter.getHead() );
+		assertTrue( propIter.isIndexed() );
+		assertEquals( "1", propIter.getIndex() );
+		assertEquals( null, propIter.getTail() );
+		assertEquals( property, propIter.getOriginalProperty() );
+	}
+
+	@Test
+	public void testNull() {
+		PropertyIterator propIter = new PropertyIterator( null );
+		assertFalse( propIter.hasNext() );
+
+		propIter.split();
+		assertFalse( propIter.hasNext() );
+		assertEquals( null, propIter.getHead() );
+		assertFalse( propIter.isIndexed() );
+		assertEquals( null, propIter.getIndex() );
+		assertEquals( null, propIter.getTail() );
+		assertEquals( null, propIter.getOriginalProperty() );
+	}
+
+	@Test
+	public void testEmptyString() {
+		PropertyIterator propIter = new PropertyIterator( "" );
+		assertFalse( propIter.hasNext() );
+
+		propIter.split();
+		assertFalse( propIter.hasNext() );
+		assertEquals( null, propIter.getHead() );
+		assertFalse( propIter.isIndexed() );
+		assertEquals( null, propIter.getIndex() );
+		assertEquals( null, propIter.getTail() );
+		assertEquals( "", propIter.getOriginalProperty() );
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/util/ReflectionHelperTest.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,72 @@
+// $Id: ReflectionHelperTest.java 111 2008-09-30 08:00:12Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package org.hibernate.validation.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import org.junit.Test;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class ReflectionHelperTest {
+	@Test
+	public void testGetIndexedValueFormMap() {
+		Map<String, Object> map = new HashMap<String, Object>();
+		Object testObject = new Object();
+		String key = "key";
+		map.put( key, testObject );
+
+		Object value = ReflectionHelper.getIndexedValue( map, key );
+		assertEquals( "We should be able to retrieve the indexed object", testObject, value );
+
+		// try to get to the value by integer index
+	    value = ReflectionHelper.getIndexedValue( map, "0" );
+		assertEquals( "We should be able to retrieve the indexed object", testObject, value );
+
+		value = ReflectionHelper.getIndexedValue( map, "foo" );
+		assertNull("A non existent index should return the null value", value);
+
+		value = ReflectionHelper.getIndexedValue( map, "2" );
+		assertNull("A non existent index should return the null value", value);
+	}
+
+	@Test
+	public void testGetIndexedValueForList() {
+		List<Object> list = new ArrayList<Object>();
+		Object testObject = new Object();
+		list.add( testObject );
+
+		Object value = ReflectionHelper.getIndexedValue( list, "0" );
+		assertEquals( "We should be able to retrieve the indexed object", testObject, value );
+
+		value = ReflectionHelper.getIndexedValue( list, "2" );
+		assertNull("A non existent index should return the null value", value);
+	}
+
+	@Test
+	public void testGetIndexedValueForNull() {
+		Object value = ReflectionHelper.getIndexedValue( null, "0" );
+		assertNull( value );
+	}
+}

Added: validator/trunk/hibernate-validator/src/test/resources/log4j.properties
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/log4j.properties	                        (rev 0)
+++ validator/trunk/hibernate-validator/src/test/resources/log4j.properties	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,24 @@
+### direct log messages to stdout ###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### direct messages to file hibernate.log ###
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.File=hibernate.log
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+### direct messages to socket - chainsaw ###
+log4j.appender.socket=org.apache.log4j.net.SocketAppender
+log4j.appender.socket.remoteHost=localhost
+log4j.appender.socket.port=4560
+log4j.appender.socket.locationInfo=true
+
+
+### set log levels - for more verbose logging change 'info' to 'debug' ###
+log4j.rootLogger=debug, stdout
+
+log4j.logger.org.hibernate.validation.engine.ValidatorImpl=trace
+


Property changes on: validator/trunk/hibernate-validator-legacy
___________________________________________________________________
Name: svn:ignore
   + build
target
test_output


Added: validator/trunk/pom.xml
===================================================================
--- validator/trunk/pom.xml	                        (rev 0)
+++ validator/trunk/pom.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.hibernate</groupId>
+    <artifactId>hibernate-validator-parent</artifactId>
+    <packaging>pom</packaging>
+    <version>1.0.0-SNAPSHOT</version>
+    <name>Hibernate Validator Parent</name>
+    <url>http://localhost/~hardy/</url>
+
+    <description>
+        Hibernate's Bean Validation (JSR-303) reference implementation.
+    </description>
+
+    <developers>
+        <developer>
+            <name>Emmanuel Bernard</name>
+            <email>emmanuel at hibernate.org</email>
+            <organization>JBoss, a division of Red Hat</organization>
+            <url>http://in.relation.to/Bloggers/Emmanuel</url>
+        </developer>
+        <developer>
+            <name>Hardy Ferentschik</name>
+            <email>hferents at redhat.com</email>
+            <organization>JBoss, a division of Red Hat</organization>
+            <url>http://in.relation.to/Bloggers/Hardy</url>
+        </developer>
+    </developers>
+
+    <repositories>
+        <repository>
+            <id>repository.jboss.org</id>
+            <name>JBoss Repository</name>
+            <url>http://repository.jboss.org/maven2</url>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>repository.jboss.org</id>
+            <name>JBoss Repository</name>
+            <url>http://repository.jboss.org/maven2</url>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <modules>
+        <module>validation-api</module>
+        <module>hibernate-validator</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>javax.validation</groupId>
+                <artifactId>validation-api</artifactId>
+                <version>${version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.4.2</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-log4j12</artifactId>
+                <version>1.4.2</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>3.2</version>
+            </dependency>
+            <dependency>
+                <groupId>junit</groupId>
+                <artifactId>junit</artifactId>
+                <version>4.4</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <extensions>
+            <extension>
+                <groupId>org.apache.maven.wagon</groupId>
+                <artifactId>wagon-webdav</artifactId>
+                <version>1.0-beta-2</version>
+            </extension>
+        </extensions>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.2</version>
+                    <configuration>
+                        <archive>
+                            <manifestEntries>
+                                <Implementation-Title>${pom.artifactId}</Implementation-Title>
+                                <Implementation-Version>${pom.version}</Implementation-Version>
+                                <Implementation-Vendor>${pom.groupId}</Implementation-Vendor>
+                                <Implementation-Vendor-Id>${pom.groupId}</Implementation-Vendor-Id>
+                                <Implementation-URL>${pom.url}</Implementation-URL>
+                                <Specification-Title>Bean Validation"</Specification-Title>
+                            </manifestEntries>
+                        </archive>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>2.0.2</version>
+                    <configuration>
+                        <source>1.5</source>
+                        <target>1.5</target>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <configuration>
+                        <forkMode>always</forkMode>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>attach-sources</id>
+                            <goals>
+                                <goal>jar</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <ciManagement>
+        <system>Hudson</system>
+        <url>http://hudson.qa.jboss.com/hudson/job/beanvalidation</url>
+    </ciManagement>
+
+    <issueManagement>
+        <system>JIRA</system>
+        <url>http://opensource.atlassian.com/projects/hibernate/browse/BVAL</url>
+    </issueManagement>
+
+    <inceptionYear>2007</inceptionYear>
+
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+
+    <scm>
+        <connection>scm:https://svn.jboss.org/repos/beancheck/ri/trunk</connection>
+        <url>http://fisheye.jboss.org/browse/Fixme</url>
+    </scm>
+
+    <distributionManagement>
+        <repository>
+            <!-- Copy the dist to the local checkout of the JBoss maven2 repo ${maven.repository.root} -->
+            <!-- It is anticipated that ${maven.repository.root} be set in user's settings.xml -->
+            <!-- todo : replace this with direct svn access once the svnkit providers are available -->
+            <id>repository.jboss.org</id>
+            <url>file://${maven.repository.root}</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots.jboss.org</id>
+            <name>JBoss Snapshot Repository</name>
+            <url>dav:https://snapshots.jboss.org/maven2</url>
+        </snapshotRepository>
+        <site>
+            <id>local</id>
+            <url>file:///Users/hardy/Sites</url>
+        </site>
+    </distributionManagement>
+
+    <reporting>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-project-info-reports-plugin</artifactId>
+                <version>2.0.1</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>jxr-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-clover-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-pmd-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>taglist-maven-plugin</artifactId>
+            </plugin>
+            <!--plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>changelog-maven-plugin</artifactId>
+            </plugin-->
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>changes-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </reporting>
+
+</project>

Added: validator/trunk/src/site/site.xml
===================================================================
--- validator/trunk/src/site/site.xml	                        (rev 0)
+++ validator/trunk/src/site/site.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="Maven">
+  <bannerLeft>
+    <name>Maven</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/"/>
+    </links>
+
+    <menu ref="modules" />  
+    <menu ref="reports"/>
+      
+
+  </body>
+</project>
\ No newline at end of file


Property changes on: validator/trunk/validation-api
___________________________________________________________________
Name: svn:ignore
   + target


Added: validator/trunk/validation-api/pom.xml
===================================================================
--- validator/trunk/validation-api/pom.xml	                        (rev 0)
+++ validator/trunk/validation-api/pom.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.hibernate</groupId>
+        <artifactId>hibernate-validator-parent</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>javax.validation</groupId>
+    <artifactId>validation-api</artifactId>
+    <packaging>jar</packaging>
+    <name>Bean Validation API</name>
+
+    <distributionManagement>
+        <site>
+            <id>local</id>
+            <url>file:///Users/hardy/Sites/${artifactId}</url>
+        </site>
+    </distributionManagement>
+</project>

Added: validator/trunk/validation-api/src/main/java/javax/validation/Constraint.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Constraint.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Constraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,49 @@
+// $Id: Constraint.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Define the logic to validate a given constraint.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface Constraint<A extends Annotation> {
+	/**
+	 * 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
+	 *
+	 * @param object object to validate
+	 * @param validationContext context in which the constraint implementation is evaluated
+	 *
+	 * @return true if object pass the constraint
+	 */
+	boolean isValid(Object object, Context validationContext);
+}
+ 
\ No newline at end of file

Added: validator/trunk/validation-api/src/main/java/javax/validation/ConstraintDescriptor.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ConstraintDescriptor.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ConstraintDescriptor.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,51 @@
+// $Id: ConstraintDescriptor.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.lang.annotation.Annotation;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Describes a single constraint.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface ConstraintDescriptor {
+	/**
+	 * @return The annotation for this constraint.
+	 */
+	Annotation getAnnotation();
+
+	/**
+	 * @return The groups the constraint is applied on.
+	 */
+	Set<String> getGroups();
+
+	/**
+	 * @return The actual constraint implementation.
+	 */
+	Constraint getConstraintImplementation();
+
+	/**
+	 * @return Returns a map containing the annotation paramter names as keys and the annotation parameter values
+	 *         as value.
+	 */
+	Map<String, Object> getParameters();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/ConstraintFactory.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ConstraintFactory.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ConstraintFactory.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,30 @@
+// $Id: ConstraintFactory.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Instantiate a Constraint from it's class.
+ * The ConstraintFactory is <b>not</b> responsible for calling Constraint#initialize
+ *
+ * @author Dhanji R. Prasanna
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface ConstraintFactory {
+	<T extends Constraint> T getInstance(Class<T> key);
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/ConstraintValidator.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ConstraintValidator.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ConstraintValidator.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,45 @@
+// $Id: ConstraintValidator.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+
+/**
+ * Link between an constraint annotation and it's constraint validation implementation.
+ * <p/>
+ * An given constraint annotation should be annotated by a @ConstraintValidator
+ * annotation which refers to its constraint validation implementation.
+ *
+ * @author Emmanuel Bernard (emmanuel at hibernate.org)
+ * @author Gavin King
+ * @author Hardy Ferentschik
+ */
+ at Documented
+ at Target({ ANNOTATION_TYPE })
+ at Retention(RUNTIME)
+public @interface ConstraintValidator {
+	/**
+	 * Constraint validation implementation
+	 */
+	public abstract Class<? extends Constraint> value();
+}
\ No newline at end of file

Added: validator/trunk/validation-api/src/main/java/javax/validation/Context.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Context.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Context.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,55 @@
+package javax.validation;
+
+/**
+ * Provide contextual data and operation when applying a given constraint implementation
+ *
+ * @author Emmanuel Bernard
+ */
+public interface Context {
+	/**
+	 * Disable default error message and default InvalidConstraint object generation.
+	 * Useful to set a different error message or generate an InvalidConstraint based on
+	 * a different property
+	 *
+	 * @see #addError(String)
+	 * @see #addError(String, String)
+	 */
+	void disableDefaultError();
+
+	/**
+	 * return the current unexpanded default message
+	 * TODO: is it needed
+	 */
+	String getDefaultErrorMessage();
+
+	/**
+	 * Add a new unexpanded error message.
+	 * <p/>
+	 * If isValid returns false, an InvalidConstraint object will be built per error message
+	 * including the default one unless #disableDefaultErrorMEssage() has been called.
+	 * <p/>
+	 * Aside from the error message, InvalidConstraint objects generated from such a call
+	 * contains the same contextual information (root bean, path and so on)
+	 * <p/>
+	 * This method can be called multiple time. One InvalidConstraint instance per call is created.
+	 *
+	 * @param message new unexpanded error message
+	 */
+	void addError(String message);
+
+	/**
+	 * Add a new unexpanded error message to a given sub property.
+	 * <p/>
+	 * If isValid returns false, an InvalidConstraint object will be built per error message including the default one
+	 * if null apply to the current property or the bean the constraint is applied on, otherwise apply to the <code>property</code> named
+	 * <p/>
+	 * TODO exception or swallowed when bean-level instance is not present?
+	 *
+	 * @param message new unexpanded error message
+	 * @param property property name the InvalidConstraint is targeting
+	 *
+	 * @throws ValidationException when the property is not present on the bean level object
+	 */
+	void addError(String message, String property);
+
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/ElementDescriptor.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ElementDescriptor.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ElementDescriptor.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,59 @@
+// $Id: ElementDescriptor.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.lang.annotation.ElementType;
+import java.util.List;
+
+/**
+ * Describes a validated element (class, field or property).
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface ElementDescriptor {
+	/**
+	 * @return The element type.
+	 */
+	ElementType getElementType();
+
+	/**
+	 * @return Statically defined returned type.
+	 *
+	 * @todo should it be Type or even completly removed
+	 */
+	Class getReturnType();
+
+	/**
+	 * @return Returns <code>true</code> if the association is cascaded, <code>false</code> otherwise.
+	 */
+	boolean isCascaded();
+
+	/**
+	 * @return All the constraint descriptors for this element.
+	 */
+	List<ConstraintDescriptor> getConstraintDescriptors();
+
+	/**
+	 * @return Property path from the root entity validated.
+	 *
+	 * @todo there is a problem in describing cyclic dependencies
+	 */
+	String getPropertyPath();
+
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/GroupSequence.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/GroupSequence.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/GroupSequence.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,34 @@
+// $Id: GroupSequence.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Target({ TYPE })
+ at Retention(RUNTIME)
+public @interface GroupSequence {
+	String name();
+
+	String[] sequence();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/GroupSequences.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/GroupSequences.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/GroupSequences.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,32 @@
+// $Id: GroupSequences.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+/**
+ * @author Hardy Ferentschik
+ */
+ at Target({ TYPE })
+ at Retention(RUNTIME)
+public @interface GroupSequences {
+	GroupSequence[] value();
+}
\ No newline at end of file

Added: validator/trunk/validation-api/src/main/java/javax/validation/InvalidConstraint.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/InvalidConstraint.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/InvalidConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,62 @@
+// $Id: InvalidConstraint.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.util.Set;
+
+/**
+ * Describe a constraint validation defect.
+ *
+ * @author Emmanuel Bernard
+ * @todo add pointers to the metadata?
+ * @todo the rational behind rootBean and propertyPath is to keep the context available to the user
+ */
+public interface InvalidConstraint<T> {
+
+	/**
+	 * @return The error message for this constraint violation.
+	 */
+	String getMessage();
+
+	/**
+	 * @return The root bean being validated.
+	 */
+	T getRootBean();
+
+	/**
+	 * @return the bean type being validated.
+	 */
+	Class<T> getBeanClass();
+
+	/**
+	 * @return the value failing to pass the constraint.
+	 */
+	Object getValue();
+
+	/**
+	 * @return the property path to the value from <code>rootBean</code>
+	 *         <code>null</code> if the value is the <code>rootBean<code> itself.
+	 */
+	String getPropertyPath();
+
+	/**
+	 * @return the list of groups that the triggered constraint applies on and which also are
+	 *         within the list of groups requested for validation.
+	 */
+	Set<String> getGroups();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/MessageResolver.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/MessageResolver.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/MessageResolver.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,37 @@
+// $Id: MessageResolver.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Interpolate a given validation message.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface MessageResolver {
+	/**
+	 * Interpolate the message from the constraint parameters and the actual validated object.
+	 *
+	 * @param message The message to interpolate.
+	 * @param constraintDescriptor The constraint descriptor.
+	 * @param value The actual validted object.
+	 *
+	 * @return Interpolated error message.
+	 */
+	String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value);
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraint.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraint.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraint.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,32 @@
+// $Id: StandardConstraint.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Define the constraint influence on standard constraint dimensions
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface StandardConstraint {
+	/**
+	 * returns the StandardConstraintDescriptor initialized according to the
+	 * constraint validator
+	 */
+	StandardConstraintDescriptor getStandardConstraints();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraintDescriptor.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraintDescriptor.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/StandardConstraintDescriptor.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,63 @@
+// $Id: StandardConstraintDescriptor.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Describe how the current constraint influences the standard constraints.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class StandardConstraintDescriptor {
+	/**
+	 * Defines the object nullability.
+	 *
+	 * @return <code>TRUE<code> if the object is nullable, <code>FALSE</code> if object is not
+	 *         nullable and <code>null</code> if nullabiltiy does not apply.
+	 */
+	public Boolean getNullability() {
+		return null;
+	}
+
+	/**
+	 * Defines the precision if the validated object is a number.
+	 *
+	 * @return the number's precision or <code>null</code> if precision does not apply.
+	 */
+	public Integer getPrecision() {
+		return null;
+	}
+
+	/**
+	 * Defines the scale if the validated object is a number.
+	 *
+	 * @return the number's scale or <code>null</code> if scale does not apply.
+	 */
+	public Integer getScale() {
+		return null;
+	}
+
+	/**
+	 * Defines the length if the validated object is a string.
+	 *
+	 * @return the strings's length or <code>null</code> if length does not apply.
+	 */
+	public Integer getLength() {
+		return null;
+	}
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/Valid.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Valid.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Valid.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+// $Id: Valid.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+
+/**
+ * Mark an association as cascaded.
+ * The associated object will be validated by cascade.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+ at Target({ METHOD, FIELD })
+ at Retention(RUNTIME)
+public @interface Valid {
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/Validation.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Validation.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Validation.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,218 @@
+// $Id: Validation.java 117 2008-10-02 10:22:31Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import javax.validation.bootstrap.DefaultValidationProviderResolver;
+import javax.validation.bootstrap.GenericBuilderFactory;
+import javax.validation.bootstrap.SpecializedBuilderFactory;
+import javax.validation.spi.BootstrapState;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * This class is the entry point for the Bean Validation framework. There are three ways to bootstrap the framework:
+ * <ul>
+ * <li>
+ * The easiest approach is to use the default Bean Validation provider.
+ * <pre>
+ * ValidatorFactory factory = Validation.getValidatorBuilder().build();
+ * </pre>
+ * In this case {@link  javax.validation.bootstrap.DefaultValidationProviderResolver  DefaultValidationProviderResolver}
+ * will be used to locate available providers.
+ *
+ * The chosen provider is defined as followed:
+ * <ul>
+ * <li>if the XML configuration defines a provider, this provider is used</li>
+ * <li>if the XML configuratio does not define a provider or if no XML configuration is present the first provider
+ * returned by the ValidationProviderResolver isntance is used.</li>
+ * </ul>
+ * </li>
+ * <li>
+ * The second bootstrap approach allows to choose a custom <code>ValidationProviderResolver</code>. The chosen
+ * <code>ValidationProvider</code> is then determined in the same way as in the default bootstrapping case (see above).
+ * <pre>
+ * ValidatorBuilder&lt?&gt; builder = Validation
+ *    .defineBootstrapState()
+ *    .providerResolver( new MyResolverStrategy() )
+ *    .getValidatorBuilder();
+ * ValidatorFactory factory = builder.build();
+ * </pre>
+ * </li>
+ * 
+ * <p/>
+ * <li>
+ * The third approach allows you to specify explicitly and in a type safe fashion the expected provider by
+ * using its specific <code>ValidatorBuilder</code> sub-interface.
+ *
+ * Optionally you can choose a custom <code>ValidationProviderResolver</code>.
+ * <pre>
+ * ACMEValidatorBuilder builder = Validation
+ *    .builderType(ACMEValidatorBuilder.class)
+ *    .providerResolver( new MyResolverStrategy() )  // optionally set the provider resolver
+ *    .getValidatorBuilder();
+ * ValidatorFactory factory = builder.build();
+ * </pre>
+ * </li>
+ * </ul>
+ * Note:<br/>
+ * <ul>
+ * <li>
+ * The ValidatorFactory object built by the bootstrap process should be cached and shared amongst
+ * Validator consumers.
+ * </li>
+ * <li>
+ * This class is thread-safe.
+ * </li>
+ * </ul>
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Feretnschik
+ * @see DefaultValidationProviderResolver
+ */
+public class Validation {
+
+	/**
+	 * Build a <code>ValidatorBuilder</code>. The actual provider choice is given by the XML configuration. If the
+	 * XML configuration does not exsist the default is taken.
+	 * <p/>
+	 * The provider list is resolved using the {@link  javax.validation.bootstrap.DefaultValidationProviderResolver  DefaultValidationProviderResolver}.
+	 *
+	 * @return <code>ValidatorBuilder</code> instance.
+	 */
+	public static ValidatorBuilder<?> getValidatorBuilder() {
+		return defineBootstrapState().getValidatorBuilder();
+	}
+
+	/**
+	 * Build a <code>ValidatorBuilder</code>. The provider list is resolved using the strategy provided to the bootstrap state.
+	 * <pre>
+	 * ValidatorBuilder&lt?&gt; builder = Validation
+	 *    .defineBootstrapState()
+	 *    .providerResolver( new MyResolverStrategy() )
+	 *    .getValidatorBuilder();
+	 * ValidatorFactory factory = builder.build();
+	 * </pre>
+	 * The actual provider choice is given by the XML configuration. If the XML configuration does not exsist the first
+	 * available provider will be returned.
+	 *
+	 * @return instance building a generic <code>ValidatorBuilder</code> compliant with the bootstrap state provided.
+	 */
+	public static GenericBuilderFactory defineBootstrapState() {
+		return new GenericBuilderFactoryImpl();
+	}
+
+	/**
+	 * Build a <code>ValidatorBuilder</code> for a particular provider implementation.
+	 * Optionally override the provider resolution strategy used to determine the provider.
+	 * <p/>
+	 * Used by applications targeting a specific provider programmatically.
+	 * <p/>
+	 * <pre>
+	 * ACMEValidatorBuilder builder = Validation.builderType(ACMEValidatorBuilder.class)
+	 *     .providerResolver( new MyResolverStrategy() )
+	 *     .build();
+	 * </pre>,
+	 * where <code>ACMEValidatorBuilder</code> is the <code>ValidatorBuiler</code> sub interface uniquely identifying
+	 * the ACME Bean Validation provider.
+	 *
+	 * @param builderType the <code>ValidatorBuilder</code> sub interface uniquely defining the targeted provider.
+	 *
+	 * @return instance building a provider specific <code>ValidatorBuilder</code> sub interface implementation.
+	 *
+	 * @see #getValidatorBuilder()
+	 */
+	public static <T extends ValidatorBuilder<T>> SpecializedBuilderFactory<T> builderType(Class<T> builderType) {
+		return new SpecializedBuilderFactoryImpl<T>( builderType );
+	}
+
+	//private class, not exposed
+	private static class SpecializedBuilderFactoryImpl<T extends ValidatorBuilder<T>>
+			implements SpecializedBuilderFactory<T> {
+
+		private Class<T> builderType;
+		private ValidationProviderResolver resolver;
+
+		public SpecializedBuilderFactoryImpl(Class<T> builderType) {
+			this.builderType = builderType;
+		}
+
+		/**
+		 * Optionally define the provider resolver implementation used.
+		 * If not defined, use the default ValidationProviderResolver
+		 *
+		 * @param resolver ValidationProviderResolver implementation used
+		 *
+		 * @return self
+		 */
+		public SpecializedBuilderFactory<T> providerResolver(ValidationProviderResolver resolver) {
+			this.resolver = resolver;
+			return this;
+		}
+
+		/**
+		 * Determine the provider implementation suitable for builderType and delegate the creation
+		 * of this specific ValidatorBuilder subclass to the provider.
+		 *
+		 * @return a ValidatorBuilder sub interface implementation
+		 */
+		public T getValidatorBuilder() {
+			if ( builderType == null ) {
+				throw new ValidationException(
+						"builder is mandatory. Use getValidatorBuilder() to use the generic provider discovery mechanism"
+				);
+			}
+			if ( resolver == null ) {
+				resolver = new DefaultValidationProviderResolver();
+			}
+			for ( ValidationProvider provider : resolver.getValidationProviders() ) {
+				if ( provider.isSuitable( builderType ) ) {
+					GenericBuilderFactoryImpl state = new GenericBuilderFactoryImpl();
+					state.providerResolver( resolver );
+					return provider.createSpecializedValidatorBuilder( state, builderType );
+				}
+			}
+			throw new ValidationException( "Unable to find provider: " + builderType );
+		}
+	}
+
+	//private class, not exposed
+	private static class GenericBuilderFactoryImpl implements GenericBuilderFactory, BootstrapState {
+
+		private ValidationProviderResolver resolver;
+
+		public GenericBuilderFactory providerResolver(ValidationProviderResolver resolver) {
+			this.resolver = resolver;
+			return this;
+		}
+
+		public ValidationProviderResolver getValidationProviderResolver() {
+			return resolver;
+		}
+
+		public ValidatorBuilder<?> getValidatorBuilder() {
+			ValidationProviderResolver resolver = this.resolver == null ?
+					new DefaultValidationProviderResolver() :
+					this.resolver;
+
+			if ( resolver.getValidationProviders().size() == 0 ) {
+				//FIXME looks like an assertion error almost
+				throw new ValidationException( "Unable to find a default provider" );
+			}
+			return resolver.getValidationProviders().get( 0 ).createGenericValidatorBuilder( this );
+		}
+	}
+}


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/Validation.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/validation-api/src/main/java/javax/validation/ValidationException.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidationException.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidationException.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,41 @@
+// $Id: ValidationException.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Base exception of all "unexpected" problems.
+ *
+ * @author Emmanuel Bernard
+ */
+public class ValidationException extends RuntimeException {
+	public ValidationException(String message) {
+		super( message );
+	}
+
+	public ValidationException() {
+		super();
+	}
+
+	public ValidationException(String message, Throwable cause) {
+		super( message, cause );
+	}
+
+	public ValidationException(Throwable cause) {
+		super( cause );
+	}
+}


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/ValidationException.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/validation-api/src/main/java/javax/validation/ValidationProviderResolver.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidationProviderResolver.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidationProviderResolver.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,44 @@
+// $Id: ValidationProviderResolver.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.util.List;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * Determine the list of Bean Validation providers available in the runtime environment
+ * <p/>
+ * Bean Validation providers are identified by the presence of META-INF/services/javax.validation.spi.ValidationProvider
+ * files following the Service Provider pattern described
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">here</a>
+ * <p/>
+ * Each META-INF/services/javax.validation.spi.ValidationProvider file contains the list of
+ * ValidationProvider implementations each of them representing a provider.
+ * <p/>
+ * Implementations must be thread-safe.
+ *
+ * @author Emmanuel Bernard
+ */
+public interface ValidationProviderResolver {
+	/**
+	 * Returns a list of ValidationProviders available in the runtime environment.
+	 *
+	 * @return list of validation providers.
+	 */
+	List<ValidationProvider> getValidationProviders();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/Validator.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/Validator.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/Validator.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,95 @@
+// $Id: Validator.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * Validate a given object type.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ * @todo Should Serializable be part of the definition?
+ */
+public interface Validator<T> extends Serializable {
+	/**
+	 * validate all constraints on object (unless shortcut)
+	 *
+	 * @param object object to validate
+	 * @param groups group name(s) targeted for validation (default to <code>default</code>
+	 *
+	 * @return array of invalid constrains or an empty array if none.
+	 *
+	 * @throws IllegalArgumentException e if object is <code>null</code>.
+	 */
+	Set<InvalidConstraint<T>> validate(T object, String... groups);
+
+	/**
+	 * validate all constraints on propertyname property of object (unless shortcut)
+	 * <p/>
+	 *
+	 * @param object object to validate
+	 * @param propertyName property to validate
+	 * @param groups group name(s) targeted for validation (default to <code>default</code>
+	 *
+	 * @return array of invalid constrains or an empty array if none
+	 *
+	 * @throws IllegalArgumentException e if object is  <code>null</code>.
+	 * @todo Do we keep this method?
+	 */
+	Set<InvalidConstraint<T>> validateProperty(T object, String propertyName, String... groups);
+
+	/**
+	 * Validates all constraints on propertyname property if the property value is value (unless shortcut)
+	 * <p/>
+	 *
+	 * @param propertyName property to validate
+	 * @param value property value to validate
+	 * @param groups group name(s) targeted for validation (default to <code>default</code>
+	 *
+	 * @return array of invalid constrains or an empty array if none
+	 *
+	 * @todo Do we keep this method?
+	 * @todo express limitations of InvalidConstraint in this case.
+	 */
+	Set<InvalidConstraint<T>> validateValue(String propertyName, Object value, String... groups);
+
+	/**
+	 * return true if at least one constraint declaration is present for the given bean
+	 * or if one property is marked for validation cascade
+	 */
+	boolean hasConstraints();
+
+	/**
+	 * return the class level constraints
+	 */
+	ElementDescriptor getBeanConstraints();
+
+	/**
+	 * return the property level constraints for a given propertyName
+	 * or null if either the property does not exist or has no constraint
+	 */
+	ElementDescriptor getConstraintsForProperty(String propertyName);
+
+	/**
+	 * return the property names having at least a constraint defined
+	 */
+	String[] getValidatedProperties();
+
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,86 @@
+// $Id: ValidatorBuilder.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+import java.io.InputStream;
+
+/**
+ * Receives configuration information, selects the appropriate
+ * Bean Validation provider and build the appropriate
+ * ValidatorFactory.
+ * <p/>
+ * Usage:
+ * <pre>
+ * ValidatorBuilder<?> validatorBuilder = //provided by one of the Validation bootstrap methods
+ * ValidatorFactory = validatorBuilder
+ *         .messageResolver( new CustomMessageResolver() )
+ *         .build();
+ * </pre>
+ * <p/>
+ * The ValidationProviderResolver is specified at ValidatorBuilder time (see {@link javax.validation.spi.ValidationProvider}).
+ * If none is explicitely requested, the default ValidationProviderResolver is used.
+ * <p/>
+ * The provider is selected in the following way:
+ * - if a specific ValidatorBuilder subclass is requested programmatically using Validation.builderType(),
+ * find the first provider matching it
+ * - if a specific ValidatorBuilder subclass is defined in META-INF/validation.xml,
+ * find the first provider matching it
+ * - otherwise, use the first provider returned by the ValidationProviderResolver
+ * <p/>
+ * Implementations are not meant to be thread safe
+ *
+ * @author Emmanuel Bernard
+ */
+public interface ValidatorBuilder<T extends ValidatorBuilder> {
+	/**
+	 * Defines the message resolver used. Has priority over the configuration based message resolver.
+	 *
+	 * @param resolver message resolver implementation.
+	 *
+	 * @return <code>this</code> following the chaining method pattern.
+	 */
+	T messageResolver(MessageResolver resolver);
+
+	/**
+	 * Defines the constraint factory. Has priority over the configuration based constraint factory.
+	 *
+	 * @param constraintFactory constraint factory inmplementation.
+	 *
+	 * @return <code>this</code> following the chaining method pattern.
+	 */
+	T constraintFactory(ConstraintFactory constraintFactory);
+
+	/**
+	 * Configure the ValidatorFactory based on <code>stream</code>
+	 * If not specified, META-INF/validation.xml is used
+	 * <p/>
+	 * The stream should be closed by the client API after the ValidatorFactory has been returned
+	 *
+	 * @param stream configuration stream.
+	 *
+	 * @return <code>this</code> following the chaining method pattern.
+	 */
+	T configure(InputStream stream);
+
+	/**
+	 * Build a ValidatorFactory implementation.
+	 *
+	 * @return ValidatorFactory
+	 */
+	ValidatorFactory build();
+}


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorBuilder.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,34 @@
+// $Id: ValidatorFactory.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation;
+
+/**
+ * Factory returning initialized Validator instances.
+ * Implementations are thread-safe
+ * This object is typically cached and reused.
+ *
+ * @author Emmanuel Bernard
+ */
+public interface ValidatorFactory {
+	/**
+	 * return an initialized Validator instance for the specific class.
+	 * Validator instances can be pooled and shared by the implementation
+	 * In this scenario, the implementation must return thread-safe Validator implementations
+	 */
+	<T> Validator<T> getValidator(Class<T> clazz);
+}


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/ValidatorFactory.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/DefaultValidationProviderResolver.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/DefaultValidationProviderResolver.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/DefaultValidationProviderResolver.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,136 @@
+// $Id: DefaultValidationProviderResolver.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation.bootstrap;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.validation.ValidationException;
+import javax.validation.ValidationProviderResolver;
+import javax.validation.spi.ValidationProvider;
+
+/**
+ * Find <code>ValidationProvider</code> according to the default <code>ValidationProviderResolver</code> defined in the
+ * Bean Validation specification. This implementation uses the current classloader or the classloader which has loaded
+ * the current class if the current class loader is unavailable. The classloader is used to retrieve the Service Provider files.
+ * <p>
+ * This class implements the Service Provider pattern described <a href="http://java.sun.com/j2se/1.5.0/docs/guide/jar/jar.html#Service%20Provider">here</a>.
+ * Since we cannot rely on Java 6 we have to reimplement the <code>Service</code> functionality.
+ * </p>
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public class DefaultValidationProviderResolver implements ValidationProviderResolver {
+
+	//cache per classloader for an appropriate discovery
+	//keep them in a weak hashmap to avoid memory leaks and allow proper hot redeployment
+	//TODO use a WeakConcurrentHashMap
+	private static final Map<ClassLoader, List<ValidationProvider>> providersPerClassloader =
+			new WeakHashMap<ClassLoader, List<ValidationProvider>>();
+
+	private static final String SERVICES_FILE = "META-INF/services/" + ValidationProvider.class.getName();
+
+	public List<ValidationProvider> getValidationProviders() {
+		ClassLoader classloader = Thread.currentThread().getContextClassLoader();
+		if ( classloader == null ) {
+			classloader = DefaultValidationProviderResolver.class.getClassLoader();
+		}
+
+		List<ValidationProvider> providers;
+		synchronized ( providersPerClassloader ) {
+			providers = providersPerClassloader.get( classloader );
+		}
+
+		if ( providers == null ) {
+			providers = new ArrayList<ValidationProvider>();
+			String name = null;
+			try {
+				Enumeration<URL> providerDefinitions = classloader.getResources( SERVICES_FILE );
+				while ( providerDefinitions.hasMoreElements() ) {
+					URL url = providerDefinitions.nextElement();
+					InputStream stream = url.openStream();
+					try {
+						BufferedReader reader = new BufferedReader( new InputStreamReader( stream ), 100 );
+						name = reader.readLine();
+						while ( name != null ) {
+							name = name.trim();
+							if ( !name.startsWith( "#" ) ) {
+								final Class<?> providerClass = loadClass(
+										name,
+										DefaultValidationProviderResolver.class
+								);
+
+								providers.add(
+										( ValidationProvider ) providerClass.newInstance()
+								);
+							}
+							name = reader.readLine();
+						}
+					}
+					finally {
+						stream.close();
+					}
+				}
+			}
+			catch ( IOException e ) {
+				throw new ValidationException( "Unable to read " + SERVICES_FILE, e );
+			}
+			catch ( ClassNotFoundException e ) {
+				//TODO is it better to not fail the whole loading because of a black sheep?
+				throw new ValidationException( "Unable to load Bean Validation provider " + name, e );
+			}
+			catch ( IllegalAccessException e ) {
+				throw new ValidationException( "Unable to instanciate Bean Validation provider" + name, e );
+			}
+			catch ( InstantiationException e ) {
+				throw new ValidationException( "Unable to instanciate Bean Validation provider" + name, e );
+			}
+
+			synchronized ( providersPerClassloader ) {
+				providersPerClassloader.put( classloader, providers );
+			}
+		}
+
+		return providers;
+	}
+
+	public static Class<?> loadClass(String name, Class caller) throws ClassNotFoundException {
+		try {
+			//try context classloader, if fails try caller classloader
+			ClassLoader loader = Thread.currentThread().getContextClassLoader();
+			if ( loader != null ) {
+				return loader.loadClass( name );
+			}
+		}
+		catch ( ClassNotFoundException e ) {
+			//trying caller classloader
+			if ( caller == null ) {
+				throw e;
+			}
+		}
+		return Class.forName( name, true, caller.getClassLoader() );
+	}
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/GenericBuilderFactory.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/GenericBuilderFactory.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/GenericBuilderFactory.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,35 @@
+package javax.validation.bootstrap;
+
+import javax.validation.ValidationProviderResolver;
+import javax.validation.ValidatorBuilder;
+
+/**
+ * Defines the state used to bootstrap Bean Validation and create an appropriate
+ * ValidatorBuilder
+ *
+ * @author Emmanuel Bernard
+ */
+public interface GenericBuilderFactory {
+	/**
+	 * Defines the provider resolution strategy.
+	 * This resolver returns the list of providers evaluated
+	 * to build the ValidationBuilder
+	 * <p/>
+	 * If no resolver is defined, the default ValidationProviderResolver
+	 * implementation is used.
+	 *
+	 * @return <code>this</code> following the chaining method pattern
+	 */
+	GenericBuilderFactory providerResolver(ValidationProviderResolver resolver);
+
+	/**
+	 * Returns a generic ValidatorBuilder implementation.
+	 * At this stage the provider used to build the ValidationFactory is not defined.
+	 * <p/>
+	 * The ValidatorBuilder implementation is provided by the first provider returned
+	 * by the ValidationProviderResolver strategy.
+	 *
+	 * @return a ValidatorBuilder implementation compliant with the bootstrap state
+	 */
+	ValidatorBuilder<?> getValidatorBuilder();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/SpecializedBuilderFactory.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/SpecializedBuilderFactory.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/bootstrap/SpecializedBuilderFactory.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,36 @@
+package javax.validation.bootstrap;
+
+import javax.validation.ValidationProviderResolver;
+import javax.validation.ValidatorBuilder;
+
+/**
+ * Build implementations of builderType, the specific ValidationBuilder sub interface uniquely identifying
+ * a provider.
+ * <p/>
+ * The requested provider is the first provider suitable for T (as defined in
+ * {@link javax.validation.spi.ValidationProvider#isSuitable(Class)}). The list of providers evaluated is
+ * returned by {@link ValidationProviderResolver}. If no ValidationProviderResolver is defined, the
+ * default ValidationProviderResolver strategy is used.
+ *
+ * @author Emmanuel Bernard
+ */
+public interface SpecializedBuilderFactory<T extends ValidatorBuilder<T>> {
+
+	/**
+	 * Optionally define the provider resolver implementation used.
+	 * If not defined, use the default ValidationProviderResolver
+	 *
+	 * @param resolver ValidationProviderResolver implementation used
+	 *
+	 * @return self
+	 */
+	public SpecializedBuilderFactory<T> providerResolver(ValidationProviderResolver resolver);
+
+	/**
+	 * Determine the provider implementation suitable for builderType and delegate the creation
+	 * of this specific ValidatorBuilder subclass to the provider.
+	 *
+	 * @return a ValidatorBuilder sub interface implementation
+	 */
+	public T getValidatorBuilder();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/spi/BootstrapState.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/spi/BootstrapState.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/spi/BootstrapState.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,17 @@
+package javax.validation.spi;
+
+import javax.validation.ValidationProviderResolver;
+
+/**
+ * Defines the state used to bootstrap the ValidationBuilder
+ *
+ * @author Emmanuel Bernard
+ */
+public interface BootstrapState {
+	/**
+	 * returns the user defined ValidationProviderResolver strategy instance or <code>null</code> if undefined.
+	 *
+	 * @return ValidationProviderResolver instance or null
+	 */
+	ValidationProviderResolver getValidationProviderResolver();
+}

Added: validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidationProvider.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidationProvider.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidationProvider.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,81 @@
+// $Id: ValidationProvider.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation.spi;
+
+import javax.validation.ValidatorBuilder;
+import javax.validation.ValidatorFactory;
+
+/**
+ * Contract between the validation bootstrap mechanism and the provider engine.
+ * <p/>
+ * Implementations must have a public no-arg constructor. The construction of a provider should be
+ * as "lightweight" as possible.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface ValidationProvider {
+	/**
+	 * @param builderClass targeted builder class.
+	 *
+	 * @return <code>true</code> if <code>builderClass</code> is the Bean Validation Provider sub interface for ValidatorBuilder
+	 *         This sub interface uniquely identify a provider.
+	 */
+	boolean isSuitable(Class<? extends ValidatorBuilder<?>> builderClass);
+
+	/**
+	 * Returns a ValidatorBuilder instance implementing the <code>builderType</code> interface.
+	 * The ValidatorBuilder instance uses the current provider (<code>this</code>) to build
+	 * the ValidatorFactory instance.
+	 * <p/>
+	 * This method can only be called on providers returning true on <code>#issuitable(builderType)</code>
+	 *
+	 * @param builderClass the Builder class type
+	 * @param state bootstrap state
+	 *
+	 * @return specific validator builder implementation
+	 */
+	<T extends ValidatorBuilder<T>> T createSpecializedValidatorBuilder(BootstrapState state, Class<T> builderClass);
+
+	/**
+	 * Returns a ValidatorBuilder instance. This instance is not bound to
+	 * use the current provider. The choice of provider follows the algorithm described
+	 * in {@link javax.validation.ValidatorBuilder}
+	 * <p/>
+	 * The ValidationProviderResolver used is provided by <code>state</code>.
+	 * If null, the default ValidationProviderResolver is used.
+	 *
+	 * @param state bootstrap state
+	 *
+	 * @return validator builder implementation
+	 */
+	ValidatorBuilder<?> createGenericValidatorBuilder(BootstrapState state);
+
+	/**
+	 * Build a ValidatorFactory using the current provider implementation. The ValidationFactory
+	 * is assembled and follow the configuration passed using ValidatorBuilderImplementor.
+	 * <p>
+	 * The returned ValidatorFactory is properly initialized and ready for use.
+	 * </p>
+	 *
+	 * @param configuration the configuration descriptor
+	 *
+	 * @return the instanciated ValidatorFactory
+	 */
+	ValidatorFactory buildValidatorFactory(ValidatorBuilderImplementor configuration);
+}
\ No newline at end of file

Added: validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidatorBuilderImplementor.java
===================================================================
--- validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidatorBuilderImplementor.java	                        (rev 0)
+++ validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidatorBuilderImplementor.java	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,56 @@
+// $Id: ValidatorBuilderImplementor.java 114 2008-10-01 13:44:26Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, 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.
+*/
+package javax.validation.spi;
+
+import java.io.InputStream;
+import javax.validation.ConstraintFactory;
+import javax.validation.MessageResolver;
+
+/**
+ * Contract between a <code>ValidationBuilder</code> and a </code>ValidatorProvider</code> to create
+ * a <code>ValidatorFactory</code>.
+ * The configuration artifacts provided to the <code>ValidationBuilder</code> are passed along.
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+public interface ValidatorBuilderImplementor {
+	/**
+	 * Message resolver as defined by the client programmatically
+	 * or null if undefined.
+	 *
+	 * @return message provider instance or null if not defined
+	 */
+	MessageResolver getMessageResolver();
+
+	/**
+	 * Returns the configuration stream defined by the client programmatically
+	 * or null if undefined.
+	 *
+	 * @return the configuration input stream or null
+	 */
+	InputStream getConfigurationStream();
+
+	/**
+	 * Defines the constraint implementation factory as defined by the client programmatically
+	 * or null if undefined
+	 *
+	 * @return factory instance or null if not defined
+	 */
+	ConstraintFactory getConstraintFactory();
+}


Property changes on: validator/trunk/validation-api/src/main/java/javax/validation/spi/ValidatorBuilderImplementor.java
___________________________________________________________________
Name: svn:executable
   + *

Added: validator/trunk/validation-api/src/site/site.xml
===================================================================
--- validator/trunk/validation-api/src/site/site.xml	                        (rev 0)
+++ validator/trunk/validation-api/src/site/site.xml	2008-10-02 10:39:39 UTC (rev 15247)
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="Maven">
+  <bannerLeft>
+    <name>Maven</name>
+    <src>http://maven.apache.org/images/apache-maven-project.png</src>
+    <href>http://maven.apache.org/</href>
+  </bannerLeft>
+  <bannerRight>
+    <src>http://maven.apache.org/images/maven-small.gif</src>
+  </bannerRight>
+  <body>
+    <links>
+      <item name="Maven 2" href="http://maven.apache.org/"/>
+    </links>
+
+    <menu ref="reports"/>
+      
+  </body>
+</project>
\ No newline at end of file




More information about the hibernate-commits mailing list