Author: hardy.ferentschik
Date: 2009-04-07 13:40:07 -0400 (Tue, 07 Apr 2009)
New Revision: 16270
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
Log:
HV-112
Parsing successfully some xml class level constraints
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaData.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -33,6 +33,12 @@
public interface BeanMetaData<T> {
/**
+ * Initalises the given meta data bean taken its current state into account. An instance
of <code>BeanMetaData</code>
+ * won't have any useful state information prior to calling this method.
+ */
+ void init();
+
+ /**
* @return the class of the bean.
*/
Class<T> getBeanClass();
@@ -43,16 +49,6 @@
BeanDescriptor 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();
Added:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java
(rev 0)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataCache.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -0,0 +1,46 @@
+// $Id:$
+/*
+* 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.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class BeanMetaDataCache {
+ /**
+ * A map for the meta data for each entity. The key is the class and the value the bean
meta data for this
+ * entity.
+ */
+ private static Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders
+ = new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>( 10 );
+
+ public static <T> BeanMetaDataImpl<T> getBeanMetaData(Class<T>
beanClass) {
+ if ( beanClass == null ) {
+ throw new IllegalArgumentException( "Class cannot be null" );
+ }
+ @SuppressWarnings("unchecked")
+ BeanMetaDataImpl<T> metadata = ( BeanMetaDataImpl<T> )
metadataProviders.get( beanClass );
+ return metadata;
+ }
+
+ static void addBeanMetaData(Class<?> beanClass, BeanMetaDataImpl<?>
metaData) {
+ metadataProviders.put( beanClass, metaData );
+ }
+}
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/BeanMetaDataImpl.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -26,10 +26,10 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.HashSet;
import javax.validation.BeanDescriptor;
import javax.validation.GroupSequence;
import javax.validation.PropertyDescriptor;
@@ -48,6 +48,7 @@
* instantiate an instance of this class and delegate the metadata extraction to it.
*
* @author Hardy Ferentschik
+ * @todo check the unchecked assignment warnings in this class
*/
public class BeanMetaDataImpl<T> implements BeanMetaData<T> {
@@ -70,16 +71,11 @@
private List<MetaConstraint<T, ?>> metaConstraintList = new
ArrayList<MetaConstraint<T, ?>>();
/**
- * List of cascaded fields.
+ * List of cascaded members.
*/
- private List<Field> cascadedFields = new ArrayList<Field>();
+ private List<Member> cascadedMembers = new ArrayList<Member>();
/**
- * List of cascaded methods.
- */
- private List<Method> cascadedMethods = new ArrayList<Method>();
-
- /**
* Maps field and method names to their <code>ElementDescriptorImpl</code>.
*/
private Map<String, PropertyDescriptor> propertyDescriptors = new
HashMap<String, PropertyDescriptor>();
@@ -97,9 +93,44 @@
public BeanMetaDataImpl(Class<T> beanClass, ConstraintHelper constraintHelper) {
this.beanClass = beanClass;
this.constraintHelper = constraintHelper;
+ }
+
+ public void init() {
createMetaData();
}
+ public Class<T> getBeanClass() {
+ return beanClass;
+ }
+
+ public BeanDescriptor getBeanDescriptor() {
+ return beanDescriptor;
+ }
+
+ public List<Member> getCascadedMembers() {
+ return cascadedMembers;
+ }
+
+ public List<MetaConstraint<T, ?>> geMetaConstraintList() {
+ return metaConstraintList;
+ }
+
+ public void addMetaConstraint(MetaConstraint<?, ?> metaConstraint) {
+ metaConstraintList.add( ( MetaConstraint<T, ?> ) metaConstraint );
+ }
+
+ public PropertyDescriptor getPropertyDescriptor(String property) {
+ return propertyDescriptors.get( property );
+ }
+
+ public List<Class<?>> getDefaultGroupSequence() {
+ return defaultGroupSequence;
+ }
+
+ public Set<PropertyDescriptor> getConstrainedProperties() {
+ return Collections.unmodifiableSet( new HashSet<PropertyDescriptor>(
propertyDescriptors.values() ) );
+ }
+
/**
* Create bean desciptor, find all classes/subclasses/interfaces which have to be taken
in consideration
* for this validator and create meta data.
@@ -187,7 +218,7 @@
}
if ( field.isAnnotationPresent( Valid.class ) ) {
ReflectionHelper.setAccessibility( field );
- cascadedFields.add( field );
+ cascadedMembers.add( field );
addPropertyDescriptorForMember( field );
}
}
@@ -205,7 +236,7 @@
}
if ( method.isAnnotationPresent( Valid.class ) ) {
ReflectionHelper.setAccessibility( method );
- cascadedMethods.add( method );
+ cascadedMembers.add( method );
addPropertyDescriptorForMember( method );
}
}
@@ -327,43 +358,4 @@
}
return metadata;
}
-
- public Class<T> getBeanClass() {
- return beanClass;
- }
-
- public BeanDescriptor 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 List<MetaConstraint<T, ?>> geMetaConstraintList() {
- return metaConstraintList;
- }
-
- public PropertyDescriptor getPropertyDescriptor(String property) {
- return propertyDescriptors.get( property );
- }
-
- public List<Class<?>> getDefaultGroupSequence() {
- return defaultGroupSequence;
- }
-
- public Set<PropertyDescriptor> getConstrainedProperties() {
- return Collections.unmodifiableSet( new
HashSet<PropertyDescriptor>(propertyDescriptors.values() ) );
- }
}
\ No newline at end of file
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java
===================================================================
---
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorFactoryImpl.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -19,9 +19,17 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
@@ -44,21 +52,27 @@
import org.hibernate.validation.util.LoggerFactory;
import org.hibernate.validation.util.ReflectionHelper;
+import org.hibernate.validation.util.annotationfactory.AnnotationDescriptor;
+import org.hibernate.validation.util.annotationfactory.AnnotationFactory;
import org.hibernate.validation.xml.BeanType;
import org.hibernate.validation.xml.ClassType;
import org.hibernate.validation.xml.ConstraintMappingsType;
+import org.hibernate.validation.xml.ConstraintType;
+import org.hibernate.validation.xml.ElementType;
import org.hibernate.validation.xml.FieldType;
import org.hibernate.validation.xml.GetterType;
+import org.hibernate.validation.xml.GroupsType;
/**
* @author Emmanuel Bernard
* @author Hardy Ferentschik
- * @todo Is this the right place to parse the mapping files?
*/
public class ValidatorFactoryImpl implements ValidatorFactory {
private static final Logger log = LoggerFactory.make();
private static final String VALIDATION_MAPPING_XSD =
"META-INF/validation-mapping-1.0.xsd";
+ private static final String MESSAGE_PARAM = "message";
+ private static final String GROUPS_PARAM = "groups";
private final MessageInterpolator messageInterpolator;
private final TraversableResolver traversableResolver;
@@ -66,13 +80,18 @@
private final ConstraintHelper constraintHelper = new ConstraintHelper();
private static final String PACKAGE_SEPERATOR = ".";
+ private final Map<Class<?>, Boolean> ignoreAnnotationDefaults = new
HashMap<Class<?>, Boolean>();
+ private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember =
new HashMap<Class<?>, List<Member>>();
+ private final List<Class<?>> ignoreAnnotationOnClass = new
ArrayList<Class<?>>();
+ private final Map<Class<?>, List<MetaConstraint<?, ?>>>
constraintMap = new HashMap<Class<?>, List<MetaConstraint<?,
?>>>();
+
public ValidatorFactoryImpl(ConfigurationState configurationState) {
this.messageInterpolator = configurationState.getMessageInterpolator();
this.constraintValidatorFactory = configurationState.getConstraintValidatorFactory();
this.traversableResolver = configurationState.getTraversableResolver();
parseMappingFiles( configurationState.getMappingStreams() );
-
+ initBeanMetaData();
}
/**
@@ -99,7 +118,7 @@
);
}
- public Schema getMappingSchema() {
+ private Schema getMappingSchema() {
URL schemaUrl = this.getClass().getClassLoader().getResource( VALIDATION_MAPPING_XSD
);
SchemaFactory sf = SchemaFactory.newInstance(
javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI );
Schema schema = null;
@@ -119,16 +138,13 @@
ConstraintMappingsType mappings = getValidationConfig( in );
String defaultPackage = mappings.getDefaultPackage();
for ( BeanType bean : mappings.getBean() ) {
- Class<?> beanClass = getBeanClass( bean.getClazz(), defaultPackage );
- if ( processedClasses.contains( beanClass ) ) {
- throw new ValidationException( beanClass.getName() + " has already be
configured in xml." );
- }
- boolean ignoreAnnotations = bean.isIgnoreAnnotations();
- @SuppressWarnings("unchecked")
- BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( beanClass,
constraintHelper );
- parseClassLevelOverrides( metaData, bean.getClassType() );
- parseFieldLevelOverrides( metaData, bean.getField() );
- parsePropertyLevelOverrides( metaData, bean.getGetter() );
+ Class<?> beanClass = getClass( bean.getClazz(), defaultPackage );
+ checkClassHasNotBeenProcessed( processedClasses, beanClass );
+ Boolean ignoreAnnotations = bean.isIgnoreAnnotations() == null ? false :
bean.isIgnoreAnnotations();
+ ignoreAnnotationDefaults.put( beanClass, ignoreAnnotations );
+ parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage );
+ parseFieldLevelOverrides( bean.getField() );
+ parsePropertyLevelOverrides( bean.getGetter() );
processedClasses.add( beanClass );
}
}
@@ -143,19 +159,226 @@
}
}
- private void parseFieldLevelOverrides(BeanMetaDataImpl<?> metaData,
List<FieldType> field) {
- //To change body of created methods use File | Settings | File Templates.
+ private void checkClassHasNotBeenProcessed(Set<Class<?>> processedClasses,
Class<?> beanClass) {
+ if ( processedClasses.contains( beanClass ) ) {
+ throw new ValidationException( beanClass.getName() + " has already be configured
in xml." );
+ }
}
- private void parsePropertyLevelOverrides(BeanMetaDataImpl<?> metaData,
List<GetterType> getter) {
- //To change body of created methods use File | Settings | File Templates.
+ private void parseFieldLevelOverrides(List<FieldType> fields) {
+ for ( FieldType field : fields ) {
+ boolean ignoreFieldAnnotation = field.isIgnoreAnnotations() == null ? false :
field.isIgnoreAnnotations();
+ }
}
- private void parseClassLevelOverrides(BeanMetaDataImpl<?> metaData, ClassType
classType) {
- //To change body of created methods use File | Settings | File Templates.
+ private void parsePropertyLevelOverrides(List<GetterType> getters) {
+ for ( GetterType getter : getters ) {
+ boolean ignoreGetterAnnotation = getter.isIgnoreAnnotations() == null ? false :
getter.isIgnoreAnnotations();
+ }
}
- private Class getBeanClass(String clazz, String defaultPackage) {
+ private void parseClassLevelOverrides(ClassType classType, Class<?> beanClass,
String defaultPackage) {
+ if ( classType == null ) {
+ return;
+ }
+ boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false :
classType.isIgnoreAnnotations();
+ if ( ignoreClassAnnotation ) {
+ ignoreAnnotationOnClass.add( beanClass );
+ }
+ for ( ConstraintType constraint : classType.getConstraint() ) {
+ MetaConstraint<?, ?> metaConstraint = createMetaConstraint( constraint,
beanClass, defaultPackage );
+ addMetaConstraint( beanClass, metaConstraint );
+ }
+ }
+
+ private void addMetaConstraint(Class<?> beanClass, MetaConstraint<?, ?>
metaConstraint) {
+ if ( constraintMap.containsKey( beanClass ) ) {
+ constraintMap.get( beanClass ).add( metaConstraint );
+ }
+ else {
+ List<MetaConstraint<?, ?>> constraintList = new
ArrayList<MetaConstraint<?, ?>>();
+ constraintList.add( metaConstraint );
+ constraintMap.put( beanClass, constraintList );
+ }
+ }
+
+ private <A extends Annotation, T> MetaConstraint<?, ?>
createMetaConstraint(ConstraintType constraint, Class<T> beanClass, String
defaultPackage) {
+ @SuppressWarnings("unchecked")
+ Class<A> annotationClass = ( Class<A> ) getClass(
constraint.getAnnotation(), defaultPackage );
+ AnnotationDescriptor<A> annotationDescriptor = new AnnotationDescriptor<A>(
annotationClass );
+
+ if ( constraint.getMessage() != null ) {
+ annotationDescriptor.setValue( MESSAGE_PARAM, constraint.getMessage() );
+ }
+ annotationDescriptor.setValue( GROUPS_PARAM, getGroups( constraint.getGroups(),
defaultPackage ) );
+
+ for ( ElementType elementType : constraint.getElement() ) {
+ String name = elementType.getName();
+ checkNameIsValid( name );
+ Class<?> returnType = getAnnotationParamterType( annotationClass, name );
+ Object elementValue = getElementValue( elementType, returnType );
+ annotationDescriptor.setValue( name, elementValue );
+ }
+
+ A annotation = AnnotationFactory.create( annotationDescriptor );
+ ConstraintDescriptorImpl<A> constraintDescriptor = new
ConstraintDescriptorImpl<A>(
+ annotation, new Class[] { }, constraintHelper
+ );
+ return new MetaConstraint<T, A>( beanClass, constraintDescriptor );
+ }
+
+ private void checkNameIsValid(String name) {
+ if ( MESSAGE_PARAM.equals( name ) || GROUPS_PARAM.equals( name ) ) {
+ throw new ValidationException( MESSAGE_PARAM + " and " + GROUPS_PARAM +
" are reserved paramter names." );
+ }
+ }
+
+ private <A extends Annotation> Class<?>
getAnnotationParamterType(Class<A> annotationClass, String name) {
+ Method m;
+ try {
+ m = annotationClass.getMethod( name );
+ }
+ catch ( NoSuchMethodException e ) {
+ throw new ValidationException( "Annotation of type " +
annotationClass.getName() + " does not contain a paramter " + name +
"." );
+ }
+ return m.getReturnType();
+ }
+
+ private Object getElementValue(ElementType elementType, Class<?> returnType) {
+ removeEmptyContentElements( elementType );
+
+ boolean isArray = returnType.isArray();
+ if ( !isArray ) {
+ if ( elementType.getContent().size() != 1 ) {
+ throw new ValidationException( "Attempt to specify an array where single value
is expected." );
+ }
+ return getSingleValue( elementType.getContent().get( 0 ), returnType );
+ }
+ else {
+ List<Object> values = new ArrayList<Object>();
+ for ( Serializable s : elementType.getContent() ) {
+ values.add( getSingleValue( s, returnType.getComponentType() ) );
+ }
+ return values.toArray( ( Object[] ) Array.newInstance( returnType.getComponentType(),
values.size() ) );
+ }
+ }
+
+ private void removeEmptyContentElements(ElementType elementType) {
+ List<Serializable> contentToDelete = new ArrayList<Serializable>();
+ for ( Serializable content : elementType.getContent() ) {
+ if ( content instanceof String && ( ( String ) content ).matches( "[\\n
].*" ) ) {
+ contentToDelete.add( content );
+ }
+ }
+ elementType.getContent().removeAll( contentToDelete );
+ }
+
+ private Object getSingleValue(Serializable serializable, Class<?> returnType) {
+ String value;
+ if ( serializable instanceof String ) {
+ value = ( String ) serializable;
+ }
+ else if ( serializable instanceof JAXBElement ) {
+ JAXBElement<?> elem = ( JAXBElement<?> ) serializable;
+ // this is safe due to the underlying schema
+ value = ( String ) elem.getValue();
+ }
+ else {
+ throw new ValidationException( "Unexpected paramter value" );
+ }
+
+ return convertStringToReturnType( returnType, value );
+ }
+
+ private Object convertStringToReturnType(Class<?> returnType, String value) {
+ Object returnValue;
+ if ( returnType.isPrimitive() && returnType.getName().equals(
byte.class.getName() ) ) {
+ try {
+ returnValue = Byte.parseByte( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid byte format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
short.class.getName() ) ) {
+ try {
+ returnValue = Short.parseShort( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid short format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
int.class.getName() ) ) {
+ try {
+ returnValue = Integer.parseInt( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid int format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
long.class.getName() ) ) {
+ try {
+ returnValue = Long.parseLong( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid long format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
float.class.getName() ) ) {
+ try {
+ returnValue = Float.parseFloat( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid float format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
double.class.getName() ) ) {
+ try {
+ returnValue = Double.parseDouble( value );
+ }
+ catch ( NumberFormatException e ) {
+ throw new ValidationException( "Invalid double format", e );
+ }
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
boolean.class.getName() ) ) {
+ returnValue = Boolean.parseBoolean( value );
+ }
+ else if ( returnType.isPrimitive() && returnType.getName().equals(
char.class.getName() ) ) {
+ if ( value.length() != 1 ) {
+ throw new ValidationException( "Invalid char value: " + value );
+ }
+ returnValue = value.charAt( 0 );
+ }
+ else if ( returnType.getName().equals( String.class.getName() ) ) {
+ returnValue = value;
+ }
+ else if ( returnType.getName().equals( Class.class.getName() ) ) {
+ try {
+ returnValue = ReflectionHelper.classForName( value, this.getClass() );
+ }
+ catch ( ClassNotFoundException e ) {
+ throw new ValidationException( "Unable to instantiate class: " + value );
+ }
+ }
+ else {
+ throw new ValidationException( "Invalid return type: " + returnType );
+ }
+ return returnValue;
+ }
+
+ private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
+ if ( groupsType == null ) {
+ return new Class[] { };
+ }
+
+ List<Class<?>> groupList = new ArrayList<Class<?>>();
+ for ( String groupClass : groupsType.getValue() ) {
+ groupList.add( getClass( groupClass, defaultPackage ) );
+ }
+ return groupList.toArray( new Class[groupList.size()] );
+ }
+
+ private Class<?> getClass(String clazz, String defaultPackage) {
String fullyQualifiedClass;
if ( isQualifiedClass( clazz ) ) {
fullyQualifiedClass = clazz;
@@ -193,4 +416,15 @@
}
return constraintMappings;
}
+
+ private void initBeanMetaData() {
+ for ( Map.Entry<Class<?>, List<MetaConstraint<?, ?>>> entry :
constraintMap.entrySet() ) {
+ BeanMetaDataImpl<?> metaData = new BeanMetaDataImpl( entry.getKey(),
constraintHelper );
+ for ( MetaConstraint<?, ?> metaConstraint : entry.getValue() ) {
+ metaData.addMetaConstraint( metaConstraint );
+ }
+ metaData.init();
+ BeanMetaDataCache.addBeanMetaData( entry.getKey(), metaData );
+ }
+ }
}
Modified:
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 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ValidatorImpl.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -27,7 +27,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import javax.validation.BeanDescriptor;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
@@ -73,13 +72,6 @@
private static final Class<?>[] DEFAULT_GROUP_ARRAY = new Class<?>[] {
Default.class };
/**
- * A map for the meta data for each entity. The key is the class and the value the bean
meta data for this
- * entity.
- */
- private static Map<Class<?>, BeanMetaDataImpl<?>> metadataProviders
- = new ConcurrentHashMap<Class<?>, BeanMetaDataImpl<?>>( 10 );
-
- /**
* Used to resolve the group execution order for a validate call.
*/
private GroupChainGenerator groupChainGenerator;
@@ -559,14 +551,11 @@
* {@inheritDoc}
*/
private <T> BeanMetaData<T> getBeanMetaData(Class<T> beanClass) {
- if ( beanClass == null ) {
- throw new IllegalArgumentException( "Class cannot be null" );
- }
- @SuppressWarnings("unchecked")
- BeanMetaDataImpl<T> metadata = ( BeanMetaDataImpl<T> )
metadataProviders.get( beanClass );
+ BeanMetaDataImpl<T> metadata = BeanMetaDataCache.getBeanMetaData( beanClass );
if ( metadata == null ) {
metadata = new BeanMetaDataImpl<T>( beanClass, constraintHelper );
- metadataProviders.put( beanClass, metadata );
+ metadata.init();
+ BeanMetaDataCache.addBeanMetaData( beanClass, metadata );
}
return metadata;
}
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserInformation.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -38,4 +38,10 @@
public abstract String message() default "User information is not
consistent.";
public abstract Class<?>[] groups() default { };
+
+ public abstract String stringParam() default "";
+
+ public abstract String[] stringArrayParam() default { };
+
+ public abstract int intParam() default 0;
}
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/ConsistentUserValidator.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -1,4 +1,4 @@
-// $Id:$
+// $Id$
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
@@ -29,6 +29,6 @@
}
public boolean isValid(User user, ConstraintValidatorContext constraintValidatorContext)
{
- return true;
+ return user.isConsistent();
}
}
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/User.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -5,6 +5,8 @@
*/
public class User {
+ private boolean isConsistent;
+
private String firstname;
//@NotNull(groups = Default.class)
@@ -37,4 +39,12 @@
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
+
+ public void setConsistent(boolean consistent) {
+ isConsistent = consistent;
+ }
+
+ public boolean isConsistent() {
+ return isConsistent;
+ }
}
\ No newline at end of file
Modified:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
===================================================================
---
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java 2009-04-07
17:40:07 UTC (rev 16270)
@@ -25,6 +25,7 @@
import static org.hibernate.validation.util.TestUtil.assertNumberOfViolations;
import static org.hibernate.validation.util.TestUtil.getValidator;
+import org.hibernate.validation.util.TestUtil;
/**
* @author Hardy Ferentschik
@@ -38,5 +39,10 @@
User user = new User();
Set<ConstraintViolation<User>> constraintViolations = validator.validate(
user );
assertNumberOfViolations( constraintViolations, 1 );
+ TestUtil.assertConstraintViolation( constraintViolations.iterator().next(),
"Message from xml" );
+
+ user.setConsistent( true );
+ constraintViolations = validator.validate( user );
+ assertNumberOfViolations( constraintViolations, 0 );
}
}
Property changes on:
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/engine/xml/XmlConfigurationTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified:
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml
===================================================================
---
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-07
16:31:07 UTC (rev 16269)
+++
validator/trunk/hibernate-validator/src/test/resources/META-INF/validation/user-constraints.xml 2009-04-07
17:40:07 UTC (rev 16270)
@@ -8,13 +8,17 @@
<value>value0</value>
</group-sequence>
<constraint
annotation="org.hibernate.validation.engine.xml.ConsistentUserInformation">
- <message>message0</message>
+ <message>Message from xml</message>
<groups>
+ <value>javax.validation.groups.Default</value>
+ </groups>
+ <element name="stringParam">foobar</element>
+ <element name="stringArrayParam">
<value>foo</value>
- </groups>
- <element name="name1">
+ <value>bar</value>
</element>
- <element name="name3">
+ <element name="intParam">
+ <value>42</value>
</element>
</constraint>
</class>
Modified: validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml
===================================================================
--- validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml 2009-04-07 16:31:07
UTC (rev 16269)
+++ validator/trunk/hibernate-validator/src/test/suite/unit-tests.xml 2009-04-07 17:40:07
UTC (rev 16270)
@@ -12,6 +12,7 @@
<package name="org.hibernate.validation.engine.groups"/>
<package name="org.hibernate.validation.engine.metadata"/>
<package
name="org.hibernate.validation.engine.validatorresolution"/>
+ <package name="org.hibernate.validation.engine.xml"/>
<package name="org.hibernate.validation.util"/>
<package
name="org.hibernate.validation.util.annotationfactory"/>
</packages>