KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > validator > ClassValidator


1 //$Id: ClassValidator.java,v 1.1 2005/05/27 08:58:53 epbernard Exp $
2
package org.hibernate.validator;
3
4 import java.beans.Introspector JavaDoc;
5 import java.lang.annotation.Annotation JavaDoc;
6 import java.lang.reflect.Method JavaDoc;
7 import java.util.ArrayList JavaDoc;
8 import java.util.HashMap JavaDoc;
9 import java.util.Iterator JavaDoc;
10 import java.util.List JavaDoc;
11 import java.util.Map JavaDoc;
12 import java.util.ResourceBundle JavaDoc;
13 import java.util.StringTokenizer JavaDoc;
14
15 import org.hibernate.MappingException;
16 import org.hibernate.mapping.PersistentClass;
17 import org.hibernate.mapping.Property;
18
19
20 /**
21  * Engine that take a bean and check every expressed annotation restrictions
22  *
23  * @author Gavin King
24  */

25 public class ClassValidator<T> {
26     
27     private final Class JavaDoc<T> beanClass;
28     private final List JavaDoc<Validator> beanValidators = new ArrayList JavaDoc<Validator>();
29     private final List JavaDoc<Validator> propertyValidators = new ArrayList JavaDoc<Validator>();
30     private final List JavaDoc<Method JavaDoc> propertyGetters = new ArrayList JavaDoc<Method JavaDoc>();
31     private final Map JavaDoc<Validator, String JavaDoc> messages = new HashMap JavaDoc<Validator, String JavaDoc>();
32     
33     private final ResourceBundle JavaDoc messageBundle;
34
35     /** create the validator engine for this bean type */
36     public ClassValidator(Class JavaDoc<T> beanClass) {
37         this(beanClass, null);
38     }
39
40     /**
41      * create the validator engine for a particular bean class, using a resource bundle
42      * for message rendering on violation *
43      */

44     public ClassValidator(Class JavaDoc<T> beanClass, ResourceBundle JavaDoc resourceBundle) {
45         this.beanClass = beanClass;
46         this.messageBundle = resourceBundle;
47         
48         Annotation JavaDoc[] classAnnotations = beanClass.getAnnotations();
49         for ( int i = 0; i < classAnnotations.length; i++ ) {
50             Annotation JavaDoc classAnnotation = classAnnotations[i];
51             Validator beanValidator = createValidator(classAnnotation);
52             if (beanValidator!=null) beanValidators.add(beanValidator);
53         }
54         
55         Method JavaDoc[] methods = beanClass.getMethods();
56         for ( int i = 0; i < methods.length; i++ ) {
57             Method JavaDoc method = methods[i];
58             Annotation JavaDoc[] methodAnnotations = method.getAnnotations();
59             for ( int j = 0; j < methodAnnotations.length; j++ ) {
60                 Annotation JavaDoc methodAnnotation = methodAnnotations[j];
61                 Validator propertyValidator = createValidator(methodAnnotation);
62                 if (propertyValidator!=null) {
63                     propertyValidators.add(propertyValidator);
64                     propertyGetters.add(method);
65                 }
66             }
67         }
68
69         //TODO test fields also
70
}
71
72
73 // private static final Set<String> methodNames = new HashSet<String>();
74
// static {
75
// methodNames.add("toString");
76
// methodNames.add("hashCode");
77
// methodNames.add("equals");
78
// methodNames.add("annotationType");
79
// }
80

81     private Validator createValidator(Annotation JavaDoc annotation) {
82         try {
83             ValidatorClass validatorClass = annotation.annotationType().getAnnotation(ValidatorClass.class);
84             if (validatorClass==null) return null;
85             Validator beanValidator = validatorClass.value().newInstance();
86             beanValidator.initialize(annotation);
87             String JavaDoc messageTemplate = (String JavaDoc) annotation.getClass()
88                     .getMethod("message", null)
89                     .invoke(annotation);
90             String JavaDoc message = replace(messageTemplate, annotation);
91             messages.put( beanValidator, message );
92             return beanValidator;
93         }
94         catch (Exception JavaDoc e) {
95             throw new IllegalArgumentException JavaDoc("could not instantiate ClassValidator", e);
96         }
97     }
98
99     /**
100      * apply constraints on a bean instance and return all the failures.
101      */

102     public InvalidValue[] getInvalidValues(T bean) {
103         if ( !beanClass.isInstance(bean) ) {
104             throw new IllegalArgumentException JavaDoc( "not an instance of: " + bean.getClass() );
105         }
106         
107         List JavaDoc<InvalidValue> results = new ArrayList JavaDoc<InvalidValue>();
108         
109         for ( int i=0; i < beanValidators.size(); i++ ) {
110             Validator validator = beanValidators.get(i);
111             if ( !validator.isValid(bean) ) {
112                 results.add( new InvalidValue( messages.get(validator), beanClass, null, bean, bean ) );
113             }
114         }
115         
116         for ( int i=0; i < propertyValidators.size(); i++ ) {
117             Method JavaDoc getter = propertyGetters.get(i);
118             Object JavaDoc value;
119             try {
120                 value = getter.invoke(bean);
121             }
122             catch (Exception JavaDoc e) {
123                 throw new IllegalStateException JavaDoc("could not get property value", e);
124             }
125             Validator validator = propertyValidators.get(i);
126             if ( !validator.isValid( value ) ) {
127                 String JavaDoc propertyName = getPropertyName( getter );
128                 results.add( new InvalidValue( messages.get(validator), beanClass, propertyName, value, bean ) );
129             }
130         }
131         
132         return results.toArray( new InvalidValue[results.size()] );
133     }
134
135     private static String JavaDoc getPropertyName(Method JavaDoc getter) {
136         String JavaDoc name = getter.getName();
137         if ( name.startsWith("is") ) {
138             name = name.substring(2);
139         }
140         else if ( name.startsWith("get") ) {
141             name = name.substring(3);
142         }
143         String JavaDoc propertyName = Introspector.decapitalize(name);
144         return propertyName;
145     }
146     
147     private String JavaDoc replace(String JavaDoc message, Annotation JavaDoc parameters) {
148         StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(message, "{}", true);
149         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
150         boolean escaped = false;
151         while ( tokens.hasMoreTokens() ) {
152             String JavaDoc token = tokens.nextToken();
153             if ( "{".equals(token) ) {
154                 escaped = true;
155             }
156             else if ( "}".equals(token) ) {
157                 escaped = false;
158             }
159             else if (!escaped) {
160                 buf.append(token);
161             }
162             else {
163                 Method JavaDoc member;
164                 try {
165                     member = parameters.getClass().getMethod(token, null);
166                 }
167                 catch (NoSuchMethodException JavaDoc nsfme) {
168                     member = null;
169                 }
170                 if ( member!=null ) {
171                     try {
172                         buf.append( member.invoke(parameters) );
173                     }
174                     catch (Exception JavaDoc e) {
175                         throw new IllegalArgumentException JavaDoc("could not render message", e);
176                     }
177                 }
178                 else if ( messageBundle!=null ) {
179                     String JavaDoc string = messageBundle.getString(token);
180                     if (string!=null) buf.append( string );
181                 }
182             }
183         }
184         return buf.toString();
185     }
186
187     /**
188      * apply the registred constraints rules on the hibernate metadata (to be applied on DB schema...)
189      * @param persistentClass hibernate metadata
190      */

191     public void apply(PersistentClass persistentClass) {
192         
193         Iterator JavaDoc<Validator> validators = beanValidators.iterator();
194         while ( validators.hasNext() ) {
195             Validator validator = validators.next();
196             if ( validator instanceof PersistentClassConstraint ) {
197                 ( (PersistentClassConstraint) validator ).apply(persistentClass);
198             }
199         }
200         
201         validators = propertyValidators.iterator();
202         Iterator JavaDoc<Method JavaDoc> getters = propertyGetters.iterator();
203         while ( validators.hasNext() ) {
204             Validator validator = validators.next();
205             String JavaDoc propertyName = getPropertyName( getters.next() );
206             if ( validator instanceof PropertyConstraint ) {
207                 try {
208                     Property property = persistentClass.getProperty( propertyName );
209                     ( (PropertyConstraint) validator ).apply(property);
210                 }
211                 catch (MappingException pnfe) {
212                     //do nothing
213
}
214             }
215         }
216         
217     }
218     
219 }
220
Popular Tags