Hibernate SVN: r15248 - annotations/branches/v3_2_1_GA_CP/src/test/org/hibernate/test/annotations/entity.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2008-10-02 16:00:39 -0400 (Thu, 02 Oct 2008)
New Revision: 15248
Modified:
annotations/branches/v3_2_1_GA_CP/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java
Log:
JBPAPP-1068 - Removing French characters that mask a mapping inconsistency on MSSQL
Modified: annotations/branches/v3_2_1_GA_CP/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java
===================================================================
--- annotations/branches/v3_2_1_GA_CP/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java 2008-10-02 10:39:39 UTC (rev 15247)
+++ annotations/branches/v3_2_1_GA_CP/src/test/org/hibernate/test/annotations/entity/BasicHibernateAnnotationsTest.java 2008-10-02 20:00:39 UTC (rev 15248)
@@ -122,7 +122,7 @@
public void testType() throws Exception {
Forest f = new Forest();
f.setName( "Broceliande" );
- String description = "C'est une enorme foret enchant�e o� vivais Merlin et toute la clique";
+ String description = "C'est une enorme foret enchantee ou vivais Merlin et toute la clique";
f.setLongDescription( description );
Session s;
Transaction tx;
16 years, 2 months
Hibernate SVN: r15247 - in validator/trunk: hibernate-validator and 43 other directories.
by hibernate-commits@lists.jboss.org
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
+ */
+@Documented
+(a)ConstraintValidator(LengthConstraint.class)
+@Target({ METHOD, FIELD, TYPE })
+@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
+ */
+@Documented
+(a)ConstraintValidator(NotEmptyConstraint.class)
+@Target({ METHOD, FIELD })
+@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
+ */
+@Documented
+(a)ConstraintValidator(NotNullConstraint.class)
+@Target({ METHOD, FIELD })
+@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
+ */
+@Documented
+(a)ConstraintValidator(PatternConstraint.class)
+@Target({ METHOD, FIELD })
+@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
+ */
+@Documented
+@Target({ METHOD, FIELD })
+@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 @Valid).
+ */
+ List<Field> getCascadedFields();
+
+ /**
+ * @return A list of all cascaded methods (methods annotated with @Valid).
+ */
+ List<Method> getCascadedMethods();
+
+ /**
+ * @return A list of all cascaded methods and fields (methods/fields annotated with @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
+ */
+@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
+ */
+@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
+ */
+@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
+ */
+@Documented
+(a)ConstraintValidator(NoGroupsConstraint.class)
+@Target({ METHOD, FIELD })
+@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
+ */
+@Documented
+(a)ConstraintValidator(NoMessageConstraint.class)
+@Target({ METHOD, FIELD })
+@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(a)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(a)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(a)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
+ */
+@Documented
+@Target({ ANNOTATION_TYPE })
+@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
+ */
+@Target({ TYPE })
+@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
+ */
+@Target({ TYPE })
+@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
+ */
+@Target({ METHOD, FIELD })
+@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<?> 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<?> 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
16 years, 2 months
Hibernate SVN: r15246 - validator/trunk.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2008-10-02 06:28:42 -0400 (Thu, 02 Oct 2008)
New Revision: 15246
Removed:
validator/trunk/build.properties.dist
validator/trunk/build.xml
validator/trunk/changelog.txt
Log:
Deleted: validator/trunk/build.properties.dist
===================================================================
--- validator/trunk/build.properties.dist 2008-10-02 08:05:49 UTC (rev 15245)
+++ validator/trunk/build.properties.dist 2008-10-02 10:28:42 UTC (rev 15246)
@@ -1,3 +0,0 @@
-common.dir=.
-src.dir=src
-test.dir=test
\ No newline at end of file
Deleted: validator/trunk/build.xml
===================================================================
--- validator/trunk/build.xml 2008-10-02 08:05:49 UTC (rev 15245)
+++ validator/trunk/build.xml 2008-10-02 10:28:42 UTC (rev 15246)
@@ -1,319 +0,0 @@
-<!--
-
- Hibernate Annotations ANT build script.
-
- You need JDK 5.0 installed to build Hibernate Annotations.
-
--->
-
-<!-- To add a dependency:
- defines the dependency.jar property that points to the expected jar file
- in init, add an available dependency.jar and populate dependency.jar.available
- create a target get.dependency which calls clean and jar
- add get.depdendecy to depends= for compile or compiletest
- alter lib.moduleclass.path or junit.moduleclasspath accordingly
--->
-
-<project name="Hibernate Validator" default="dist" basedir="."
- xmlns:ivy="antlib:fr.jayasoft.ivy.ant">
-
- <!-- Give user a chance to override without editing this file
- (and without typing -D each time it compiles it) -->
- <property file="build.properties"/>
- <property file="${user.home}/.ant.properties"/>
-
- <!-- Name of project and version, used to create filenames -->
- <property name="Name" value="Hibernate Validator"/>
- <property name="name" value="hibernate-validator"/>
- <property name="version" value="3.1.0.GA"/>
- <property name="javadoc.packagenames" value="org.hibernate.validator.*"/>
- <property name="copy.test" value="true"/>
- <property name="javac.source" value="1.5"/>
- <property name="javac.target" value="1.5"/>
- <property name="jdbc.dir" value="jdbc"/>
- <property name="common.dir" value="${basedir}"/>
-
- <property name="ivy.dep.dir" value="${basedir}/build/lib" />
-
- <!-- dependencies -->
- <!-- property name="jpa-api.jar" value="${basedir}/../jpa-api/build/ejb3-persistence.jar"/>
- <property name="annotations.jar"
- value="${basedir}/../annotations/target/hibernate-annotations/hibernate-annotations.jar"/>
- <property name="jpa.jar"
- value="${basedir}/../entitymanager/target/hibernate-entitymanager/hibernate-entitymanager.jar"/>
- <property name="archive-browsing.jar"
- value="${basedir}/../entitymanager/lib/jboss-archive-browsing.jar"/>
- <property name="commons-annotations.jar"
- value="${basedir}/../commons-annotations/target/hibernate-commons-annotations/hibernate-commons-annotations.jar"/ -->
-
- <import file="${common.dir}/common-build.xml"/>
-
-
- <path id="lib.moduleclass.path">
- <!-- pathelement location="${jpa-api.jar}"/>
- <pathelement location="${commons-annotations.jar}"/ -->
- <fileset dir="${ivy.dep.dir}/core">
- <include name="*.jar"/>
- </fileset>
- </path>
- <path id="junit.moduleclasspath">
- <pathelement location="${src.dir}"/>
- <pathelement location="${test.dir}"/>
- <!-- pathelement location="${annotations.jar}"/>
- <pathelement location="${jpa.jar}"/>
- <pathelement location="${archive-browsing.jar}"/ -->
- <fileset dir="${ivy.dep.dir}/test">
- <include name="*.jar"/>
- </fileset>
- <fileset dir="${jdbc.dir}">
- <include name="*.jar"/>
- <include name="*.zip"/>
- </fileset>
- <fileset dir="${lib.dir}/test">
- <include name="*.jar"/>
- <include name="*.zip"/>
- </fileset>
- </path>
-
- <!-- ivy load -->
- <property name="ivy.jar.dir" value="${basedir}/ivy" />
- <property name="ivy.conf.dir" value="${basedir}" />
- <path id="ivy.lib.path">
- <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
- </path>
- <taskdef resource="fr/jayasoft/ivy/ant/antlib.xml"
- uri="antlib:fr.jayasoft.ivy.ant" classpathref="ivy.lib.path"/>
-
- <target name="init">
- <antcall target="common-build.init"/>
- <tstamp>
- <format property="now" pattern="yyyyMMddhhmmss"/>
- </tstamp>
- <!-- check for dependency artefacts -->
- <!-- available file="${jpa-api.jar}" type="file" property="jpa-api.jar.available"/>
- <available file="${commons-annotations.jar}" type="file" property="commons-annotations.jar.available"/>
- <available file="${annotations.jar}" type="file" property="annotations.jar.available"/>
- <available file="${jpa.jar}" type="file" property="jpa.jar.available"/ -->
- <mkdir dir="${ivy.dep.dir}/core"/>
- <mkdir dir="${ivy.dep.dir}/test"/>
- <ivy:configure file="${ivy.jar.dir}/ivyconf.xml" />
- <mkdir dir="${lib.dir}/test"/>
- </target>
-
- <!-- target name="get.jpa-api" depends="init" unless="jpa-api.jar.available">
- <ant inheritall="false" dir="${basedir}/../jpa-api" target="clean"/>
- <ant inheritall="false" dir="${basedir}/../jpa-api" target="jar"/>
- </target>
-
- <target name="get.commons-annotations" depends="init" unless="commons-annotations.jar.available">
- <ant inheritall="false" dir="${basedir}/../commons-annotations" target="clean"/>
- <ant inheritall="false" dir="${basedir}/../commons-annotations" target="jar"/>
- </target>
-
- <target name="get.annotations" depends="init" unless="annotations.jar.available">
- <ant inheritall="false" dir="${basedir}/../annotations" target="clean"/>
- <ant inheritall="false" dir="${basedir}/../annotations" target="jar"/>
- </target>
-
- <target name="get.jpa" depends="init" unless="jpa.jar.available">
- <ant inheritall="false" dir="${basedir}/../entitymanager" target="clean"/>
- <ant inheritall="false" dir="${basedir}/../entitymanager" target="jar"/>
- </target -->
-
- <target name="get.deps.core" depends="init" description="retrieve the core dependencies">
- <ivy:resolve conf="default" />
- <ivy:retrieve pattern="${ivy.dep.dir}/core/[artifact].[ext]" conf="default" />
- </target>
-
- <target name="compile" depends="init,get.deps.core" description="Compile the Java source code">
- <available
- classname="org.eclipse.core.launcher.Main"
- property="build.compiler"
- value="org.eclipse.jdt.core.JDTCompilerAdapter"
- classpath="${java.class.path}"/>
- <javac
- srcdir="${src.dir}"
- destdir="${classes.dir}"
- classpathref="lib.class.path"
- debug="${javac.debug}"
- optimize="${javac.optimize}"
- nowarn="on"
- source="${javac.source}"
- target="${javac.target}">
- <src path="${src.dir}"/>
- </javac>
- <copy todir="${classes.dir}">
- <fileset dir="${src.dir}">
- <include name="**/resources/*.properties"/>
- <include name="**/*.xsd"/>
- </fileset>
- </copy>
- </target>
-
- <target name="get.deps.test" depends="init" description="retrieve the test dependencies">
- <ivy:resolve conf="test" />
- <ivy:retrieve pattern="${ivy.dep.dir}/test/[artifact].[ext]" conf="test" />
- </target>
-
- <target name="compiletest" depends="init,get.deps.test,compile" description="Compile the tests">
- <available
- classname="org.eclipse.core.launcher.Main"
- property="build.compiler"
- value="org.eclipse.jdt.core.JDTCompilerAdapter"
- classpath="${java.class.path}"/>
- <javac
- destdir="${testclasses.dir}"
- classpathref="junit.classpath"
- debug="${javac.debug}"
- optimize="${javac.optimize}"
- nowarn="on"
- source="1.5"
- target="1.5">
- <src refid="testsrc.path"/>
- </javac>
- </target>
-
-
- <!-- target name="junit" depends="compiletest">
- <mkdir dir="test_output"/>
- <junit fork="yes" printsummary="yes" haltonfailure="yes"
- forkmode="perBatch">
- <classpath>
- <fileset dir="${jdbc.dir}">
- <include name="**/*.jar"/>
- <include name="**/*.zip"/>
- </fileset>
- <path refid="lib.class.path"/>
- <pathelement path="${classes.dir}"/>
- <pathelement path="${src.dir}"/>
- <pathelement path="${test.dir}"/>
- </classpath>
- <formatter type="plain"/>
- <formatter type="xml"/>
- <batchtest fork="yes" todir="test_output" haltonfailure="no">
- <fileset dir="${classes.dir}">
- <include name="**/*Test.class"/>
- </fileset>
- </batchtest>
- </junit>
- </target -->
-
- <!-- Run a single unit test. -->
- <target name="junitsingle" depends="compiletest"
- description="Run a single test suite (requires testname and jdbc.driver properties)">
- <mkdir dir="test_output"/>
- <junit printsummary="yes" fork="yes" haltonfailure="yes">
- <classpath>
- <fileset dir="${jdbc.dir}">
- <include name="**/*.jar"/>
- <include name="**/*.zip"/>
- </fileset>
- <path refid="lib.class.path"/>
- <pathelement path="${classes.dir}"/>
- <pathelement path="${src.dir}"/>
- <!-- pick up properties from here -->
- <pathelement path="${test.dir}"/>
- <!-- pick up mappings from here -->
- </classpath>
- <formatter type="plain"/>
- <formatter type="xml"/>
- <test fork="yes" todir="test_output" haltonfailure="no" name="${testname}"/>
- </junit>
- </target>
-
- <!-- target name="report">
- <mkdir dir="test_output"/>
- <junitreport todir="test_output">
- <fileset dir="test_output">
- <include name="TEST-*.xml"/>
- </fileset>
- <report format="frames" todir="test_output/report"/>
- </junitreport>
- </target -->
-
- <target name="jar" depends="compile" description="Build the distribution .jar file">
- <mkdir dir="${classes.dir}/META-INF"/>
- <manifest file="${classes.dir}/META-INF/MANIFEST.MF">
- <attribute name="Implementation-Title" value="${Name}"/>
- <attribute name="Implementation-Version" value="${version}"/>
- <attribute name="Implementation-Vendor" value="hibernate.org"/>
- <attribute name="Implementation-Vendor-Id" value="hibernate.org"/>
- <attribute name="Implementation-URL" value="http://validator.hibernate.org"/>
- </manifest>
- <antcall target="common-build.jar"/>
- <ivy:resolve conf="default"/>
- <ivy:publish artifactspattern="${dist.dir}/[artifact].[ext]"
- resolver="local"
- pubrevision="latest"
- pubdate="${now}"
- status="integration"
- />
- </target>
-
- <!-- Some of this can probably be moved to common-build... -->
- <target name="dist" depends="get.deps.core,get.deps.test,jar,javadoc,copysource,copytest,copylib,extras"
- description="Build everything">
-
- <ant inheritall="false" dir="${basedir}/doc/reference"/>
- <copy todir="${dist.dir}/doc/reference" failonerror="false">
- <fileset dir="${basedir}/doc/reference/build">
- <include name="**/*.*"/>
- </fileset>
- </copy>
-
- <copy todir="${dist.dir}" failonerror="false">
- <fileset dir="${common.dir}">
- <include name="common-build.xml"/>
- </fileset>
- </copy>
- <copy todir="${dist.dir}/ivy" failonerror="false">
- <fileset dir="${ivy.jar.dir}">
- <include name="**/*.*"/>
- </fileset>
- </copy>
-
- <!-- copy dependencies -->
- <copy todir="${dist.lib.dir}" failonerror="false">
- <!-- fileset file="${jpa-api.jar}"/>
- <fileset file="${commons-annotations.jar}"/ -->
- <fileset dir="${ivy.dep.dir}/core">
- <include name="*.jar"/>
- </fileset>
- </copy>
-
- <mkdir dir="${dist.lib.dir}/test"/>
- <copy todir="${dist.lib.dir}/test" failonerror="false">
- <fileset dir="${ivy.dep.dir}/test">
- <include name="*.jar"/>
- </fileset>
- </copy>
-
- <mkdir dir="${dist.lib.dir}/build"/>
- <copy todir="${dist.lib.dir}/build" failonerror="false">
- <fileset file="${lib.dir}/build/*.jar"/>
- </copy>
-
- <!-- ivy uses the module name without hibernate- (to mimic the directory names). Revert the situation -->
- <move file="${dist.lib.dir}/commons-annotations.jar" tofile="${dist.lib.dir}/hibernate-commons-annotations.jar"
- failonerror="false"/>
- <move file="${dist.lib.dir}/test/annotations.jar" tofile="${dist.lib.dir}/test/hibernate-annotations.jar"
- failonerror="false"/>
- <move file="${dist.lib.dir}/test/entitymanager.jar" tofile="${dist.lib.dir}/test/hibernate-entitymanager.jar"
- failonerror="false"/>
-
- <copy file="${basedir}/build.properties.dist" tofile="${dist.dir}/build.properties" failonerror="false">
- </copy>
- <antcall target="common-build.dist"/>
- </target>
-
- <target name="zip-dist" description="zip the dist">
- <zip zipfile="${dist.dir}-${version}.zip">
- <zipfileset prefix="${name}-${version}" dir="${dist.dir}"/>
- </zip>
- <tar compression="gzip" tarfile="${dist.dir}-${version}.tar.gz">
- <tarfileset prefix="${name}-${version}" dir="${dist.dir}"/>
- </tar>
- </target>
-
-
-</project>
Deleted: validator/trunk/changelog.txt
===================================================================
--- validator/trunk/changelog.txt 2008-10-02 08:05:49 UTC (rev 15245)
+++ validator/trunk/changelog.txt 2008-10-02 10:28:42 UTC (rev 15246)
@@ -1,57 +0,0 @@
-Hibernate Validator Changelog
-=============================
-
-3.1.0.GA (10-09-2008)
-----------------------
-
-
-3.1.0.CR2 (20-08-2008)
-----------------------
-
-** Bug
- * [HV-15] - @Past validation annotation generates incorrect DDL for Oracle 8.x
- * [HV-53] - AssertTrue and AssertFalse not compatible with null values
- * [HV-65] - @Past cannot use current_date as per the ANSI SQL spec
- * [HV-66] - 3.1.0.CR1 incompatible with Hibernate 3.3.0
-
-
-3.1.0.CR1 (27-05-2008)
-----------------------
-
-** Bug
- * [HV-14] - Minor typo in regular expression in class EmailValidator
- * [HV-48] - There is no DefaultValidatorMessage_en leading to no message loaded when locale is explicit and the system default is not en
-
-
-** Improvement
- * [HV-57] - Move to slf4j
-
-** New Feature
- * [HV-54] - Add pom
- * [HV-55] - Make build independent of Hibernate Core structure
- * [HV-56] - Move to Hibernate Core 3.3
-
-** Patch
- * [HV-36] - DefaultValidatorMessages_ja.properties
-
-
-3.0.0.GA (19-03-2007)
----------------------
-
-Initial release as a standalone product (see Hibernate Annotations changelog for previous informations)
-
-** Bug
- * [HV-2] - Deprecate String support for both @Past and @Future validating Strings
- * [HV-3] - @Email fail on empty strings
- * [HV-7] - Two level @Valid annotation doesn't work
-
-
-** Improvement
- * [HV-5] - Multiple validators of the same type per element (John Gilbert)
-
-** New Feature
- * [HV-1] - Make ClassValidator independent of Hibernate Annotations
- * [HV-6] - @EAN
- * [HV-8] - Make Validator support pure JavaPersistence players
- * [HV-9] - @Digits(integerDigits, fractionalDigits)
- * [HV-10] - @CreditCardNumber for Hibernate Validator
16 years, 2 months
Hibernate SVN: r15245 - core/trunk/cache-jbosscache2.
by hibernate-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2008-10-02 04:05:49 -0400 (Thu, 02 Oct 2008)
New Revision: 15245
Modified:
core/trunk/cache-jbosscache2/pom.xml
Log:
javax.persistence is a dependency for these tests
Modified: core/trunk/cache-jbosscache2/pom.xml
===================================================================
--- core/trunk/cache-jbosscache2/pom.xml 2008-10-02 07:53:37 UTC (rev 15244)
+++ core/trunk/cache-jbosscache2/pom.xml 2008-10-02 08:05:49 UTC (rev 15245)
@@ -48,6 +48,13 @@
<version>3.4.GA</version>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
16 years, 2 months
Hibernate SVN: r15244 - core/trunk/cache-jbosscache2.
by hibernate-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2008-10-02 03:53:37 -0400 (Thu, 02 Oct 2008)
New Revision: 15244
Modified:
core/trunk/cache-jbosscache2/pom.xml
Log:
Updated to 2.2.0.GA
Modified: core/trunk/cache-jbosscache2/pom.xml
===================================================================
--- core/trunk/cache-jbosscache2/pom.xml 2008-10-01 21:25:02 UTC (rev 15243)
+++ core/trunk/cache-jbosscache2/pom.xml 2008-10-02 07:53:37 UTC (rev 15244)
@@ -25,7 +25,7 @@
<dependency>
<groupId>org.jboss.cache</groupId>
<artifactId>jbosscache-core</artifactId>
- <version>2.1.1.GA</version>
+ <version>2.2.0.GA</version>
</dependency>
<!-- test dependencies -->
16 years, 2 months
Hibernate SVN: r15243 - core/trunk/core/src/main/java/org/hibernate/hql/ast/tree.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 17:25:02 -0400 (Wed, 01 Oct 2008)
New Revision: 15243
Modified:
core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java
Log:
HHH-3510 : HQL SQLFunction replacement not occuring when HQL text has no parenthesis (rollback)
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java 2008-10-01 21:09:20 UTC (rev 15242)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java 2008-10-01 21:25:02 UTC (rev 15243)
@@ -27,7 +27,6 @@
import antlr.SemanticException;
import antlr.collections.AST;
import org.hibernate.QueryException;
-import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.hql.antlr.SqlTokenTypes;
import org.hibernate.hql.ast.util.ColumnHelper;
import org.hibernate.persister.collection.QueryableCollection;
@@ -38,7 +37,6 @@
import org.hibernate.util.StringHelper;
import java.util.List;
-import java.util.Collections;
/**
* Represents an identifier all by itself, which may be a function name,
@@ -129,14 +127,6 @@
// resolve this...
return;
}
- else if ( result == UNKNOWN ) {
- final SQLFunction sqlFunction = getSessionFactoryHelper().findSQLFunction( getText() );
- if ( sqlFunction != null ) {
- setText( sqlFunction.render( Collections.EMPTY_LIST, getSessionFactoryHelper().getFactory() ) );
- setDataType( sqlFunction.getReturnType( null, getSessionFactoryHelper().getFactory() ) );
- setResolved();
- }
- }
}
// if we are still not resolved, we might represent a constant.
@@ -303,18 +293,18 @@
}
public void setScalarColumnText(int i) throws SemanticException {
- if ( nakedPropertyRef ) {
+ if (nakedPropertyRef) {
// do *not* over-write the column text, as that has already been
// "rendered" during resolve
- ColumnHelper.generateSingleScalarColumn( this, i );
+ ColumnHelper.generateSingleScalarColumn(this, i);
}
else {
FromElement fe = getFromElement();
- if ( fe != null ) {
- setText( fe.renderScalarIdentifierSelect( i ) );
+ if (fe != null) {
+ setText(fe.renderScalarIdentifierSelect(i));
}
else {
- ColumnHelper.generateSingleScalarColumn( this, i );
+ ColumnHelper.generateSingleScalarColumn(this, i);
}
}
}
@@ -322,19 +312,19 @@
public String getDisplayText() {
StringBuffer buf = new StringBuffer();
- if ( getType() == SqlTokenTypes.ALIAS_REF ) {
- buf.append( "{alias=" ).append( getOriginalText() );
- if ( getFromElement() == null ) {
- buf.append( ", no from element" );
+ if (getType() == SqlTokenTypes.ALIAS_REF) {
+ buf.append("{alias=").append(getOriginalText());
+ if (getFromElement() == null) {
+ buf.append(", no from element");
}
else {
- buf.append( ", className=" ).append( getFromElement().getClassName() );
- buf.append( ", tableAlias=" ).append( getFromElement().getTableAlias() );
+ buf.append(", className=").append(getFromElement().getClassName());
+ buf.append(", tableAlias=").append(getFromElement().getTableAlias());
}
- buf.append( "}" );
+ buf.append("}");
}
else {
- buf.append( "{originalText=" ).append( getOriginalText() ).append( "}" );
+ buf.append("{originalText=" + getOriginalText()).append("}");
}
return buf.toString();
}
16 years, 3 months
Hibernate SVN: r15242 - core/trunk/core/src/main/java/org/hibernate/hql/ast/tree.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 17:09:20 -0400 (Wed, 01 Oct 2008)
New Revision: 15242
Modified:
core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java
Log:
HHH-3510 : HQL SQLFunction replacement not occuring when HQL text has no parenthesis
Modified: core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java 2008-10-01 19:42:55 UTC (rev 15241)
+++ core/trunk/core/src/main/java/org/hibernate/hql/ast/tree/IdentNode.java 2008-10-01 21:09:20 UTC (rev 15242)
@@ -38,6 +38,7 @@
import org.hibernate.util.StringHelper;
import java.util.List;
+import java.util.Collections;
/**
* Represents an identifier all by itself, which may be a function name,
@@ -128,6 +129,14 @@
// resolve this...
return;
}
+ else if ( result == UNKNOWN ) {
+ final SQLFunction sqlFunction = getSessionFactoryHelper().findSQLFunction( getText() );
+ if ( sqlFunction != null ) {
+ setText( sqlFunction.render( Collections.EMPTY_LIST, getSessionFactoryHelper().getFactory() ) );
+ setDataType( sqlFunction.getReturnType( null, getSessionFactoryHelper().getFactory() ) );
+ setResolved();
+ }
+ }
}
// if we are still not resolved, we might represent a constant.
@@ -283,26 +292,29 @@
public Type getDataType() {
Type type = super.getDataType();
- if (type != null) return type;
+ if ( type != null ) {
+ return type;
+ }
FromElement fe = getFromElement();
- if (fe != null) return fe.getDataType();
- SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction(getText());
- return sf == null ? null : sf.getReturnType(null, null);
+ if ( fe != null ) {
+ return fe.getDataType();
+ }
+ return null;
}
public void setScalarColumnText(int i) throws SemanticException {
- if (nakedPropertyRef) {
+ if ( nakedPropertyRef ) {
// do *not* over-write the column text, as that has already been
// "rendered" during resolve
- ColumnHelper.generateSingleScalarColumn(this, i);
+ ColumnHelper.generateSingleScalarColumn( this, i );
}
else {
FromElement fe = getFromElement();
- if (fe != null) {
- setText(fe.renderScalarIdentifierSelect(i));
+ if ( fe != null ) {
+ setText( fe.renderScalarIdentifierSelect( i ) );
}
else {
- ColumnHelper.generateSingleScalarColumn(this, i);
+ ColumnHelper.generateSingleScalarColumn( this, i );
}
}
}
@@ -310,19 +322,19 @@
public String getDisplayText() {
StringBuffer buf = new StringBuffer();
- if (getType() == SqlTokenTypes.ALIAS_REF) {
- buf.append("{alias=").append(getOriginalText());
- if (getFromElement() == null) {
- buf.append(", no from element");
+ if ( getType() == SqlTokenTypes.ALIAS_REF ) {
+ buf.append( "{alias=" ).append( getOriginalText() );
+ if ( getFromElement() == null ) {
+ buf.append( ", no from element" );
}
else {
- buf.append(", className=").append(getFromElement().getClassName());
- buf.append(", tableAlias=").append(getFromElement().getTableAlias());
+ buf.append( ", className=" ).append( getFromElement().getClassName() );
+ buf.append( ", tableAlias=" ).append( getFromElement().getTableAlias() );
}
- buf.append("}");
+ buf.append( "}" );
}
else {
- buf.append("{originalText=" + getOriginalText()).append("}");
+ buf.append( "{originalText=" ).append( getOriginalText() ).append( "}" );
}
return buf.toString();
}
16 years, 3 months
Hibernate SVN: r15241 - in core/branches/Branch_3_3: core/src/main/java/org/hibernate/engine and 8 other directories.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 15:42:55 -0400 (Wed, 01 Oct 2008)
New Revision: 15241
Added:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/ParameterContainer.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Basic.hbm.xml
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Customer.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Employee.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Joined.hbm.xml
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Person.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/User.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/filter-defs.hbm.xml
Modified:
core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/QueryParameters.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/HqlSqlWalker.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/SqlGenerator.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/SqlFragment.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/JoinProcessor.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/SyntheticAndFactory.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/AbstractExplicitParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/DynamicFilterParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/ExplicitParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/NamedParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/PositionalParameterSpecification.java
core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/VersionTypeSeedParameterSpecification.java
core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java
Log:
HHH-530 : filters + subqueries;
HHH-3506 : filters + HQL update/delete
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/criterion/SubqueryExpression.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -24,14 +24,13 @@
*/
package org.hibernate.criterion;
-import java.util.HashMap;
-
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.TypedValue;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
@@ -53,49 +52,67 @@
protected Type[] getTypes() {
return types;
}
-
+
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
this.criteriaImpl = dc.getCriteriaImpl();
this.quantifier = quantifier;
this.op = op;
}
-
+
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
- public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
- throws HibernateException {
-
+ public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
- final OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
+ final OuterJoinLoadable persister =
+ ( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
createAndSetInnerQuery( criteriaQuery, factory );
-
+ criteriaImpl.setSession( deriveRootSession( criteria ) );
+
CriteriaJoinWalker walker = new CriteriaJoinWalker(
persister,
innerQuery,
factory,
criteriaImpl,
criteriaImpl.getEntityOrClassName(),
- new HashMap(),
- innerQuery.getRootSQLALias());
+ criteriaImpl.getSession().getEnabledFilters(),
+ innerQuery.getRootSQLALias()
+ );
String sql = walker.getSQLString();
- final StringBuffer buf = new StringBuffer()
- .append( toLeftSqlString(criteria, criteriaQuery) );
- if (op!=null) buf.append(' ').append(op).append(' ');
- if (quantifier!=null) buf.append(quantifier).append(' ');
- return buf.append('(').append(sql).append(')')
- .toString();
+ final StringBuffer buf = new StringBuffer( toLeftSqlString(criteria, criteriaQuery) );
+ if ( op != null ) {
+ buf.append( ' ' ).append( op ).append( ' ' );
+ }
+ if ( quantifier != null ) {
+ buf.append( quantifier ).append( ' ' );
+ }
+ return buf.append( '(' ).append( sql ).append( ')' )
+ .toString();
}
- public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
+ private SessionImplementor deriveRootSession(Criteria criteria) {
+ if ( criteria instanceof CriteriaImpl ) {
+ return ( ( CriteriaImpl ) criteria ).getSession();
+ }
+ else if ( criteria instanceof CriteriaImpl.Subcriteria ) {
+ return deriveRootSession( ( ( CriteriaImpl.Subcriteria ) criteria ).getParent() );
+ }
+ else {
+ // could happen for custom Criteria impls. Not likely, but...
+ // for long term solution, see HHH-3514
+ return null;
+ }
+ }
+
+ public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
//the following two lines were added to ensure that this.params is not null, which
//can happen with two-deep nested subqueries
SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery(criteriaQuery, factory);
-
+
Type[] ppTypes = params.getPositionalParameterTypes();
Object[] ppValues = params.getPositionalParameterValues();
TypedValue[] tv = new TypedValue[ppTypes.length];
@@ -106,12 +123,12 @@
}
/**
- * Creates the inner query used to extract some useful information about
- * types, since it is needed in both methods.
- * @param criteriaQuery
- * @param factory
+ * Creates the inner query used to extract some useful information about types, since it is needed in both methods.
+ *
+ * @param criteriaQuery The criteria query
+ * @param factory The session factory.
*/
- private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, final SessionFactoryImplementor factory) {
+ private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, SessionFactoryImplementor factory) {
if ( innerQuery == null ) {
//with two-deep subqueries, the same alias would get generated for
//both using the old method (criteriaQuery.generateSQLAlias()), so
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/QueryParameters.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/QueryParameters.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/engine/QueryParameters.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -26,7 +26,6 @@
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -39,6 +38,7 @@
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
+import org.hibernate.impl.FilterImpl;
import org.hibernate.dialect.Dialect;
import org.hibernate.hql.classic.ParserHelper;
import org.hibernate.pretty.Printer;
@@ -50,7 +50,7 @@
* @author Gavin King
*/
public final class QueryParameters {
- private static final Logger log = LoggerFactory.getLogger(QueryParameters.class);
+ private static final Logger log = LoggerFactory.getLogger( QueryParameters.class );
private Type[] positionalParameterTypes;
private Object[] positionalParameterValues;
@@ -69,29 +69,28 @@
private boolean callable = false;
private boolean autodiscovertypes = false;
private boolean isNaturalKeyLookup;
-
+
private final ResultTransformer resultTransformer; // why is all others non final ?
-
+
private String processedSQL;
private Type[] processedPositionalParameterTypes;
private Object[] processedPositionalParameterValues;
-
+
public QueryParameters() {
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
}
public QueryParameters(Type type, Object value) {
- this( new Type[] {type}, new Object[] {value} );
+ this( new Type[] { type }, new Object[] { value } );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalObjectId
- ) {
- this(positionalParameterTypes, postionalParameterValues);
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalObjectId) {
+ this( positionalParameterTypes, postionalParameterValues );
this.optionalObject = optionalObject;
this.optionalId = optionalObjectId;
this.optionalEntityName = optionalEntityName;
@@ -99,42 +98,24 @@
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- null,
- false,
- null,
- null,
- false,
- null
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues) {
+ this( positionalParameterTypes, postionalParameterValues, null, null, false, null, null, false, null );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Serializable[] collectionKeys
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- collectionKeys
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Serializable[] collectionKeys) {
+ this( positionalParameterTypes, postionalParameterValues, null, collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] postionalParameterValues,
final Map namedParameters,
- final Serializable[] collectionKeys
- ) {
- this(
+ final Serializable[] collectionKeys) {
+ this(
positionalParameterTypes,
postionalParameterValues,
namedParameters,
@@ -142,37 +123,36 @@
null,
false,
false,
- null,
null,
+ null,
collectionKeys,
null
- );
- }
+ );
+ }
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final boolean isLookupByNaturalKey,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final boolean isLookupByNaturalKey,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- null,
- lockModes,
- rowSelection,
- false,
- cacheable,
- cacheRegion,
- comment,
- null,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ null,
+ lockModes,
+ rowSelection,
+ false,
+ cacheable,
+ cacheRegion,
+ comment,
+ null,
+ transformer
);
isNaturalKeyLookup = isLookupByNaturalKey;
}
@@ -189,8 +169,7 @@
//final boolean forceCacheRefresh,
final String comment,
final Serializable[] collectionKeys,
- ResultTransformer transformer
- ) {
+ ResultTransformer transformer) {
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
this.namedParameters = namedParameters;
@@ -204,36 +183,35 @@
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
-
+
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map namedParameters,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean readOnly,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final Serializable[] collectionKeys,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalId,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map namedParameters,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean readOnly,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final Serializable[] collectionKeys,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalId,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- namedParameters,
- lockModes,
- rowSelection,
- readOnly,
- cacheable,
- cacheRegion,
- comment,
- collectionKeys,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ namedParameters,
+ lockModes,
+ rowSelection,
+ readOnly,
+ cacheable,
+ cacheRegion,
+ comment,
+ collectionKeys,
+ transformer
);
this.optionalEntityName = optionalEntityName;
this.optionalId = optionalId;
@@ -241,7 +219,7 @@
}
public boolean hasRowSelection() {
- return rowSelection!=null;
+ return rowSelection != null;
}
public Map getNamedParameters() {
@@ -259,7 +237,7 @@
public RowSelection getRowSelection() {
return rowSelection;
}
-
+
public ResultTransformer getResultTransformer() {
return resultTransformer;
}
@@ -289,15 +267,15 @@
}
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
- Printer print = new Printer(factory);
- if (positionalParameterValues.length!=0) {
+ Printer print = new Printer( factory );
+ if ( positionalParameterValues.length != 0 ) {
log.trace(
- "parameters: " +
- print.toString(positionalParameterTypes, positionalParameterValues)
- );
+ "parameters: " +
+ print.toString( positionalParameterTypes, positionalParameterValues )
+ );
}
- if (namedParameters!=null) {
- log.trace( "named parameters: " + print.toString(namedParameters) );
+ if ( namedParameters != null ) {
+ log.trace( "named parameters: " + print.toString( namedParameters ) );
}
}
@@ -318,13 +296,13 @@
}
public void validateParameters() throws QueryException {
- int types = positionalParameterTypes==null ? 0 : positionalParameterTypes.length;
- int values = positionalParameterValues==null ? 0 : positionalParameterValues.length;
- if (types!=values) {
+ int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
+ int values = positionalParameterValues == null ? 0 : positionalParameterValues.length;
+ if ( types != values ) {
throw new QueryException(
- "Number of positional parameter types:" + types +
- " does not match number of positional parameters: " + values
- );
+ "Number of positional parameter types:" + types +
+ " does not match number of positional parameters: " + values
+ );
}
}
@@ -385,44 +363,49 @@
}
public void setCallable(boolean callable) {
- this.callable = callable;
+ this.callable = callable;
}
public boolean isCallable() {
return callable;
}
-
+
public boolean hasAutoDiscoverScalarTypes() {
return autodiscovertypes;
}
public void processFilters(String sql, SessionImplementor session) {
-
- if ( session.getEnabledFilters().size()==0 || sql.indexOf(ParserHelper.HQL_VARIABLE_PREFIX)<0 ) {
+ processFilters( sql, session.getEnabledFilters(), session.getFactory() );
+ }
+
+ public void processFilters(String sql, Map filters, SessionFactoryImplementor factory) {
+ if ( filters.size() == 0 || sql.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0 ) {
// HELLA IMPORTANT OPTIMIZATION!!!
processedPositionalParameterValues = getPositionalParameterValues();
processedPositionalParameterTypes = getPositionalParameterTypes();
processedSQL = sql;
}
else {
-
- Dialect dialect = session.getFactory().getDialect();
+ final Dialect dialect = factory.getDialect();
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
.append( dialect.openQuote() )
.append( dialect.closeQuote() )
.toString();
StringTokenizer tokens = new StringTokenizer( sql, symbols, true );
StringBuffer result = new StringBuffer();
-
+
List parameters = new ArrayList();
List parameterTypes = new ArrayList();
-
+
+ int positionalIndex = 0;
while ( tokens.hasMoreTokens() ) {
final String token = tokens.nextToken();
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
- String filterParameterName = token.substring( 1 );
- Object value = session.getFilterParameterValue( filterParameterName );
- Type type = session.getFilterParameterType( filterParameterName );
+ final String filterParameterName = token.substring( 1 );
+ final String[] parts = parseFilterParameterName( filterParameterName );
+ final FilterImpl filter = ( FilterImpl ) filters.get( parts[0] );
+ final Object value = filter.getParameter( parts[1] );
+ final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
if ( value != null && Collection.class.isAssignableFrom( value.getClass() ) ) {
Iterator itr = ( ( Collection ) value ).iterator();
while ( itr.hasNext() ) {
@@ -442,15 +425,17 @@
}
}
else {
+ if ( "?".equals( token ) && positionalIndex < getPositionalParameterValues().length ) {
+ parameters.add( getPositionalParameterValues()[positionalIndex] );
+ parameterTypes.add( getPositionalParameterTypes()[positionalIndex] );
+ positionalIndex++;
+ }
result.append( token );
}
}
- parameters.addAll( Arrays.asList( getPositionalParameterValues() ) );
- parameterTypes.addAll( Arrays.asList( getPositionalParameterTypes() ) );
processedPositionalParameterValues = parameters.toArray();
- processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[0] );
+ processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[parameterTypes.size()] );
processedSQL = result.toString();
-
}
}
@@ -481,16 +466,16 @@
public QueryParameters createCopyUsing(RowSelection selection) {
QueryParameters copy = new QueryParameters(
this.positionalParameterTypes,
- this.positionalParameterValues,
- this.namedParameters,
- this.lockModes,
- selection,
- this.readOnly,
- this.cacheable,
- this.cacheRegion,
- this.comment,
- this.collectionKeys,
- this.optionalObject,
+ this.positionalParameterValues,
+ this.namedParameters,
+ this.lockModes,
+ selection,
+ this.readOnly,
+ this.cacheable,
+ this.cacheRegion,
+ this.comment,
+ this.collectionKeys,
+ this.optionalObject,
this.optionalEntityName,
this.optionalId,
this.resultTransformer
@@ -501,5 +486,14 @@
return copy;
}
-
+ public static String[] parseFilterParameterName(String filterParameterName) {
+ int dot = filterParameterName.indexOf( '.' );
+ if ( dot <= 0 ) {
+ throw new IllegalArgumentException( "Invalid filter-parameter name format" );
+ }
+ String filterName = filterParameterName.substring( 0, dot );
+ String parameterName = filterParameterName.substring( dot + 1 );
+ return new String[] { filterName, parameterName };
+ }
+
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/HqlSqlWalker.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -231,6 +231,10 @@
return collectionFilterRole != null;
}
+ public String getCollectionFilterRole() {
+ return collectionFilterRole;
+ }
+
public SessionFactoryHelper getSessionFactoryHelper() {
return sessionFactoryHelper;
}
@@ -553,8 +557,8 @@
// After that, process the JOINs.
// Invoke a delegate to do the work, as this is farily complex.
- JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl );
- joinProcessor.processJoins( qn, isSubQuery() );
+ JoinProcessor joinProcessor = new JoinProcessor( this );
+ joinProcessor.processJoins( qn );
// Attach any mapping-defined "ORDER BY" fragments
Iterator itr = qn.getFromClause().getProjectionList().iterator();
@@ -592,13 +596,21 @@
// Make #@%$^#^&# sure no alias is applied to the table name
fromElement.setText( persister.getTableName() );
- // append any filter fragments; the EMPTY_MAP is used under the assumption that
- // currently enabled filters should not affect this process
- if ( persister.getDiscriminatorType() != null ) {
- new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
+// // append any filter fragments; the EMPTY_MAP is used under the assumption that
+// // currently enabled filters should not affect this process
+// if ( persister.getDiscriminatorType() != null ) {
+// new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
+// statement,
+// persister,
+// java.util.Collections.EMPTY_MAP,
+// fromElement.getTableAlias()
+// );
+// }
+ if ( persister.getDiscriminatorType() != null || ! queryTranslatorImpl.getEnabledFilters().isEmpty() ) {
+ new SyntheticAndFactory( this ).addDiscriminatorWhereFragment(
statement,
persister,
- java.util.Collections.EMPTY_MAP,
+ queryTranslatorImpl.getEnabledFilters(),
fromElement.getTableAlias()
);
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -97,7 +97,9 @@
private String sql;
private ParameterTranslations paramTranslations;
+ private List collectedParameterSpecifications;
+
/**
* Creates a new AST-based query translator.
*
@@ -240,6 +242,7 @@
log.debug( "SQL: " + sql );
}
gen.getParseErrorHandler().throwQueryException();
+ collectedParameterSpecifications = gen.getCollectedParameters();
}
}
@@ -563,10 +566,15 @@
public ParameterTranslations getParameterTranslations() {
if ( paramTranslations == null ) {
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
+// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
}
return paramTranslations;
}
+ public List getCollectedParameterSpecifications() {
+ return collectedParameterSpecifications;
+ }
+
public static class JavaConstantConverter implements NodeTraverser.VisitationStrategy {
private AST dotRoot;
public void visit(AST node) {
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/SqlGenerator.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -27,16 +27,20 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Arrays;
import antlr.RecognitionException;
import antlr.collections.AST;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.hql.antlr.SqlGeneratorBase;
import org.hibernate.hql.ast.tree.MethodNode;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.Node;
+import org.hibernate.hql.ast.tree.ParameterNode;
+import org.hibernate.hql.ast.tree.ParameterContainer;
/**
* Generates SQL by overriding callback methods in the base class, which does
@@ -64,6 +68,12 @@
private LinkedList outputStack = new LinkedList();
+ private List collectedParameters = new ArrayList();
+
+ public List getCollectedParameters() {
+ return collectedParameters;
+ }
+
protected void out(String s) {
writer.clause( s );
}
@@ -75,6 +85,18 @@
else {
super.out( n );
}
+
+ if ( n instanceof ParameterNode ) {
+ collectedParameters.add( ( ( ParameterNode ) n ).getHqlParameterSpecification() );
+ }
+ else if ( n instanceof ParameterContainer ) {
+ if ( ( ( ParameterContainer ) n ).hasEmbeddedParameters() ) {
+ ParameterSpecification[] specifications = ( ( ParameterContainer ) n ).getEmbeddedParameters();
+ if ( specifications != null ) {
+ collectedParameters.addAll( Arrays.asList( specifications ) );
+ }
+ }
+ }
}
protected void commaBetweenParameters(String comma) {
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -27,6 +27,9 @@
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.Statement;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collections;
import org.hibernate.HibernateException;
import org.hibernate.action.BulkOperationCleanupAction;
@@ -42,6 +45,7 @@
import org.hibernate.sql.Select;
import org.hibernate.sql.SelectFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.util.EmptyIterator;
import antlr.RecognitionException;
import antlr.collections.AST;
@@ -57,6 +61,7 @@
private final Logger log;
private final HqlSqlWalker walker;
+ private List idSelectParameterSpecifications = Collections.EMPTY_LIST;
public AbstractStatementExecutor(HqlSqlWalker walker, Logger log) {
this.walker = walker;
@@ -71,6 +76,10 @@
return walker.getSessionFactoryHelper().getFactory();
}
+ protected List getIdSelectParameterSpecifications() {
+ return idSelectParameterSpecifications;
+ }
+
protected abstract Queryable[] getAffectedQueryables();
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
@@ -103,6 +112,7 @@
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
sqlGenerator.whereClause( whereClause );
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
+ idSelectParameterSpecifications = sqlGenerator.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw new HibernateException( "Unable to generate id select for DML operation", e );
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -27,6 +27,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
+import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
@@ -54,6 +55,7 @@
private final Queryable persister;
private final String sql;
+ private final List parameterSpecifications;
public BasicExecutor(HqlSqlWalker walker, Queryable persister) {
super( walker, log );
@@ -63,6 +65,7 @@
gen.statement( walker.getAST() );
sql = gen.getSQL();
gen.getParseErrorHandler().throwQueryException();
+ parameterSpecifications = gen.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw QuerySyntaxException.convert( e );
@@ -83,10 +86,10 @@
try {
try {
st = session.getBatcher().prepareStatement( sql );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator parameterSpecifications = this.parameterSpecifications.iterator();
int pos = 1;
- while ( paramSpecifications.hasNext() ) {
- final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
+ while ( parameterSpecifications.hasNext() ) {
+ final ParameterSpecification paramSpec = ( ParameterSpecification ) parameterSpecifications.next();
pos += paramSpec.bind( st, parameters, session, pos );
}
if ( selection != null ) {
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -107,7 +107,7 @@
try {
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -132,7 +132,7 @@
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
int parameterStart = getWalker().getNumberOfParametersInSetClause();
- List allParams = getWalker().getParameters();
+ List allParams = getIdSelectParameterSpecifications();
Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
int sum = 1; // jdbc params are 1-based
while ( whereParams.hasNext() ) {
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -26,8 +26,10 @@
import java.util.LinkedList;
import java.util.List;
+import java.util.ArrayList;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.CollectionProperties;
@@ -57,7 +59,7 @@
*
* @author josh
*/
-public class FromElement extends HqlSqlWalkerNode implements DisplayableNode {
+public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, ParameterContainer {
private static final Logger log = LoggerFactory.getLogger( FromElement.class );
private String className;
@@ -569,4 +571,23 @@
public boolean isDereferencedBySubclassProperty() {
return dereferencedBySubclassProperty;
}
+
+
+ // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private List embeddedParameters;
+
+ public void addEmbeddedParameter(ParameterSpecification specification) {
+ if ( embeddedParameters == null ) {
+ embeddedParameters = new ArrayList();
+ }
+ embeddedParameters.add( specification );
+ }
+
+ public boolean hasEmbeddedParameters() {
+ return embeddedParameters != null && ! embeddedParameters.isEmpty();
+ }
+
+ public ParameterSpecification[] getEmbeddedParameters() {
+ return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
+ }
}
Added: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/ParameterContainer.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/ParameterContainer.java (rev 0)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/ParameterContainer.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,77 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.hql.ast.tree;
+
+import org.hibernate.param.ParameterSpecification;
+
+/**
+ * Currently this is needed in order to deal with {@link FromElement FromElements} which
+ * conatin "hidden" JDBC parameters from applying filters.
+ * <p/>
+ * Would love for this to go away, but that would require that Hibernate's
+ * internal {@link org.hibernate.engine.JoinSequence join handling} be able to either:<ul>
+ * <li>render the same AST structures</li>
+ * <li>render structures capable of being converted to these AST structures</li>
+ * </ul>
+ * <p/>
+ * In the interim, this allows us to at least treat these "hidden" parameters properly which is
+ * the most pressing need.
+ *
+ * @deprecated
+ * @author Steve Ebersole
+ */
+public interface ParameterContainer {
+ /**
+ * Set the renderable text of this node.
+ *
+ * @param text The renderable text
+ */
+ public void setText(String text);
+
+ /**
+ * Adds a parameter specification for a parameter encountered within this node. We use the term 'embedded' here
+ * because of the fact that the parameter was simply encountered as part of the node's text; it does not exist
+ * as part of a subtree as it might in a true AST.
+ *
+ * @param specification The generated specification.
+ */
+ public void addEmbeddedParameter(ParameterSpecification specification);
+
+ /**
+ * Determine whether this node contans embedded parameters. The implication is that
+ * {@link #getEmbeddedParameters()} is allowed to return null if this method returns false.
+ *
+ * @return True if this node contains embedded parameters; false otherwise.
+ */
+ public boolean hasEmbeddedParameters();
+
+ /**
+ * Retrieve all embedded parameter specifications.
+ *
+ * @return All embedded parameter specifications; may return null.
+ * @see #hasEmbeddedParameters()
+ */
+ public ParameterSpecification[] getEmbeddedParameters();
+}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/SqlFragment.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -24,14 +24,18 @@
*/
package org.hibernate.hql.ast.tree;
+import java.util.List;
+import java.util.ArrayList;
+
import org.hibernate.sql.JoinFragment;
+import org.hibernate.param.ParameterSpecification;
/**
* Represents an SQL fragment in the AST.
*
* @author josh
*/
-public class SqlFragment extends Node {
+public class SqlFragment extends Node implements ParameterContainer {
private JoinFragment joinFragment;
private FromElement fromElement;
@@ -50,4 +54,23 @@
public FromElement getFromElement() {
return fromElement;
}
+
+
+ // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private List embeddedParameters;
+
+ public void addEmbeddedParameter(ParameterSpecification specification) {
+ if ( embeddedParameters == null ) {
+ embeddedParameters = new ArrayList();
+ }
+ embeddedParameters.add( specification );
+ }
+
+ public boolean hasEmbeddedParameters() {
+ return embeddedParameters != null && ! embeddedParameters.isEmpty();
+ }
+
+ public ParameterSpecification[] getEmbeddedParameters() {
+ return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
+ }
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/JoinProcessor.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -27,22 +27,29 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
-import java.util.Collections;
import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Collection;
import org.hibernate.AssertionFailure;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.impl.FilterImpl;
+import org.hibernate.type.Type;
+import org.hibernate.param.DynamicFilterParameterSpecification;
import org.hibernate.engine.JoinSequence;
+import org.hibernate.engine.QueryParameters;
import org.hibernate.hql.antlr.SqlTokenTypes;
-import org.hibernate.hql.ast.QueryTranslatorImpl;
+import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.tree.FromClause;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.DotNode;
+import org.hibernate.hql.ast.tree.ParameterContainer;
+import org.hibernate.hql.classic.ParserHelper;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.util.ArrayHelper;
-import antlr.ASTFactory;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,18 +64,17 @@
private static final Logger log = LoggerFactory.getLogger( JoinProcessor.class );
- private QueryTranslatorImpl queryTranslatorImpl;
- private SyntheticAndFactory andFactory;
+ private final HqlSqlWalker walker;
+ private final SyntheticAndFactory syntheticAndFactory;
/**
* Constructs a new JoinProcessor.
*
- * @param astFactory The factory for AST node creation.
- * @param queryTranslatorImpl The query translator.
+ * @param walker The walker to which we are bound, giving us access to needed resources.
*/
- public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
- this.andFactory = new SyntheticAndFactory( astFactory );
- this.queryTranslatorImpl = queryTranslatorImpl;
+ public JoinProcessor(HqlSqlWalker walker) {
+ this.walker = walker;
+ this.syntheticAndFactory = new SyntheticAndFactory( walker );
}
/**
@@ -92,7 +98,7 @@
}
}
- public void processJoins(QueryNode query, boolean inSubquery) {
+ public void processJoins(QueryNode query) {
final FromClause fromClause = query.getFromClause();
final List fromElements;
@@ -131,22 +137,21 @@
log.trace( "forcing inclusion of extra joins [alias=" + alias + ", containsTableAlias=" + containsTableAlias + "]" );
return true;
}
- boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
+ boolean shallowQuery = walker.isShallowQuery();
boolean includeSubclasses = fromElement.isIncludeSubclasses();
boolean subQuery = fromClause.isSubQuery();
return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
}
}
);
- addJoinNodes( query, join, fromElement, inSubquery );
+ addJoinNodes( query, join, fromElement );
}
}
- private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement, boolean inSubquery) {
- // Generate FROM and WHERE fragments for the from element.
+ private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
JoinFragment joinFragment = join.toJoinFragment(
- inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.getEnabledFilters(),
+ walker.getEnabledFilters(),
fromElement.useFromFragment() || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
fromElement.getWithClauseFragment(),
fromElement.getWithClauseJoinAlias()
@@ -166,13 +171,24 @@
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
- String fromFragment = processFromFragment( frag, join );
+ String fromFragment = processFromFragment( frag, join ).trim();
if ( log.isDebugEnabled() ) {
log.debug( "Using FROM fragment [" + fromFragment + "]" );
}
- fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement.
+ processDynamicFilterParameters(
+ fromFragment,
+ fromElement,
+ walker
+ );
}
- andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement );
+
+ syntheticAndFactory.addWhereFragment(
+ joinFragment,
+ whereFrag,
+ query,
+ fromElement,
+ walker
+ );
}
private String processFromFragment(String frag, JoinSequence join) {
@@ -184,4 +200,56 @@
return fromFragment;
}
+ public static void processDynamicFilterParameters(
+ final String sqlFragment,
+ final ParameterContainer container,
+ final HqlSqlWalker walker) {
+ if ( walker.getEnabledFilters().isEmpty()
+ && ( ! hasDynamicFilterParam( sqlFragment ) )
+ && ( ! ( hasCollectionFilterParam( sqlFragment ) ) ) ) {
+ return;
+ }
+
+ Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect();
+ String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
+ .append( dialect.openQuote() )
+ .append( dialect.closeQuote() )
+ .toString();
+ StringTokenizer tokens = new StringTokenizer( sqlFragment, symbols, true );
+ StringBuffer result = new StringBuffer();
+
+ while ( tokens.hasMoreTokens() ) {
+ final String token = tokens.nextToken();
+ if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
+ final String filterParameterName = token.substring( 1 );
+ final String[] parts = QueryParameters.parseFilterParameterName( filterParameterName );
+ final FilterImpl filter = ( FilterImpl ) walker.getEnabledFilters().get( parts[0] );
+ final Object value = filter.getParameter( parts[1] );
+ final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
+ final String typeBindFragment = StringHelper.join(
+ ",",
+ ArrayHelper.fillArray( "?", type.getColumnSpan( walker.getSessionFactoryHelper().getFactory() ) )
+ );
+ final String bindFragment = ( value != null && Collection.class.isInstance( value ) )
+ ? StringHelper.join( ",", ArrayHelper.fillArray( typeBindFragment, ( ( Collection ) value ).size() ) )
+ : typeBindFragment;
+ result.append( bindFragment );
+ container.addEmbeddedParameter( new DynamicFilterParameterSpecification( parts[0], parts[1], type ) );
+ }
+ else {
+ result.append( token );
+ }
+ }
+
+ container.setText( result.toString() );
+ }
+
+ private static boolean hasDynamicFilterParam(String sqlFragment) {
+ return sqlFragment.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0;
+ }
+
+ private static boolean hasCollectionFilterParam(String sqlFragment) {
+ return sqlFragment.indexOf( "?" ) < 0;
+ }
+
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/SyntheticAndFactory.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -31,9 +31,14 @@
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.RestrictableStatement;
import org.hibernate.hql.ast.tree.SqlFragment;
+import org.hibernate.hql.ast.tree.Node;
+import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.type.Type;
+import org.hibernate.param.CollectionFilterKeyParameterSpecification;
import antlr.ASTFactory;
import antlr.collections.AST;
@@ -49,27 +54,36 @@
public class SyntheticAndFactory implements HqlSqlTokenTypes {
private static final Logger log = LoggerFactory.getLogger( SyntheticAndFactory.class );
- private ASTFactory astFactory;
+ private HqlSqlWalker hqlSqlWalker;
private AST thetaJoins;
private AST filters;
- public SyntheticAndFactory(ASTFactory astFactory) {
- this.astFactory = astFactory;
+ public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) {
+ this.hqlSqlWalker = hqlSqlWalker;
}
- public void addWhereFragment(JoinFragment joinFragment, String whereFragment, QueryNode query, FromElement fromElement) {
+ private Node create(int tokenType, String text) {
+ return ( Node ) ASTUtil.create( hqlSqlWalker.getASTFactory(), tokenType, text );
+ }
+ public void addWhereFragment(
+ JoinFragment joinFragment,
+ String whereFragment,
+ QueryNode query,
+ FromElement fromElement,
+ HqlSqlWalker hqlSqlWalker) {
if ( whereFragment == null ) {
return;
}
+ if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
+ return;
+ }
+
whereFragment = whereFragment.trim();
if ( StringHelper.isEmpty( whereFragment ) ) {
return;
}
- else if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
- return;
- }
// Forcefully remove leading ands from where fragments; the grammar will
// handle adding them
@@ -77,12 +91,34 @@
whereFragment = whereFragment.substring( 4 );
}
- if ( log.isDebugEnabled() ) log.debug( "Using WHERE fragment [" + whereFragment + "]" );
+ log.debug( "Using unprocessed WHERE-fragment [{}]", whereFragment );
- SqlFragment fragment = ( SqlFragment ) ASTUtil.create( astFactory, SQL_TOKEN, whereFragment );
+ SqlFragment fragment = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
fragment.setJoinFragment( joinFragment );
fragment.setFromElement( fromElement );
+ if ( hqlSqlWalker.isFilter() ) {
+ if ( whereFragment.indexOf( '?' ) >= 0 ) {
+ Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
+ .requireQueryableCollection( hqlSqlWalker.getCollectionFilterRole() )
+ .getKeyType();
+ CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
+ hqlSqlWalker.getCollectionFilterRole(),
+ collectionFilterKeyType,
+ 0
+ );
+ fragment.addEmbeddedParameter( paramSpec );
+ }
+ }
+
+ JoinProcessor.processDynamicFilterParameters(
+ whereFragment,
+ fragment,
+ hqlSqlWalker
+ );
+
+ log.debug( "Using processed WHERE-fragment [{}]", fragment.getText() );
+
// Filter conditions need to be inserted before the HQL where condition and the
// theta join node. This is because org.hibernate.loader.Loader binds the filter parameters first,
// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
@@ -91,7 +127,7 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// Create a new FILTERS node as a parent of all filters
- filters = astFactory.create( FILTERS, "{filter conditions}" );
+ filters = create( FILTERS, "{filter conditions}" );
// Put the FILTERS node before the HQL condition and theta joins
ASTUtil.insertChild( where, filters );
}
@@ -104,7 +140,7 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// Create a new THETA_JOINS node as a parent of all filters
- thetaJoins = astFactory.create( THETA_JOINS, "{theta joins}" );
+ thetaJoins = create( THETA_JOINS, "{theta joins}" );
// Put the THETA_JOINS node before the HQL condition, after the filters.
if (filters==null) {
ASTUtil.insertChild( where, thetaJoins );
@@ -120,7 +156,11 @@
}
- public void addDiscriminatorWhereFragment(RestrictableStatement statement, Queryable persister, Map enabledFilters, String alias) {
+ public void addDiscriminatorWhereFragment(
+ RestrictableStatement statement,
+ Queryable persister,
+ Map enabledFilters,
+ String alias) {
String whereFragment = persister.filterFragment( alias, enabledFilters ).trim();
if ( "".equals( whereFragment ) ) {
return;
@@ -140,13 +180,19 @@
// At some point we probably want to apply an additional grammar to
// properly tokenize this where fragment into constituent parts
// focused on the operators embedded within the fragment.
- AST discrimNode = astFactory.create( SQL_TOKEN, whereFragment );
+ SqlFragment discrimNode = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
+ JoinProcessor.processDynamicFilterParameters(
+ whereFragment,
+ discrimNode,
+ hqlSqlWalker
+ );
+
if ( statement.getWhereClause().getNumberOfChildren() == 0 ) {
statement.getWhereClause().setFirstChild( discrimNode );
}
else {
- AST and = astFactory.create( AND, "{and}" );
+ AST and = create( AND, "{and}" );
AST currentFirstChild = statement.getWhereClause().getFirstChild();
and.setFirstChild( discrimNode );
and.addChild( currentFirstChild );
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/loader/hql/QueryLoader.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -506,8 +506,8 @@
final QueryParameters queryParameters,
final int startIndex,
final SessionImplementor session) throws SQLException {
- int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
- List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
+ int position = startIndex;
+ List parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
Iterator itr = parameterSpecs.iterator();
while ( itr.hasNext() ) {
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/AbstractExplicitParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/AbstractExplicitParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/AbstractExplicitParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -32,28 +32,45 @@
* @author Steve Ebersole
*/
public abstract class AbstractExplicitParameterSpecification implements ExplicitParameterSpecification {
-
private final int sourceLine;
private final int sourceColumn;
private Type expectedType;
+ /**
+ * Constructs an AbstractExplicitParameterSpecification.
+ *
+ * @param sourceLine See {@link #getSourceLine()}
+ * @param sourceColumn See {@link #getSourceColumn()}
+ */
protected AbstractExplicitParameterSpecification(int sourceLine, int sourceColumn) {
this.sourceLine = sourceLine;
this.sourceColumn = sourceColumn;
}
+ /**
+ * {@inheritDoc}
+ */
public int getSourceLine() {
return sourceLine;
}
+ /**
+ * {@inheritDoc}
+ */
public int getSourceColumn() {
return sourceColumn;
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return expectedType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
this.expectedType = expectedType;
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -32,13 +32,12 @@
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a collection-key
- * as part of a collection filter compilation.
+ * A specialized ParameterSpecification impl for dealing with a collection-key as part of a collection filter
+ * compilation.
*
* @author Steve Ebersole
*/
public class CollectionFilterKeyParameterSpecification implements ParameterSpecification {
-
private final String collectionRole;
private final Type keyType;
private final int queryParameterPosition;
@@ -57,6 +56,9 @@
this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
@@ -67,14 +69,23 @@
return keyType.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return keyType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// todo : throw exception?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "collection-filter-key=" + collectionRole;
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/DynamicFilterParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -26,20 +26,17 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Iterator;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a dynamic filter
- * parameters.
- * <p/>
- * Note: this class is currently not used. The ideal way to deal with dynamic filter
- * parameters for HQL would be to track them just as we do with other parameters
- * in the translator. However, the problem with that is that we currently do not
- * know the filters which actually apply to the query; we know the active/enabled ones,
- * but not the ones that actually "make it into" the resulting query.
+ * A specialized ParameterSpecification impl for dealing with a dynamic filter parameters.
+ *
+ * @see org.hibernate.Session#enableFilter(String)
*
* @author Steve Ebersole
*/
@@ -47,37 +44,65 @@
private final String filterName;
private final String parameterName;
private final Type definedParameterType;
- private final int queryParameterPosition;
+ /**
+ * Constructs a parameter specification for a particular filter parameter.
+ *
+ * @param filterName The name of the filter
+ * @param parameterName The name of the parameter
+ * @param definedParameterType The paremeter type specified on the filter metadata
+ */
public DynamicFilterParameterSpecification(
String filterName,
String parameterName,
- Type definedParameterType,
- int queryParameterPosition) {
+ Type definedParameterType) {
this.filterName = filterName;
this.parameterName = parameterName;
this.definedParameterType = definedParameterType;
- this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
SessionImplementor session,
- int position) throws SQLException {
- Object value = qp.getFilteredPositionalParameterValues()[queryParameterPosition];
- definedParameterType.nullSafeSet( statement, value, position, session );
- return definedParameterType.getColumnSpan( session.getFactory() );
+ int start) throws SQLException {
+ final int columnSpan = definedParameterType.getColumnSpan( session.getFactory() );
+ final Object value = session.getFilterParameterValue( filterName + '.' + parameterName );
+ if ( Collection.class.isInstance( value ) ) {
+ int positions = 0;
+ Iterator itr = ( ( Collection ) value ).iterator();
+ while ( itr.hasNext() ) {
+ definedParameterType.nullSafeSet( statement, itr.next(), start + positions, session );
+ positions += columnSpan;
+ }
+ return positions;
+ }
+ else {
+ definedParameterType.nullSafeSet( statement, value, start, session );
+ return columnSpan;
+ }
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return definedParameterType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
- // todo : throw exception?
+ // todo : throw exception? maybe warn if not the same?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/ExplicitParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/ExplicitParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/ExplicitParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -25,13 +25,23 @@
package org.hibernate.param;
/**
- * An additional contract for parameters which originate from
- * parameters explicitly encountered in the source statement
+ * An additional contract for parameters which originate from parameters explicitly encountered in the source statement
* (HQL or native-SQL).
*
* @author Steve Ebersole
*/
public interface ExplicitParameterSpecification extends ParameterSpecification {
+ /**
+ * Retrieves the line number on which this parameter occurs in the source query.
+ *
+ * @return The line number.
+ */
public int getSourceLine();
+
+ /**
+ * Retrieves the column number (within the {@link #getSourceLine()}) where this parameter occurs.
+ *
+ * @return The column number.
+ */
public int getSourceColumn();
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/NamedParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/NamedParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/NamedParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -32,14 +32,20 @@
import java.sql.SQLException;
/**
- * Relates to an explicit query named-parameter.
+ * Parameter bind specification for an explicit named parameter.
*
* @author Steve Ebersole
*/
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
-
private final String name;
+ /**
+ * Constructs a named parameter bind specification.
+ *
+ * @param sourceLine See {@link #getSourceLine()}
+ * @param sourceColumn See {@link #getSourceColumn()}
+ * @param name The named parameter name.
+ */
public NamedParameterSpecification(int sourceLine, int sourceColumn, String name) {
super( sourceLine, sourceColumn );
this.name = name;
@@ -62,10 +68,18 @@
return typedValue.getType().getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "name=" + name + ", expectedType=" + getExpectedType();
}
+ /**
+ * Getter for property 'name'.
+ *
+ * @return Value for property 'name'.
+ */
public String getName() {
return name;
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/PositionalParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -32,14 +32,20 @@
import java.sql.SQLException;
/**
- * Relates to an explicit query positional (or ordinal) parameter.
+ * Parameter bind specification for an explicit positional (or ordinal) parameter.
*
* @author Steve Ebersole
*/
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
-
private final int hqlPosition;
+ /**
+ * Constructs a position/ordinal parameter bind specification.
+ *
+ * @param sourceLine See {@link #getSourceLine()}
+ * @param sourceColumn See {@link #getSourceColumn()}
+ * @param hqlPosition The position in the source query, relative to the other source positional parameters.
+ */
public PositionalParameterSpecification(int sourceLine, int sourceColumn, int hqlPosition) {
super( sourceLine, sourceColumn );
this.hqlPosition = hqlPosition;
@@ -63,10 +69,18 @@
return type.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "ordinal=" + hqlPosition + ", expectedType=" + getExpectedType();
}
+ /**
+ * Getter for property 'hqlPosition'.
+ *
+ * @return Value for property 'hqlPosition'.
+ */
public int getHqlPosition() {
return hqlPosition;
}
Modified: core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/VersionTypeSeedParameterSpecification.java
===================================================================
--- core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/core/src/main/java/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -33,20 +33,24 @@
import java.sql.SQLException;
/**
- * Implementation of VersionTypeSeedParameterSpecification.
+ * Parameter bind specification used for optimisitc lock version seeding (from insert statements).
*
* @author Steve Ebersole
*/
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
-
private VersionType type;
+ /**
+ * Constructs a version seed parameter bind specification.
+ *
+ * @param type The version type.
+ */
public VersionTypeSeedParameterSpecification(VersionType type) {
this.type = type;
}
/**
- * @see org.hibernate.param.ParameterSpecification#bind
+ * {@inheritDoc}
*/
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
throws SQLException {
@@ -54,14 +58,23 @@
return 1;
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return type;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// expected type is intrinsic here...
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "version-seed, type=" + type;
}
Modified: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01 19:32:11 UTC (rev 15240)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -18,13 +18,17 @@
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
+import org.hibernate.Criteria;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.entry.CollectionCacheEntry;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Restrictions;
-import org.hibernate.engine.SessionImplementor;
-import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Property;
+import org.hibernate.criterion.Subqueries;
import org.hibernate.junit.functional.FunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.persister.collection.CollectionPersister;
@@ -210,6 +214,305 @@
testData.release();
}
+ public void testCriteriaControl() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ // the subquery...
+ DetachedCriteria subquery = DetachedCriteria.forClass( Salesperson.class )
+ .setProjection( Property.forName( "name" ) );
+
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+
+ List result = session.createCriteria( Order.class )
+ .add( Subqueries.in( "steve", subquery ) )
+ .list();
+ assertEquals( 1, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testCriteriaSubqueryWithFilters() {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Criteria-subquery test
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ log.info("Starting Criteria-subquery filter tests");
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ log.info("Criteria query against Department with a subquery on Salesperson in the APAC reqion...");
+ DetachedCriteria salespersonSubquery = DetachedCriteria.forClass(Salesperson.class)
+ .add(Restrictions.eq("name", "steve"))
+ .setProjection(Property.forName("department"));
+
+ Criteria departmentsQuery = session.createCriteria(Department.class).add(Subqueries.propertyIn("id", salespersonSubquery));
+ List departments = departmentsQuery.list();
+
+ assertEquals("Incorrect department count", 1, departments.size());
+
+ log.info("Criteria query against Department with a subquery on Salesperson in the FooBar reqion...");
+
+ session.enableFilter("region").setParameter("region", "Foobar");
+ departments = departmentsQuery.list();
+
+ assertEquals("Incorrect department count", 0, departments.size());
+
+ log.info("Criteria query against Order with a subquery for line items with a subquery on product and sold by a given sales person...");
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ DetachedCriteria lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
+ .add(Restrictions.ge("quantity", 1L))
+ .createCriteria("product")
+ .add(Restrictions.eq("name", "Acme Hair Gel"))
+ .setProjection(Property.forName("id"));
+
+ List orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of last month");
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ DetachedCriteria productSubquery = DetachedCriteria.forClass(Product.class)
+ .add(Restrictions.eq("name", "Acme Hair Gel"))
+ .setProjection(Property.forName("id"));
+
+ lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
+ .add(Restrictions.ge("quantity", 1L))
+ .createCriteria("product")
+ .add(Subqueries.propertyIn("id", productSubquery))
+ .setProjection(Property.forName("id"));
+
+ orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of 4 months ago");
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
+
+ orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 0, orders.size());
+
+ session.close();
+ testData.release();
+ }
+
+ public void testHQLSubqueryWithFilters() {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // HQL subquery with filters test
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ log.info("Starting HQL subquery with filters tests");
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ log.info("query against Department with a subquery on Salesperson in the APAC reqion...");
+
+ List departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
+
+ assertEquals("Incorrect department count", 1, departments.size());
+
+ log.info("query against Department with a subquery on Salesperson in the FooBar reqion...");
+
+ session.enableFilter("region").setParameter("region", "Foobar");
+ departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
+
+ assertEquals("Incorrect department count", 0, departments.size());
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region for a given buyer");
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ List orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li, Product as p where p.id = li.product and li.quantity >= ? and p.name = ?) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of last month");
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of 4 months ago");
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 0, orders.size());
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of last month with named types");
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= :quantity and li.product in (select p.id from Product p where p.name = :name)) and o.buyer = :buyer")
+ .setLong("quantity", 1L).setString("name", "Acme Hair Gel").setString("buyer", "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ log.info("query against Order with a subquery for line items with a subquery line items where the product name is Acme Hair Gel and the quantity is greater than 1 in a given region and the product is effective as of last month with mixed types");
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = :buyer")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString("buyer", "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.close();
+ testData.release();
+ }
+
+ public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingPositionalParameter() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.beginTransaction();
+
+ final String queryString = "from Order o where ? in ( select sp.name from Salesperson sp )";
+
+ // first a control-group query
+ List result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 2, result.size() );
+
+ // now lets enable filters on Order...
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // now, lets additionally enable filter on Salesperson. First a valid one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // ... then a silly one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 0, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingNamedParameter() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.beginTransaction();
+
+ final String queryString = "from Order o where :salesPersonName in ( select sp.name from Salesperson sp )";
+
+ // first a control-group query
+ List result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 2, result.size() );
+
+ // now lets enable filters on Order...
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // now, lets additionally enable filter on Salesperson. First a valid one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // ... then a silly one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 0, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testFiltersOnSimpleHqlDelete() {
+ Session session = openSession();
+ session.beginTransaction();
+ Salesperson sp = new Salesperson();
+ sp.setName( "steve" );
+ sp.setRegion( "NA" );
+ session.persist( sp );
+ Salesperson sp2 = new Salesperson();
+ sp2.setName( "john" );
+ sp2.setRegion( "APAC" );
+ session.persist( sp2 );
+ session.getTransaction().commit();
+ session.close();
+
+ session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "region" ).setParameter( "region", "NA" );
+ int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
+ assertEquals( 1, count );
+ session.delete( sp2 );
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ public void testFiltersOnMultiTableHqlDelete() {
+ Session session = openSession();
+ session.beginTransaction();
+ Salesperson sp = new Salesperson();
+ sp.setName( "steve" );
+ sp.setRegion( "NA" );
+ session.persist( sp );
+ Salesperson sp2 = new Salesperson();
+ sp2.setName( "john" );
+ sp2.setRegion( "APAC" );
+ session.persist( sp2 );
+ session.getTransaction().commit();
+ session.close();
+
+ session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "region" ).setParameter( "region", "NA" );
+ int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
+ assertEquals( 1, count );
+ session.delete( sp2 );
+ session.getTransaction().commit();
+ session.close();
+ }
+
+
public void testGetFilters() {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get() test
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Basic.hbm.xml
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Basic.hbm.xml (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Basic.hbm.xml 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <class name="Person" table="FILTER_HQL_PERSON">
+ <id column="ID" name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" type="string"/>
+ <property name="sex" column="SEX_CODE" type="char"/>
+ <filter name="sex"/>
+ </class>
+</hibernate-mapping>
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.Session;
+
+/**
+ * Tests for application of filters
+ *
+ * @author Steve Ebersole
+ */
+public class BasicFilteredBulkManipulationTest extends FunctionalTestCase {
+ public BasicFilteredBulkManipulationTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[]{
+ "filter/hql/filter-defs.hbm.xml",
+ "filter/hql/Basic.hbm.xml"
+ };
+ }
+
+ public void testBasicFilteredHqlDelete() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Person( "Steve", 'M' ) );
+ s.save( new Person( "Emmanuel", 'M' ) );
+ s.save( new Person( "Gail", 'F' ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
+ int count = s.createQuery( "delete Person" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBasicFilteredHqlUpdate() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Person( "Shawn", 'M' ) );
+ s.save( new Person( "Sally", 'F' ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
+ int count = s.createQuery( "update Person p set p.name = 'Shawn'" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Customer.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Customer.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Customer.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class Customer extends User {
+ private String company;
+
+ protected Customer() {
+ super();
+ }
+
+ public Customer(String name, char sex, String username, String company) {
+ super( name, sex, username );
+ this.company = company;
+ }
+
+ public String getCompany() {
+ return company;
+ }
+
+ public void setCompany(String company) {
+ this.company = company;
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Employee.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Employee.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Employee.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import java.util.Date;
+
+/**
+ * Leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class Employee extends User {
+ private Date hireDate;
+
+ protected Employee() {
+ super();
+ }
+
+ public Employee(String name, char sex, String username, Date hireDate) {
+ super( name, sex, username );
+ this.hireDate = hireDate;
+ }
+
+ public Date getHireDate() {
+ return hireDate;
+ }
+
+ public void setHireDate(Date hireDate) {
+ this.hireDate = hireDate;
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Joined.hbm.xml
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Joined.hbm.xml (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Joined.hbm.xml 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <class name="Person" table="FILTER_HQL_JOINED_PERSON">
+ <id column="ID" name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" type="string"/>
+ <property name="sex" column="SEX_CODE" type="char"/>
+ <joined-subclass name="User" table="FILTER_HQL_JOINED_USER">
+ <key column="USER_ID"/>
+ <property name="username" type="string"/>
+ <joined-subclass name="Employee" table="FILTER_HQL_JOINED_EMP">
+ <key column="EMP_ID"/>
+ <property name="hireDate" type="date"/>
+ </joined-subclass>
+ <joined-subclass name="Customer" table="FILTER_HQL_JOINED_CUST">
+ <key column="CUST_ID"/>
+ <property name="company" type="string"/>
+ </joined-subclass>
+ </joined-subclass>
+ <filter name="sex"/>
+ </class>
+</hibernate-mapping>
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,201 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import java.util.Date;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.Session;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class JoinedFilteredBulkManipulationTest extends FunctionalTestCase {
+ public JoinedFilteredBulkManipulationTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[]{
+ "filter/hql/filter-defs.hbm.xml",
+ "filter/hql/Joined.hbm.xml"
+ };
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteRoot() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete Person" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteNonLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete User" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete Employee" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateRoot() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update Person p set p.name = '<male>'" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateNonLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update User u set u.username = :un where u.name = :n" )
+ .setString( "un", "charlie" )
+ .setString( "n", "Wanda" )
+ .executeUpdate();
+ assertEquals( 0, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update Customer c set c.company = 'XYZ'" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Person.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Person.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/Person.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,71 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Base of inheritence hierarchy
+ *
+ * @author Steve Ebersole
+ */
+public class Person {
+ private Long id;
+ private String name;
+ private char sex;
+
+ /**
+ * Used by persistence
+ */
+ protected Person() {
+ }
+
+ public Person(String name, char sex) {
+ this.name = name;
+ this.sex = sex;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ private void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public char getSex() {
+ return sex;
+ }
+
+ public void setSex(char sex) {
+ this.sex = sex;
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/User.java
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/User.java (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/User.java 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Non-leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class User extends Person {
+ private String username;
+
+ protected User() {
+ super();
+ }
+
+ public User(String name, char sex, String username) {
+ super( name, sex );
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
Added: core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/filter-defs.hbm.xml
===================================================================
--- core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/filter-defs.hbm.xml (rev 0)
+++ core/branches/Branch_3_3/testsuite/src/test/java/org/hibernate/test/filter/hql/filter-defs.hbm.xml 2008-10-01 19:42:55 UTC (rev 15241)
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <filter-def name="sex" condition="SEX_CODE = :sexCode">
+ <filter-param name="sexCode" type="char"/>
+ </filter-def>
+</hibernate-mapping>
16 years, 3 months
Hibernate SVN: r15240 - in core/branches/Branch_3_2: src/org/hibernate/engine and 8 other directories.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 15:32:11 -0400 (Wed, 01 Oct 2008)
New Revision: 15240
Added:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml
Modified:
core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java
core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java
core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java
core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java
core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java
core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java
Log:
HHH-530 : filters + subqueries;
HHH-3506 : filters + HQL update/delete
Modified: core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/criterion/SubqueryExpression.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -1,14 +1,13 @@
//$Id$
package org.hibernate.criterion;
-import java.util.HashMap;
-
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.TypedValue;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaJoinWalker;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
@@ -19,7 +18,7 @@
* @author Gavin King
*/
public abstract class SubqueryExpression implements Criterion {
-
+
private CriteriaImpl criteriaImpl;
private String quantifier;
private String op;
@@ -30,49 +29,67 @@
protected Type[] getTypes() {
return types;
}
-
+
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
this.criteriaImpl = dc.getCriteriaImpl();
this.quantifier = quantifier;
this.op = op;
}
-
+
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
- public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
- throws HibernateException {
-
+ public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
- final OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
+ final OuterJoinLoadable persister =
+ ( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
createAndSetInnerQuery( criteriaQuery, factory );
-
+ criteriaImpl.setSession( deriveRootSession( criteria ) );
+
CriteriaJoinWalker walker = new CriteriaJoinWalker(
persister,
innerQuery,
factory,
criteriaImpl,
criteriaImpl.getEntityOrClassName(),
- new HashMap(),
- innerQuery.getRootSQLALias());
+ criteriaImpl.getSession().getEnabledFilters(),
+ innerQuery.getRootSQLALias()
+ );
String sql = walker.getSQLString();
- final StringBuffer buf = new StringBuffer()
- .append( toLeftSqlString(criteria, criteriaQuery) );
- if (op!=null) buf.append(' ').append(op).append(' ');
- if (quantifier!=null) buf.append(quantifier).append(' ');
- return buf.append('(').append(sql).append(')')
- .toString();
+ final StringBuffer buf = new StringBuffer( toLeftSqlString(criteria, criteriaQuery) );
+ if ( op != null ) {
+ buf.append( ' ' ).append( op ).append( ' ' );
+ }
+ if ( quantifier != null ) {
+ buf.append( quantifier ).append( ' ' );
+ }
+ return buf.append( '(' ).append( sql ).append( ')' )
+ .toString();
}
- public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
+ private SessionImplementor deriveRootSession(Criteria criteria) {
+ if ( criteria instanceof CriteriaImpl ) {
+ return ( ( CriteriaImpl ) criteria ).getSession();
+ }
+ else if ( criteria instanceof CriteriaImpl.Subcriteria ) {
+ return deriveRootSession( ( ( CriteriaImpl.Subcriteria ) criteria ).getParent() );
+ }
+ else {
+ // could happen for custom Criteria impls. Not likely, but...
+ // for long term solution, see HHH-3514
+ return null;
+ }
+ }
+
+ public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
//the following two lines were added to ensure that this.params is not null, which
//can happen with two-deep nested subqueries
SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery(criteriaQuery, factory);
-
+
Type[] ppTypes = params.getPositionalParameterTypes();
Object[] ppValues = params.getPositionalParameterValues();
TypedValue[] tv = new TypedValue[ppTypes.length];
@@ -83,12 +100,12 @@
}
/**
- * Creates the inner query used to extract some useful information about
- * types, since it is needed in both methods.
- * @param criteriaQuery
- * @param factory
+ * Creates the inner query used to extract some useful information about types, since it is needed in both methods.
+ *
+ * @param criteriaQuery The criteria query
+ * @param factory The session factory.
*/
- private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, final SessionFactoryImplementor factory) {
+ private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, SessionFactoryImplementor factory) {
if ( innerQuery == null ) {
//with two-deep subqueries, the same alias would get generated for
//both using the old method (criteriaQuery.generateSQLAlias()), so
Modified: core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/engine/QueryParameters.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -3,7 +3,6 @@
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -16,6 +15,7 @@
import org.hibernate.HibernateException;
import org.hibernate.QueryException;
import org.hibernate.ScrollMode;
+import org.hibernate.impl.FilterImpl;
import org.hibernate.dialect.Dialect;
import org.hibernate.hql.classic.ParserHelper;
import org.hibernate.pretty.Printer;
@@ -46,29 +46,28 @@
private boolean callable = false;
private boolean autodiscovertypes = false;
private boolean isNaturalKeyLookup;
-
+
private final ResultTransformer resultTransformer; // why is all others non final ?
-
+
private String processedSQL;
private Type[] processedPositionalParameterTypes;
private Object[] processedPositionalParameterValues;
-
+
public QueryParameters() {
this( ArrayHelper.EMPTY_TYPE_ARRAY, ArrayHelper.EMPTY_OBJECT_ARRAY );
}
public QueryParameters(Type type, Object value) {
- this( new Type[] {type}, new Object[] {value} );
+ this( new Type[] { type }, new Object[] { value } );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalObjectId
- ) {
- this(positionalParameterTypes, postionalParameterValues);
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalObjectId) {
+ this( positionalParameterTypes, postionalParameterValues );
this.optionalObject = optionalObject;
this.optionalId = optionalObjectId;
this.optionalEntityName = optionalEntityName;
@@ -76,42 +75,24 @@
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- null,
- false,
- null,
- null,
- false,
- null
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues) {
+ this( positionalParameterTypes, postionalParameterValues, null, null, false, null, null, false, null );
}
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] postionalParameterValues,
- final Serializable[] collectionKeys
- ) {
- this(
- positionalParameterTypes,
- postionalParameterValues,
- null,
- collectionKeys
- );
+ final Type[] positionalParameterTypes,
+ final Object[] postionalParameterValues,
+ final Serializable[] collectionKeys) {
+ this( positionalParameterTypes, postionalParameterValues, null, collectionKeys );
}
public QueryParameters(
final Type[] positionalParameterTypes,
final Object[] postionalParameterValues,
final Map namedParameters,
- final Serializable[] collectionKeys
- ) {
- this(
+ final Serializable[] collectionKeys) {
+ this(
positionalParameterTypes,
postionalParameterValues,
namedParameters,
@@ -119,37 +100,36 @@
null,
false,
false,
- null,
null,
+ null,
collectionKeys,
null
- );
- }
+ );
+ }
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final boolean isLookupByNaturalKey,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final boolean isLookupByNaturalKey,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- null,
- lockModes,
- rowSelection,
- false,
- cacheable,
- cacheRegion,
- comment,
- null,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ null,
+ lockModes,
+ rowSelection,
+ false,
+ cacheable,
+ cacheRegion,
+ comment,
+ null,
+ transformer
);
isNaturalKeyLookup = isLookupByNaturalKey;
}
@@ -166,8 +146,7 @@
//final boolean forceCacheRefresh,
final String comment,
final Serializable[] collectionKeys,
- ResultTransformer transformer
- ) {
+ ResultTransformer transformer) {
this.positionalParameterTypes = positionalParameterTypes;
this.positionalParameterValues = positionalParameterValues;
this.namedParameters = namedParameters;
@@ -181,36 +160,35 @@
this.readOnly = readOnly;
this.resultTransformer = transformer;
}
-
+
public QueryParameters(
- final Type[] positionalParameterTypes,
- final Object[] positionalParameterValues,
- final Map namedParameters,
- final Map lockModes,
- final RowSelection rowSelection,
- final boolean readOnly,
- final boolean cacheable,
- final String cacheRegion,
- //final boolean forceCacheRefresh,
- final String comment,
- final Serializable[] collectionKeys,
- final Object optionalObject,
- final String optionalEntityName,
- final Serializable optionalId,
- final ResultTransformer transformer
- ) {
+ final Type[] positionalParameterTypes,
+ final Object[] positionalParameterValues,
+ final Map namedParameters,
+ final Map lockModes,
+ final RowSelection rowSelection,
+ final boolean readOnly,
+ final boolean cacheable,
+ final String cacheRegion,
+ //final boolean forceCacheRefresh,
+ final String comment,
+ final Serializable[] collectionKeys,
+ final Object optionalObject,
+ final String optionalEntityName,
+ final Serializable optionalId,
+ final ResultTransformer transformer) {
this(
- positionalParameterTypes,
- positionalParameterValues,
- namedParameters,
- lockModes,
- rowSelection,
- readOnly,
- cacheable,
- cacheRegion,
- comment,
- collectionKeys,
- transformer
+ positionalParameterTypes,
+ positionalParameterValues,
+ namedParameters,
+ lockModes,
+ rowSelection,
+ readOnly,
+ cacheable,
+ cacheRegion,
+ comment,
+ collectionKeys,
+ transformer
);
this.optionalEntityName = optionalEntityName;
this.optionalId = optionalId;
@@ -218,7 +196,7 @@
}
public boolean hasRowSelection() {
- return rowSelection!=null;
+ return rowSelection != null;
}
public Map getNamedParameters() {
@@ -236,7 +214,7 @@
public RowSelection getRowSelection() {
return rowSelection;
}
-
+
public ResultTransformer getResultTransformer() {
return resultTransformer;
}
@@ -266,15 +244,15 @@
}
public void traceParameters(SessionFactoryImplementor factory) throws HibernateException {
- Printer print = new Printer(factory);
- if (positionalParameterValues.length!=0) {
+ Printer print = new Printer( factory );
+ if ( positionalParameterValues.length != 0 ) {
log.trace(
- "parameters: " +
- print.toString(positionalParameterTypes, positionalParameterValues)
- );
+ "parameters: " +
+ print.toString( positionalParameterTypes, positionalParameterValues )
+ );
}
- if (namedParameters!=null) {
- log.trace( "named parameters: " + print.toString(namedParameters) );
+ if ( namedParameters != null ) {
+ log.trace( "named parameters: " + print.toString( namedParameters ) );
}
}
@@ -295,13 +273,13 @@
}
public void validateParameters() throws QueryException {
- int types = positionalParameterTypes==null ? 0 : positionalParameterTypes.length;
- int values = positionalParameterValues==null ? 0 : positionalParameterValues.length;
- if (types!=values) {
+ int types = positionalParameterTypes == null ? 0 : positionalParameterTypes.length;
+ int values = positionalParameterValues == null ? 0 : positionalParameterValues.length;
+ if ( types != values ) {
throw new QueryException(
- "Number of positional parameter types:" + types +
- " does not match number of positional parameters: " + values
- );
+ "Number of positional parameter types:" + types +
+ " does not match number of positional parameters: " + values
+ );
}
}
@@ -362,44 +340,49 @@
}
public void setCallable(boolean callable) {
- this.callable = callable;
+ this.callable = callable;
}
public boolean isCallable() {
return callable;
}
-
+
public boolean hasAutoDiscoverScalarTypes() {
return autodiscovertypes;
}
public void processFilters(String sql, SessionImplementor session) {
-
- if ( session.getEnabledFilters().size()==0 || sql.indexOf(ParserHelper.HQL_VARIABLE_PREFIX)<0 ) {
+ processFilters( sql, session.getEnabledFilters(), session.getFactory() );
+ }
+
+ public void processFilters(String sql, Map filters, SessionFactoryImplementor factory) {
+ if ( filters.size() == 0 || sql.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0 ) {
// HELLA IMPORTANT OPTIMIZATION!!!
processedPositionalParameterValues = getPositionalParameterValues();
processedPositionalParameterTypes = getPositionalParameterTypes();
processedSQL = sql;
}
else {
-
- Dialect dialect = session.getFactory().getDialect();
+ final Dialect dialect = factory.getDialect();
String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
.append( dialect.openQuote() )
.append( dialect.closeQuote() )
.toString();
StringTokenizer tokens = new StringTokenizer( sql, symbols, true );
StringBuffer result = new StringBuffer();
-
+
List parameters = new ArrayList();
List parameterTypes = new ArrayList();
-
+
+ int positionalIndex = 0;
while ( tokens.hasMoreTokens() ) {
final String token = tokens.nextToken();
if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
- String filterParameterName = token.substring( 1 );
- Object value = session.getFilterParameterValue( filterParameterName );
- Type type = session.getFilterParameterType( filterParameterName );
+ final String filterParameterName = token.substring( 1 );
+ final String[] parts = parseFilterParameterName( filterParameterName );
+ final FilterImpl filter = ( FilterImpl ) filters.get( parts[0] );
+ final Object value = filter.getParameter( parts[1] );
+ final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
if ( value != null && Collection.class.isAssignableFrom( value.getClass() ) ) {
Iterator itr = ( ( Collection ) value ).iterator();
while ( itr.hasNext() ) {
@@ -419,15 +402,17 @@
}
}
else {
+ if ( "?".equals( token ) && positionalIndex < getPositionalParameterValues().length ) {
+ parameters.add( getPositionalParameterValues()[positionalIndex] );
+ parameterTypes.add( getPositionalParameterTypes()[positionalIndex] );
+ positionalIndex++;
+ }
result.append( token );
}
}
- parameters.addAll( Arrays.asList( getPositionalParameterValues() ) );
- parameterTypes.addAll( Arrays.asList( getPositionalParameterTypes() ) );
processedPositionalParameterValues = parameters.toArray();
- processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[0] );
+ processedPositionalParameterTypes = ( Type[] ) parameterTypes.toArray( new Type[parameterTypes.size()] );
processedSQL = result.toString();
-
}
}
@@ -458,16 +443,16 @@
public QueryParameters createCopyUsing(RowSelection selection) {
QueryParameters copy = new QueryParameters(
this.positionalParameterTypes,
- this.positionalParameterValues,
- this.namedParameters,
- this.lockModes,
- selection,
- this.readOnly,
- this.cacheable,
- this.cacheRegion,
- this.comment,
- this.collectionKeys,
- this.optionalObject,
+ this.positionalParameterValues,
+ this.namedParameters,
+ this.lockModes,
+ selection,
+ this.readOnly,
+ this.cacheable,
+ this.cacheRegion,
+ this.comment,
+ this.collectionKeys,
+ this.optionalObject,
this.optionalEntityName,
this.optionalId,
this.resultTransformer
@@ -478,5 +463,13 @@
return copy;
}
-
+ public static String[] parseFilterParameterName(String filterParameterName) {
+ int dot = filterParameterName.indexOf( '.' );
+ if ( dot <= 0 ) {
+ throw new IllegalArgumentException( "Invalid filter-parameter name format" );
+ }
+ String filterName = filterParameterName.substring( 0, dot );
+ String parameterName = filterParameterName.substring( dot + 1 );
+ return new String[] { filterName, parameterName };
+ }
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/HqlSqlWalker.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -209,6 +209,10 @@
return collectionFilterRole != null;
}
+ public String getCollectionFilterRole() {
+ return collectionFilterRole;
+ }
+
public SessionFactoryHelper getSessionFactoryHelper() {
return sessionFactoryHelper;
}
@@ -531,8 +535,8 @@
// After that, process the JOINs.
// Invoke a delegate to do the work, as this is farily complex.
- JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl );
- joinProcessor.processJoins( qn, isSubQuery() );
+ JoinProcessor joinProcessor = new JoinProcessor( this );
+ joinProcessor.processJoins( qn );
// Attach any mapping-defined "ORDER BY" fragments
Iterator itr = qn.getFromClause().getProjectionList().iterator();
@@ -570,13 +574,21 @@
// Make #@%$^#^&# sure no alias is applied to the table name
fromElement.setText( persister.getTableName() );
- // append any filter fragments; the EMPTY_MAP is used under the assumption that
- // currently enabled filters should not affect this process
- if ( persister.getDiscriminatorType() != null ) {
- new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
+// // append any filter fragments; the EMPTY_MAP is used under the assumption that
+// // currently enabled filters should not affect this process
+// if ( persister.getDiscriminatorType() != null ) {
+// new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
+// statement,
+// persister,
+// java.util.Collections.EMPTY_MAP,
+// fromElement.getTableAlias()
+// );
+// }
+ if ( persister.getDiscriminatorType() != null || ! queryTranslatorImpl.getEnabledFilters().isEmpty() ) {
+ new SyntheticAndFactory( this ).addDiscriminatorWhereFragment(
statement,
persister,
- java.util.Collections.EMPTY_MAP,
+ queryTranslatorImpl.getEnabledFilters(),
fromElement.getTableAlias()
);
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/QueryTranslatorImpl.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -74,7 +74,9 @@
private String sql;
private ParameterTranslations paramTranslations;
+ private List collectedParameterSpecifications;
+
/**
* Creates a new AST-based query translator.
*
@@ -217,6 +219,7 @@
log.debug( "SQL: " + sql );
}
gen.getParseErrorHandler().throwQueryException();
+ collectedParameterSpecifications = gen.getCollectedParameters();
}
}
@@ -540,10 +543,15 @@
public ParameterTranslations getParameterTranslations() {
if ( paramTranslations == null ) {
paramTranslations = new ParameterTranslationsImpl( getWalker().getParameters() );
+// paramTranslations = new ParameterTranslationsImpl( collectedParameterSpecifications );
}
return paramTranslations;
}
+ public List getCollectedParameterSpecifications() {
+ return collectedParameterSpecifications;
+ }
+
public static class JavaConstantConverter implements NodeTraverser.VisitationStrategy {
private AST dotRoot;
public void visit(AST node) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlGenerator.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -4,16 +4,20 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.Arrays;
import antlr.RecognitionException;
import antlr.collections.AST;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.hql.antlr.SqlGeneratorBase;
import org.hibernate.hql.ast.tree.MethodNode;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.Node;
+import org.hibernate.hql.ast.tree.ParameterNode;
+import org.hibernate.hql.ast.tree.ParameterContainer;
/**
* Generates SQL by overriding callback methods in the base class, which does
@@ -41,6 +45,12 @@
private LinkedList outputStack = new LinkedList();
+ private List collectedParameters = new ArrayList();
+
+ public List getCollectedParameters() {
+ return collectedParameters;
+ }
+
protected void out(String s) {
writer.clause( s );
}
@@ -52,6 +62,18 @@
else {
super.out( n );
}
+
+ if ( n instanceof ParameterNode ) {
+ collectedParameters.add( ( ( ParameterNode ) n ).getHqlParameterSpecification() );
+ }
+ else if ( n instanceof ParameterContainer ) {
+ if ( ( ( ParameterContainer ) n ).hasEmbeddedParameters() ) {
+ ParameterSpecification[] specifications = ( ( ParameterContainer ) n ).getEmbeddedParameters();
+ if ( specifications != null ) {
+ collectedParameters.addAll( Arrays.asList( specifications ) );
+ }
+ }
+ }
}
protected void commaBetweenParameters(String comma) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -4,6 +4,8 @@
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.action.BulkOperationCleanupAction;
@@ -34,6 +36,7 @@
private final Log log;
private final HqlSqlWalker walker;
+ private List idSelectParameterSpecifications = Collections.EMPTY_LIST;
public AbstractStatementExecutor(HqlSqlWalker walker, Log log) {
this.walker = walker;
@@ -48,6 +51,10 @@
return walker.getSessionFactoryHelper().getFactory();
}
+ protected List getIdSelectParameterSpecifications() {
+ return idSelectParameterSpecifications;
+ }
+
protected abstract Queryable[] getAffectedQueryables();
protected String generateIdInsertSelect(Queryable persister, String tableAlias, AST whereClause) {
@@ -80,6 +87,7 @@
SqlGenerator sqlGenerator = new SqlGenerator( getFactory() );
sqlGenerator.whereClause( whereClause );
userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
+ idSelectParameterSpecifications = sqlGenerator.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw new HibernateException( "Unable to generate id select for DML operation", e );
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/BasicExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -4,6 +4,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Iterator;
+import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.engine.QueryParameters;
@@ -31,6 +32,7 @@
private final Queryable persister;
private final String sql;
+ private final List parameterSpecifications;
public BasicExecutor(HqlSqlWalker walker, Queryable persister) {
super( walker, log );
@@ -40,6 +42,7 @@
gen.statement( walker.getAST() );
sql = gen.getSQL();
gen.getParseErrorHandler().throwQueryException();
+ parameterSpecifications = gen.getCollectedParameters();
}
catch ( RecognitionException e ) {
throw QuerySyntaxException.convert( e );
@@ -60,10 +63,10 @@
try {
try {
st = session.getBatcher().prepareStatement( sql );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator parameterSpecifications = this.parameterSpecifications.iterator();
int pos = 1;
- while ( paramSpecifications.hasNext() ) {
- final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
+ while ( parameterSpecifications.hasNext() ) {
+ final ParameterSpecification paramSpec = ( ParameterSpecification ) parameterSpecifications.next();
pos += paramSpec.bind( st, parameters, session, pos );
}
if ( selection != null ) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableDeleteExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -84,7 +84,7 @@
try {
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
- Iterator paramSpecifications = getWalker().getParameters().iterator();
+ Iterator paramSpecifications = getIdSelectParameterSpecifications().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/exec/MultiTableUpdateExecutor.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -109,7 +109,7 @@
try {
ps = session.getBatcher().prepareStatement( idInsertSelect );
int parameterStart = getWalker().getNumberOfParametersInSetClause();
- List allParams = getWalker().getParameters();
+ List allParams = getIdSelectParameterSpecifications();
Iterator whereParams = allParams.subList( parameterStart, allParams.size() ).iterator();
int sum = 1; // jdbc params are 1-based
while ( whereParams.hasNext() ) {
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/FromElement.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -3,8 +3,10 @@
import java.util.LinkedList;
import java.util.List;
+import java.util.ArrayList;
import org.hibernate.QueryException;
+import org.hibernate.param.ParameterSpecification;
import org.hibernate.engine.JoinSequence;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.CollectionProperties;
@@ -36,7 +38,7 @@
* Date: Dec 6, 2003<br>
* Time: 10:28:17 AM<br>
*/
-public class FromElement extends HqlSqlWalkerNode implements DisplayableNode {
+public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, ParameterContainer {
private static final Log log = LogFactory.getLog( FromElement.class );
private String className;
@@ -548,4 +550,23 @@
public boolean isDereferencedBySubclassProperty() {
return dereferencedBySubclassProperty;
}
+
+
+ // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private List embeddedParameters;
+
+ public void addEmbeddedParameter(ParameterSpecification specification) {
+ if ( embeddedParameters == null ) {
+ embeddedParameters = new ArrayList();
+ }
+ embeddedParameters.add( specification );
+ }
+
+ public boolean hasEmbeddedParameters() {
+ return embeddedParameters != null && ! embeddedParameters.isEmpty();
+ }
+
+ public ParameterSpecification[] getEmbeddedParameters() {
+ return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
+ }
}
Added: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/ParameterContainer.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,77 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.hql.ast.tree;
+
+import org.hibernate.param.ParameterSpecification;
+
+/**
+ * Currently this is needed in order to deal with {@link FromElement FromElements} which
+ * conatin "hidden" JDBC parameters from applying filters.
+ * <p/>
+ * Would love for this to go away, but that would require that Hibernate's
+ * internal {@link org.hibernate.engine.JoinSequence join handling} be able to either:<ul>
+ * <li>render the same AST structures</li>
+ * <li>render structures capable of being converted to these AST structures</li>
+ * </ul>
+ * <p/>
+ * In the interim, this allows us to at least treat these "hidden" parameters properly which is
+ * the most pressing need.
+ *
+ * @deprecated
+ * @author Steve Ebersole
+ */
+public interface ParameterContainer {
+ /**
+ * Set the renderable text of this node.
+ *
+ * @param text The renderable text
+ */
+ public void setText(String text);
+
+ /**
+ * Adds a parameter specification for a parameter encountered within this node. We use the term 'embedded' here
+ * because of the fact that the parameter was simply encountered as part of the node's text; it does not exist
+ * as part of a subtree as it might in a true AST.
+ *
+ * @param specification The generated specification.
+ */
+ public void addEmbeddedParameter(ParameterSpecification specification);
+
+ /**
+ * Determine whether this node contans embedded parameters. The implication is that
+ * {@link #getEmbeddedParameters()} is allowed to return null if this method returns false.
+ *
+ * @return True if this node contains embedded parameters; false otherwise.
+ */
+ public boolean hasEmbeddedParameters();
+
+ /**
+ * Retrieve all embedded parameter specifications.
+ *
+ * @return All embedded parameter specifications; may return null.
+ * @see #hasEmbeddedParameters()
+ */
+ public ParameterSpecification[] getEmbeddedParameters();
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/SqlFragment.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -1,14 +1,41 @@
-// $Id$
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
package org.hibernate.hql.ast.tree;
+import java.util.List;
+import java.util.ArrayList;
+
import org.hibernate.sql.JoinFragment;
+import org.hibernate.param.ParameterSpecification;
/**
* Represents an SQL fragment in the AST.
*
- * @author josh Dec 5, 2004 9:01:52 AM
+ * @author josh
*/
-public class SqlFragment extends Node {
+public class SqlFragment extends Node implements ParameterContainer {
private JoinFragment joinFragment;
private FromElement fromElement;
@@ -27,4 +54,23 @@
public FromElement getFromElement() {
return fromElement;
}
+
+
+ // ParameterContainer impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ private List embeddedParameters;
+
+ public void addEmbeddedParameter(ParameterSpecification specification) {
+ if ( embeddedParameters == null ) {
+ embeddedParameters = new ArrayList();
+ }
+ embeddedParameters.add( specification );
+ }
+
+ public boolean hasEmbeddedParameters() {
+ return embeddedParameters != null && ! embeddedParameters.isEmpty();
+ }
+
+ public ParameterSpecification[] getEmbeddedParameters() {
+ return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
+ }
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/JoinProcessor.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -4,22 +4,29 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
-import java.util.Collections;
import java.util.List;
+import java.util.StringTokenizer;
+import java.util.Collection;
import org.hibernate.AssertionFailure;
+import org.hibernate.param.DynamicFilterParameterSpecification;
+import org.hibernate.type.Type;
+import org.hibernate.impl.FilterImpl;
+import org.hibernate.dialect.Dialect;
import org.hibernate.engine.JoinSequence;
+import org.hibernate.engine.QueryParameters;
import org.hibernate.hql.antlr.SqlTokenTypes;
-import org.hibernate.hql.ast.QueryTranslatorImpl;
+import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.hql.ast.tree.FromClause;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.DotNode;
+import org.hibernate.hql.ast.tree.ParameterContainer;
+import org.hibernate.hql.classic.ParserHelper;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.util.ArrayHelper;
-import antlr.ASTFactory;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -34,18 +41,17 @@
private static final Log log = LogFactory.getLog( JoinProcessor.class );
- private QueryTranslatorImpl queryTranslatorImpl;
- private SyntheticAndFactory andFactory;
+ private final HqlSqlWalker walker;
+ private final SyntheticAndFactory syntheticAndFactory;
/**
* Constructs a new JoinProcessor.
*
- * @param astFactory The factory for AST node creation.
- * @param queryTranslatorImpl The query translator.
+ * @param walker The walker to which we are bound, giving us access to needed resources.
*/
- public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
- this.andFactory = new SyntheticAndFactory( astFactory );
- this.queryTranslatorImpl = queryTranslatorImpl;
+ public JoinProcessor(HqlSqlWalker walker) {
+ this.walker = walker;
+ this.syntheticAndFactory = new SyntheticAndFactory( walker );
}
/**
@@ -69,7 +75,7 @@
}
}
- public void processJoins(QueryNode query, boolean inSubquery) {
+ public void processJoins(QueryNode query) {
final FromClause fromClause = query.getFromClause();
final List fromElements;
@@ -108,22 +114,21 @@
log.trace( "forcing inclusion of extra joins [alias=" + alias + ", containsTableAlias=" + containsTableAlias + "]" );
return true;
}
- boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
+ boolean shallowQuery = walker.isShallowQuery();
boolean includeSubclasses = fromElement.isIncludeSubclasses();
boolean subQuery = fromClause.isSubQuery();
return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
}
}
);
- addJoinNodes( query, join, fromElement, inSubquery );
+ addJoinNodes( query, join, fromElement );
}
}
- private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement, boolean inSubquery) {
- // Generate FROM and WHERE fragments for the from element.
+ private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
JoinFragment joinFragment = join.toJoinFragment(
- inSubquery ? Collections.EMPTY_MAP : queryTranslatorImpl.getEnabledFilters(),
+ walker.getEnabledFilters(),
fromElement.useFromFragment() || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
fromElement.getWithClauseFragment(),
fromElement.getWithClauseJoinAlias()
@@ -143,13 +148,24 @@
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
- String fromFragment = processFromFragment( frag, join );
+ String fromFragment = processFromFragment( frag, join ).trim();
if ( log.isDebugEnabled() ) {
log.debug( "Using FROM fragment [" + fromFragment + "]" );
}
- fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement.
+ processDynamicFilterParameters(
+ fromFragment,
+ fromElement,
+ walker
+ );
}
- andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement );
+
+ syntheticAndFactory.addWhereFragment(
+ joinFragment,
+ whereFrag,
+ query,
+ fromElement,
+ walker
+ );
}
private String processFromFragment(String frag, JoinSequence join) {
@@ -161,4 +177,56 @@
return fromFragment;
}
+ public static void processDynamicFilterParameters(
+ final String sqlFragment,
+ final ParameterContainer container,
+ final HqlSqlWalker walker) {
+ if ( walker.getEnabledFilters().isEmpty()
+ && ( ! hasDynamicFilterParam( sqlFragment ) )
+ && ( ! ( hasCollectionFilterParam( sqlFragment ) ) ) ) {
+ return;
+ }
+
+ Dialect dialect = walker.getSessionFactoryHelper().getFactory().getDialect();
+ String symbols = new StringBuffer().append( ParserHelper.HQL_SEPARATORS )
+ .append( dialect.openQuote() )
+ .append( dialect.closeQuote() )
+ .toString();
+ StringTokenizer tokens = new StringTokenizer( sqlFragment, symbols, true );
+ StringBuffer result = new StringBuffer();
+
+ while ( tokens.hasMoreTokens() ) {
+ final String token = tokens.nextToken();
+ if ( token.startsWith( ParserHelper.HQL_VARIABLE_PREFIX ) ) {
+ final String filterParameterName = token.substring( 1 );
+ final String[] parts = QueryParameters.parseFilterParameterName( filterParameterName );
+ final FilterImpl filter = ( FilterImpl ) walker.getEnabledFilters().get( parts[0] );
+ final Object value = filter.getParameter( parts[1] );
+ final Type type = filter.getFilterDefinition().getParameterType( parts[1] );
+ final String typeBindFragment = StringHelper.join(
+ ",",
+ ArrayHelper.fillArray( "?", type.getColumnSpan( walker.getSessionFactoryHelper().getFactory() ) )
+ );
+ final String bindFragment = ( value != null && Collection.class.isInstance( value ) )
+ ? StringHelper.join( ",", ArrayHelper.fillArray( typeBindFragment, ( ( Collection ) value ).size() ) )
+ : typeBindFragment;
+ result.append( bindFragment );
+ container.addEmbeddedParameter( new DynamicFilterParameterSpecification( parts[0], parts[1], type ) );
+ }
+ else {
+ result.append( token );
+ }
+ }
+
+ container.setText( result.toString() );
+ }
+
+ private static boolean hasDynamicFilterParam(String sqlFragment) {
+ return sqlFragment.indexOf( ParserHelper.HQL_VARIABLE_PREFIX ) < 0;
+ }
+
+ private static boolean hasCollectionFilterParam(String sqlFragment) {
+ return sqlFragment.indexOf( "?" ) < 0;
+ }
+
}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/util/SyntheticAndFactory.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -2,18 +2,20 @@
package org.hibernate.hql.ast.util;
import java.util.Map;
-import java.util.StringTokenizer;
import org.hibernate.hql.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.RestrictableStatement;
import org.hibernate.hql.ast.tree.SqlFragment;
+import org.hibernate.hql.ast.tree.Node;
+import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
+import org.hibernate.type.Type;
+import org.hibernate.param.CollectionFilterKeyParameterSpecification;
-import antlr.ASTFactory;
import antlr.collections.AST;
import org.apache.commons.logging.Log;
@@ -27,27 +29,36 @@
public class SyntheticAndFactory implements HqlSqlTokenTypes {
private static final Log log = LogFactory.getLog( SyntheticAndFactory.class );
- private ASTFactory astFactory;
+ private HqlSqlWalker hqlSqlWalker;
private AST thetaJoins;
private AST filters;
- public SyntheticAndFactory(ASTFactory astFactory) {
- this.astFactory = astFactory;
+ public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) {
+ this.hqlSqlWalker = hqlSqlWalker;
}
- public void addWhereFragment(JoinFragment joinFragment, String whereFragment, QueryNode query, FromElement fromElement) {
+ private Node create(int tokenType, String text) {
+ return ( Node ) ASTUtil.create( hqlSqlWalker.getASTFactory(), tokenType, text );
+ }
+ public void addWhereFragment(
+ JoinFragment joinFragment,
+ String whereFragment,
+ QueryNode query,
+ FromElement fromElement,
+ HqlSqlWalker hqlSqlWalker) {
if ( whereFragment == null ) {
return;
}
+ if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
+ return;
+ }
+
whereFragment = whereFragment.trim();
if ( StringHelper.isEmpty( whereFragment ) ) {
return;
}
- else if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
- return;
- }
// Forcefully remove leading ands from where fragments; the grammar will
// handle adding them
@@ -55,12 +66,36 @@
whereFragment = whereFragment.substring( 4 );
}
- if ( log.isDebugEnabled() ) log.debug( "Using WHERE fragment [" + whereFragment + "]" );
+ if ( log.isDebugEnabled() ) {
+ log.debug( "Using unprocessed WHERE-fragment [" + whereFragment + "]");
+ }
- SqlFragment fragment = ( SqlFragment ) ASTUtil.create( astFactory, SQL_TOKEN, whereFragment );
+ SqlFragment fragment = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
fragment.setJoinFragment( joinFragment );
fragment.setFromElement( fromElement );
+ if ( hqlSqlWalker.isFilter() ) {
+ if ( whereFragment.indexOf( '?' ) >= 0 ) {
+ Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
+ .requireQueryableCollection( hqlSqlWalker.getCollectionFilterRole() )
+ .getKeyType();
+ CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
+ hqlSqlWalker.getCollectionFilterRole(),
+ collectionFilterKeyType,
+ 0
+ );
+ fragment.addEmbeddedParameter( paramSpec );
+ }
+ }
+
+ JoinProcessor.processDynamicFilterParameters(
+ whereFragment,
+ fragment,
+ hqlSqlWalker
+ );
+
+ log.debug( "Using processed WHERE-fragment [" + fragment.getText() + "]" );
+
// Filter conditions need to be inserted before the HQL where condition and the
// theta join node. This is because org.hibernate.loader.Loader binds the filter parameters first,
// then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
@@ -69,11 +104,11 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// Create a new FILTERS node as a parent of all filters
- filters = astFactory.create( FILTERS, "{filter conditions}" );
+ filters = create( FILTERS, "{filter conditions}" );
// Put the FILTERS node before the HQL condition and theta joins
ASTUtil.insertChild( where, filters );
}
-
+
// add the current fragment to the FILTERS node
filters.addChild( fragment );
}
@@ -82,7 +117,7 @@
// Find or create the WHERE clause
AST where = query.getWhereClause();
// Create a new THETA_JOINS node as a parent of all filters
- thetaJoins = astFactory.create( THETA_JOINS, "{theta joins}" );
+ thetaJoins = create( THETA_JOINS, "{theta joins}" );
// Put the THETA_JOINS node before the HQL condition, after the filters.
if (filters==null) {
ASTUtil.insertChild( where, thetaJoins );
@@ -91,14 +126,18 @@
ASTUtil.insertSibling( thetaJoins, filters );
}
}
-
+
// add the current fragment to the THETA_JOINS node
thetaJoins.addChild(fragment);
}
}
- public void addDiscriminatorWhereFragment(RestrictableStatement statement, Queryable persister, Map enabledFilters, String alias) {
+ public void addDiscriminatorWhereFragment(
+ RestrictableStatement statement,
+ Queryable persister,
+ Map enabledFilters,
+ String alias) {
String whereFragment = persister.filterFragment( alias, enabledFilters ).trim();
if ( "".equals( whereFragment ) ) {
return;
@@ -118,13 +157,19 @@
// At some point we probably want to apply an additional grammar to
// properly tokenize this where fragment into constituent parts
// focused on the operators embedded within the fragment.
- AST discrimNode = astFactory.create( SQL_TOKEN, whereFragment );
+ SqlFragment discrimNode = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
+ JoinProcessor.processDynamicFilterParameters(
+ whereFragment,
+ discrimNode,
+ hqlSqlWalker
+ );
+
if ( statement.getWhereClause().getNumberOfChildren() == 0 ) {
statement.getWhereClause().setFirstChild( discrimNode );
}
else {
- AST and = astFactory.create( AND, "{and}" );
+ AST and = create( AND, "{and}" );
AST currentFirstChild = statement.getWhereClause().getFirstChild();
and.setFirstChild( discrimNode );
and.addChild( currentFirstChild );
Modified: core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/loader/hql/QueryLoader.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -483,8 +483,8 @@
final QueryParameters queryParameters,
final int startIndex,
final SessionImplementor session) throws SQLException {
- int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
- List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
+ int position = startIndex;
+ List parameterSpecs = queryTranslator.getCollectedParameterSpecifications();
Iterator itr = parameterSpecs.iterator();
while ( itr.hasNext() ) {
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
Modified: core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/param/CollectionFilterKeyParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -8,13 +8,12 @@
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a collection-key
- * as part of a collection filter compilation.
+ * A specialized ParameterSpecification impl for dealing with a collection-key as part of a collection filter
+ * compilation.
*
* @author Steve Ebersole
*/
public class CollectionFilterKeyParameterSpecification implements ParameterSpecification {
-
private final String collectionRole;
private final Type keyType;
private final int queryParameterPosition;
@@ -34,6 +33,9 @@
this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
@@ -44,14 +46,23 @@
return keyType.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return keyType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// todo : throw exception?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "collection-filter-key=" + collectionRole;
}
Modified: core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/param/DynamicFilterParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -2,20 +2,17 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Iterator;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.type.Type;
/**
- * A specialized ParameterSpecification impl for dealing with a dynamic filter
- * parameters.
- * <p/>
- * Note: this class is currently not used. The ideal way to deal with dynamic filter
- * parameters for HQL would be to track them just as we do with other parameters
- * in the translator. However, the problem with that is that we currently do not
- * know the filters which actually apply to the query; we know the active/enabled ones,
- * but not the ones that actually "make it into" the resulting query.
+ * A specialized ParameterSpecification impl for dealing with a dynamic filter parameters.
+ *
+ * @see org.hibernate.Session#enableFilter(String)
*
* @author Steve Ebersole
*/
@@ -23,37 +20,65 @@
private final String filterName;
private final String parameterName;
private final Type definedParameterType;
- private final int queryParameterPosition;
+ /**
+ * Constructs a parameter specification for a particular filter parameter.
+ *
+ * @param filterName The name of the filter
+ * @param parameterName The name of the parameter
+ * @param definedParameterType The paremeter type specified on the filter metadata
+ */
public DynamicFilterParameterSpecification(
String filterName,
String parameterName,
- Type definedParameterType,
- int queryParameterPosition) {
+ Type definedParameterType) {
this.filterName = filterName;
this.parameterName = parameterName;
this.definedParameterType = definedParameterType;
- this.queryParameterPosition = queryParameterPosition;
}
+ /**
+ * {@inheritDoc}
+ */
public int bind(
PreparedStatement statement,
QueryParameters qp,
SessionImplementor session,
- int position) throws SQLException {
- Object value = qp.getFilteredPositionalParameterValues()[queryParameterPosition];
- definedParameterType.nullSafeSet( statement, value, position, session );
- return definedParameterType.getColumnSpan( session.getFactory() );
+ int start) throws SQLException {
+ final int columnSpan = definedParameterType.getColumnSpan( session.getFactory() );
+ final Object value = session.getFilterParameterValue( filterName + '.' + parameterName );
+ if ( Collection.class.isInstance( value ) ) {
+ int positions = 0;
+ Iterator itr = ( ( Collection ) value ).iterator();
+ while ( itr.hasNext() ) {
+ definedParameterType.nullSafeSet( statement, itr.next(), start + positions, session );
+ positions += columnSpan;
+ }
+ return positions;
+ }
+ else {
+ definedParameterType.nullSafeSet( statement, value, start, session );
+ return columnSpan;
+ }
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return definedParameterType;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
- // todo : throw exception?
+ // todo : throw exception? maybe warn if not the same?
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "dynamic-filter={filterName=" + filterName + ",paramName=" + parameterName + "}";
}
Modified: core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/param/NamedParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -9,14 +9,20 @@
import java.sql.SQLException;
/**
- * Relates to an explicit query named-parameter.
+ * Parameter bind specification for an explicit named parameter.
*
* @author Steve Ebersole
*/
public class NamedParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
-
private final String name;
+ /**
+ * Constructs a named parameter bind specification.
+ *
+ * @param sourceLine See {@link #getSourceLine()}
+ * @param sourceColumn See {@link #getSourceColumn()}
+ * @param name The named parameter name.
+ */
public NamedParameterSpecification(int sourceLine, int sourceColumn, String name) {
super( sourceLine, sourceColumn );
this.name = name;
@@ -39,10 +45,18 @@
return typedValue.getType().getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "name=" + name + ", expectedType=" + getExpectedType();
}
+ /**
+ * Getter for property 'name'.
+ *
+ * @return Value for property 'name'.
+ */
public String getName() {
return name;
}
Modified: core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/param/PositionalParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -9,14 +9,20 @@
import java.sql.SQLException;
/**
- * Relates to an explicit query positional (or ordinal) parameter.
+ * Parameter bind specification for an explicit positional (or ordinal) parameter.
*
* @author Steve Ebersole
*/
public class PositionalParameterSpecification extends AbstractExplicitParameterSpecification implements ParameterSpecification {
-
private final int hqlPosition;
+ /**
+ * Constructs a position/ordinal parameter bind specification.
+ *
+ * @param sourceLine See {@link #getSourceLine()}
+ * @param sourceColumn See {@link #getSourceColumn()}
+ * @param hqlPosition The position in the source query, relative to the other source positional parameters.
+ */
public PositionalParameterSpecification(int sourceLine, int sourceColumn, int hqlPosition) {
super( sourceLine, sourceColumn );
this.hqlPosition = hqlPosition;
@@ -40,10 +46,18 @@
return type.getColumnSpan( session.getFactory() );
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "ordinal=" + hqlPosition + ", expectedType=" + getExpectedType();
}
+ /**
+ * Getter for property 'hqlPosition'.
+ *
+ * @return Value for property 'hqlPosition'.
+ */
public int getHqlPosition() {
return hqlPosition;
}
Modified: core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/src/org/hibernate/param/VersionTypeSeedParameterSpecification.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -11,20 +11,24 @@
import java.sql.SQLException;
/**
- * Implementation of VersionTypeSeedParameterSpecification.
+ * Parameter bind specification used for optimisitc lock version seeding (from insert statements).
*
* @author Steve Ebersole
*/
public class VersionTypeSeedParameterSpecification implements ParameterSpecification {
-
private VersionType type;
+ /**
+ * Constructs a version seed parameter bind specification.
+ *
+ * @param type The version type.
+ */
public VersionTypeSeedParameterSpecification(VersionType type) {
this.type = type;
}
/**
- * @see org.hibernate.param.ParameterSpecification#bind
+ * {@inheritDoc}
*/
public int bind(PreparedStatement statement, QueryParameters qp, SessionImplementor session, int position)
throws SQLException {
@@ -32,14 +36,23 @@
return 1;
}
+ /**
+ * {@inheritDoc}
+ */
public Type getExpectedType() {
return type;
}
+ /**
+ * {@inheritDoc}
+ */
public void setExpectedType(Type expectedType) {
// expected type is intrinsic here...
}
+ /**
+ * {@inheritDoc}
+ */
public String renderDisplayInfo() {
return "version-seed, type=" + type;
}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01 19:03:53 UTC (rev 15239)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/DynamicFilterTest.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -10,26 +10,26 @@
import java.util.Set;
import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
-import org.hibernate.junit.functional.FunctionalTestCase;
-import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Criteria;
+import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.engine.SessionImplementor;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.entry.CollectionCacheEntry;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
-import org.hibernate.criterion.Expression;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.impl.SessionFactoryImpl;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Property;
+import org.hibernate.criterion.Subqueries;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
import org.hibernate.persister.collection.CollectionPersister;
-import org.hibernate.test.TestCase;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
/**
@@ -39,8 +39,6 @@
*/
public class DynamicFilterTest extends FunctionalTestCase {
- private Log log = LogFactory.getLog( DynamicFilterTest.class );
-
public DynamicFilterTest(String testName) {
super( testName );
}
@@ -79,6 +77,7 @@
testData.prepare();
Session session = openSession();
+ long ts = ( ( SessionImplementor ) session ).getTimestamp();
// Force a collection into the second level cache, with its non-filtered elements
Salesperson sp = ( Salesperson ) session.load( Salesperson.class, testData.steveId );
@@ -93,6 +92,7 @@
session.close();
session = openSession();
+ ts = ( ( SessionImplementor ) session ).getTimestamp();
session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
sp = ( Salesperson ) session.createQuery( "from Salesperson as s where s.id = :id" )
.setLong( "id", testData.steveId.longValue() )
@@ -152,7 +152,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HQL test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting HQL filter tests" );
TestData testData = new TestData();
testData.prepare();
@@ -162,13 +161,11 @@
session.enableFilter( "effectiveDate" )
.setParameter( "asOfDate", testData.lastMonth.getTime() );
- log.info( "HQL against Salesperson..." );
List results = session.createQuery( "select s from Salesperson as s left join fetch s.orders" ).list();
assertTrue( "Incorrect filtered HQL result count [" + results.size() + "]", results.size() == 1 );
Salesperson result = ( Salesperson ) results.get( 0 );
assertTrue( "Incorrect collectionfilter count", result.getOrders().size() == 1 );
- log.info( "HQL against Product..." );
results = session.createQuery( "from Product as p where p.stockNumber = ?" ).setInteger( 0, 124 ).list();
assertTrue( results.size() == 1 );
@@ -180,7 +177,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Criteria-query test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting Criteria-query filter tests" );
TestData testData = new TestData();
testData.prepare();
@@ -193,16 +189,14 @@
session.enableFilter( "effectiveDate" )
.setParameter( "asOfDate", testData.lastMonth.getTime() );
- log.info( "Criteria query against Salesperson..." );
List salespersons = session.createCriteria( Salesperson.class )
.setFetchMode( "orders", FetchMode.JOIN )
.list();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
assertEquals( "Incorrect order count", 1, ( ( Salesperson ) salespersons.get( 0 ) ).getOrders().size() );
- log.info( "Criteria query against Product..." );
List products = session.createCriteria( Product.class )
- .add( Expression.eq( "stockNumber", new Integer( 124 ) ) )
+ .add( Restrictions.eq( "stockNumber", new Integer( 124 ) ) )
.list();
assertEquals( "Incorrect product count", 1, products.size() );
@@ -210,18 +204,292 @@
testData.release();
}
+ public void testCriteriaControl() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ // the subquery...
+ DetachedCriteria subquery = DetachedCriteria.forClass( Salesperson.class )
+ .setProjection( Property.forName( "name" ) );
+
+ Session session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+
+ List result = session.createCriteria( Order.class )
+ .add( Subqueries.in( "steve", subquery ) )
+ .list();
+ assertEquals( 1, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testCriteriaSubqueryWithFilters() {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // Criteria-subquery test
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ DetachedCriteria salespersonSubquery = DetachedCriteria.forClass(Salesperson.class)
+ .add(Restrictions.eq("name", "steve"))
+ .setProjection(Property.forName("department"));
+
+ Criteria departmentsQuery = session.createCriteria(Department.class).add(Subqueries.propertyIn("id", salespersonSubquery));
+ List departments = departmentsQuery.list();
+
+ assertEquals("Incorrect department count", 1, departments.size());
+
+ session.enableFilter("region").setParameter("region", "Foobar");
+ departments = departmentsQuery.list();
+
+ assertEquals("Incorrect department count", 0, departments.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ DetachedCriteria lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
+ .add(Restrictions.ge("quantity", 1L))
+ .createCriteria("product")
+ .add(Restrictions.eq("name", "Acme Hair Gel"))
+ .setProjection(Property.forName("id"));
+
+ List orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ DetachedCriteria productSubquery = DetachedCriteria.forClass(Product.class)
+ .add(Restrictions.eq("name", "Acme Hair Gel"))
+ .setProjection(Property.forName("id"));
+
+ lineItemSubquery = DetachedCriteria.forClass(LineItem.class)
+ .add(Restrictions.ge("quantity", 1L))
+ .createCriteria("product")
+ .add(Subqueries.propertyIn("id", productSubquery))
+ .setProjection(Property.forName("id"));
+
+ orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
+
+ orders = session.createCriteria(Order.class)
+ .add(Subqueries.exists(lineItemSubquery))
+ .add(Restrictions.eq("buyer", "gavin"))
+ .list();
+
+ assertEquals("Incorrect orders count", 0, orders.size());
+
+ session.close();
+ testData.release();
+ }
+
+ public void testHQLSubqueryWithFilters() {
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ // HQL subquery with filters test
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ List departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
+
+ assertEquals("Incorrect department count", 1, departments.size());
+
+ session.enableFilter("region").setParameter("region", "Foobar");
+ departments = session.createQuery("select d from Department as d where d.id in (select s.department from Salesperson s where s.name = ?)").setString(0, "steve").list();
+
+ assertEquals("Incorrect department count", 0, departments.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+
+ List orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li, Product as p where p.id = li.product and li.quantity >= ? and p.name = ?) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.fourMonthsAgo.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = ?")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString(2, "gavin").list();
+
+ assertEquals("Incorrect orders count", 0, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= :quantity and li.product in (select p.id from Product p where p.name = :name)) and o.buyer = :buyer")
+ .setLong("quantity", 1L).setString("name", "Acme Hair Gel").setString("buyer", "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.enableFilter("region").setParameter("region", "APAC");
+ session.enableFilter("effectiveDate").setParameter("asOfDate", testData.lastMonth.getTime());
+
+ orders = session.createQuery("select o from Order as o where exists (select li.id from LineItem li where li.quantity >= ? and li.product in (select p.id from Product p where p.name = ?)) and o.buyer = :buyer")
+ .setLong(0, 1L).setString(1, "Acme Hair Gel").setString("buyer", "gavin").list();
+
+ assertEquals("Incorrect orders count", 1, orders.size());
+
+ session.close();
+ testData.release();
+ }
+
+ public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingPositionalParameter() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.beginTransaction();
+
+ final String queryString = "from Order o where ? in ( select sp.name from Salesperson sp )";
+
+ // first a control-group query
+ List result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 2, result.size() );
+
+ // now lets enable filters on Order...
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // now, lets additionally enable filter on Salesperson. First a valid one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // ... then a silly one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
+ result = session.createQuery( queryString ).setParameter( 0, "steve" ).list();
+ assertEquals( 0, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testFilterApplicationOnHqlQueryWithImplicitSubqueryContainingNamedParameter() {
+ TestData testData = new TestData();
+ testData.prepare();
+
+ Session session = openSession();
+ session.beginTransaction();
+
+ final String queryString = "from Order o where :salesPersonName in ( select sp.name from Salesperson sp )";
+
+ // first a control-group query
+ List result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 2, result.size() );
+
+ // now lets enable filters on Order...
+ session.enableFilter( "fulfilledOrders" ).setParameter( "asOfDate", testData.lastMonth.getTime() );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // now, lets additionally enable filter on Salesperson. First a valid one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "APAC" } );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 1, result.size() );
+
+ // ... then a silly one...
+ session.enableFilter( "regionlist" ).setParameterList( "regions", new String[] { "gamma quadrant" } );
+ result = session.createQuery( queryString ).setParameter( "salesPersonName", "steve" ).list();
+ assertEquals( 0, result.size() );
+
+ session.getTransaction().commit();
+ session.close();
+
+ testData.release();
+ }
+
+ public void testFiltersOnSimpleHqlDelete() {
+ Session session = openSession();
+ session.beginTransaction();
+ Salesperson sp = new Salesperson();
+ sp.setName( "steve" );
+ sp.setRegion( "NA" );
+ session.persist( sp );
+ Salesperson sp2 = new Salesperson();
+ sp2.setName( "john" );
+ sp2.setRegion( "APAC" );
+ session.persist( sp2 );
+ session.getTransaction().commit();
+ session.close();
+
+ session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "region" ).setParameter( "region", "NA" );
+ int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
+ assertEquals( 1, count );
+ session.delete( sp2 );
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ public void testFiltersOnMultiTableHqlDelete() {
+ Session session = openSession();
+ session.beginTransaction();
+ Salesperson sp = new Salesperson();
+ sp.setName( "steve" );
+ sp.setRegion( "NA" );
+ session.persist( sp );
+ Salesperson sp2 = new Salesperson();
+ sp2.setName( "john" );
+ sp2.setRegion( "APAC" );
+ session.persist( sp2 );
+ session.getTransaction().commit();
+ session.close();
+
+ session = openSession();
+ session.beginTransaction();
+ session.enableFilter( "region" ).setParameter( "region", "NA" );
+ int count = session.createQuery( "delete from Salesperson" ).executeUpdate();
+ assertEquals( 1, count );
+ session.delete( sp2 );
+ session.getTransaction().commit();
+ session.close();
+ }
+
+
public void testGetFilters() {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get() test
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting get() filter tests (eager assoc. fetching)." );
TestData testData = new TestData();
testData.prepare();
Session session = openSession();
session.enableFilter( "region" ).setParameter( "region", "APAC" );
- log.info( "Performing get()..." );
Salesperson salesperson = ( Salesperson ) session.get( Salesperson.class, testData.steveId );
assertNotNull( salesperson );
assertEquals( "Incorrect order count", 1, salesperson.getOrders().size() );
@@ -234,7 +502,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// one-to-many loading tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting one-to-many collection loader filter tests." );
TestData testData = new TestData();
testData.prepare();
@@ -242,7 +509,6 @@
session.enableFilter( "seniorSalespersons" )
.setParameter( "asOfDate", testData.lastMonth.getTime() );
- log.info( "Performing load of Department..." );
Department department = ( Department ) session.load( Department.class, testData.deptId );
Set salespersons = department.getSalespersons();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
@@ -255,7 +521,6 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// one-to-many loading tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- log.info( "Starting one-to-many collection loader filter tests." );
TestData testData = new TestData();
testData.prepare();
@@ -263,7 +528,6 @@
session.enableFilter( "regionlist" )
.setParameterList( "regions", new String[]{"LA", "APAC"} );
- log.debug( "Performing query of Salespersons" );
List salespersons = session.createQuery( "from Salesperson" ).list();
assertEquals( "Incorrect salesperson count", 1, salespersons.size() );
@@ -280,7 +544,7 @@
Product prod = ( Product ) session.createCriteria( Product.class )
.setResultTransformer( new DistinctRootEntityResultTransformer() )
- .add( Expression.eq( "id", testData.prod1Id ) )
+ .add( Restrictions.eq( "id", testData.prod1Id ) )
.uniqueResult();
assertNotNull( prod );
@@ -420,7 +684,7 @@
Session session = openSession();
List result = session.createCriteria( Product.class )
- .add( Expression.eq( "id", testData.prod1Id ) )
+ .add( Restrictions.eq( "id", testData.prod1Id ) )
.list();
Product prod = ( Product ) result.get( 0 );
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Basic.hbm.xml 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <class name="Person" table="FILTER_HQL_PERSON">
+ <id column="ID" name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" type="string"/>
+ <property name="sex" column="SEX_CODE" type="char"/>
+ <filter name="sex"/>
+ </class>
+</hibernate-mapping>
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/BasicFilteredBulkManipulationTest.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.Session;
+
+/**
+ * Tests for application of filters
+ *
+ * @author Steve Ebersole
+ */
+public class BasicFilteredBulkManipulationTest extends FunctionalTestCase {
+ public BasicFilteredBulkManipulationTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[]{
+ "filter/hql/filter-defs.hbm.xml",
+ "filter/hql/Basic.hbm.xml"
+ };
+ }
+
+ public void testBasicFilteredHqlDelete() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Person( "Steve", 'M' ) );
+ s.save( new Person( "Emmanuel", 'M' ) );
+ s.save( new Person( "Gail", 'F' ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
+ int count = s.createQuery( "delete Person" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBasicFilteredHqlUpdate() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Person( "Shawn", 'M' ) );
+ s.save( new Person( "Sally", 'F' ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character( 'M' ) );
+ int count = s.createQuery( "update Person p set p.name = 'Shawn'" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Customer.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class Customer extends User {
+ private String company;
+
+ protected Customer() {
+ super();
+ }
+
+ public Customer(String name, char sex, String username, String company) {
+ super( name, sex, username );
+ this.company = company;
+ }
+
+ public String getCompany() {
+ return company;
+ }
+
+ public void setCompany(String company) {
+ this.company = company;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Employee.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,53 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import java.util.Date;
+
+/**
+ * Leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class Employee extends User {
+ private Date hireDate;
+
+ protected Employee() {
+ super();
+ }
+
+ public Employee(String name, char sex, String username, Date hireDate) {
+ super( name, sex, username );
+ this.hireDate = hireDate;
+ }
+
+ public Date getHireDate() {
+ return hireDate;
+ }
+
+ public void setHireDate(Date hireDate) {
+ this.hireDate = hireDate;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Joined.hbm.xml 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <class name="Person" table="FILTER_HQL_JOINED_PERSON">
+ <id column="ID" name="id" type="long">
+ <generator class="increment"/>
+ </id>
+ <property name="name" type="string"/>
+ <property name="sex" column="SEX_CODE" type="char"/>
+ <joined-subclass name="User" table="FILTER_HQL_JOINED_USER">
+ <key column="USER_ID"/>
+ <property name="username" type="string"/>
+ <joined-subclass name="Employee" table="FILTER_HQL_JOINED_EMP">
+ <key column="EMP_ID"/>
+ <property name="hireDate" type="date"/>
+ </joined-subclass>
+ <joined-subclass name="Customer" table="FILTER_HQL_JOINED_CUST">
+ <key column="CUST_ID"/>
+ <property name="company" type="string"/>
+ </joined-subclass>
+ </joined-subclass>
+ <filter name="sex"/>
+ </class>
+</hibernate-mapping>
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/JoinedFilteredBulkManipulationTest.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,201 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+import java.util.Date;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.Session;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class JoinedFilteredBulkManipulationTest extends FunctionalTestCase {
+ public JoinedFilteredBulkManipulationTest(String string) {
+ super( string );
+ }
+
+ public String[] getMappings() {
+ return new String[]{
+ "filter/hql/filter-defs.hbm.xml",
+ "filter/hql/Joined.hbm.xml"
+ };
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteRoot() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete Person" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteNonLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete User" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlDeleteLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "delete Employee" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateRoot() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update Person p set p.name = '<male>'" ).executeUpdate();
+ assertEquals( 2, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateNonLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update User u set u.username = :un where u.name = :n" )
+ .setString( "un", "charlie" )
+ .setString( "n", "Wanda" )
+ .executeUpdate();
+ assertEquals( 0, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testFilteredJoinedSubclassHqlUpdateLeaf() {
+ Session s = openSession();
+ s.beginTransaction();
+ s.save( new Employee( "John", 'M', "john", new Date() ) );
+ s.save( new Employee( "Jane", 'F', "jane", new Date() ) );
+ s.save( new Customer( "Charlie", 'M', "charlie", "Acme" ) );
+ s.save( new Customer( "Wanda", 'F', "wanda", "ABC" ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.enableFilter( "sex" ).setParameter( "sexCode", new Character('M' ) );
+ int count = s.createQuery( "update Customer c set c.company = 'XYZ'" ).executeUpdate();
+ assertEquals( 1, count );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Person" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/Person.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,71 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Base of inheritence hierarchy
+ *
+ * @author Steve Ebersole
+ */
+public class Person {
+ private Long id;
+ private String name;
+ private char sex;
+
+ /**
+ * Used by persistence
+ */
+ protected Person() {
+ }
+
+ public Person(String name, char sex) {
+ this.name = name;
+ this.sex = sex;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ private void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public char getSex() {
+ return sex;
+ }
+
+ public void setSex(char sex) {
+ this.sex = sex;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/User.java 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,51 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.filter.hql;
+
+/**
+ * Non-leaf subclass
+ *
+ * @author Steve Ebersole
+ */
+public class User extends Person {
+ private String username;
+
+ protected User() {
+ super();
+ }
+
+ public User(String name, char sex, String username) {
+ super( name, sex );
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/filter/hql/filter-defs.hbm.xml 2008-10-01 19:32:11 UTC (rev 15240)
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ ~
+ -->
+
+<!DOCTYPE hibernate-mapping
+ SYSTEM
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
+
+<hibernate-mapping package="org.hibernate.test.filter.hql">
+ <filter-def name="sex" condition="SEX_CODE = :sexCode">
+ <filter-param name="sexCode" type="char"/>
+ </filter-def>
+</hibernate-mapping>
16 years, 3 months
Hibernate SVN: r15239 - in core/branches/Branch_3_2/test/org/hibernate/test: engine and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2008-10-01 15:03:53 -0400 (Wed, 01 Oct 2008)
New Revision: 15239
Added:
core/branches/Branch_3_2/test/org/hibernate/test/engine/
core/branches/Branch_3_2/test/org/hibernate/test/engine/query/
core/branches/Branch_3_2/test/org/hibernate/test/engine/query/ParameterParserTest.java
Log:
HHH-3216 : ParameterParser + escaped function call syntax
Added: core/branches/Branch_3_2/test/org/hibernate/test/engine/query/ParameterParserTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/engine/query/ParameterParserTest.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/engine/query/ParameterParserTest.java 2008-10-01 19:03:53 UTC (rev 15239)
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ *
+ */
+package org.hibernate.test.engine.query;
+
+import junit.framework.TestCase;
+
+import org.hibernate.engine.query.ParameterParser;
+
+/**
+ * Unit tests of the ParameterParser class
+ *
+ * @author Steve Ebersole
+ */
+public class ParameterParserTest extends TestCase {
+ public void testEscapeCallRecognition() {
+ assertTrue( ParameterParser.startsWithEscapeCallTemplate( "{ ? = call abc(?) }" ) );
+ assertFalse( ParameterParser.startsWithEscapeCallTemplate( "from User u where u.userName = ? and u.userType = 'call'" ) );
+ }
+}
16 years, 3 months