KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > genmodel > GenValidationModel


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18 package org.apache.beehive.netui.compiler.genmodel;
19
20 import org.apache.beehive.netui.compiler.CompilerUtils;
21 import org.apache.beehive.netui.compiler.JpfLanguageConstants;
22 import org.apache.beehive.netui.compiler.MergedControllerAnnotation;
23 import org.apache.beehive.netui.compiler.Diagnostics;
24 import org.apache.beehive.netui.compiler.FatalCompileTimeException;
25 import org.apache.beehive.netui.compiler.model.FormBeanModel;
26 import org.apache.beehive.netui.compiler.model.validation.ValidationModel;
27 import org.apache.beehive.netui.compiler.model.validation.ValidatorConstants;
28 import org.apache.beehive.netui.compiler.model.validation.ValidatorRule;
29 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
30 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationValue;
31 import org.apache.beehive.netui.compiler.typesystem.declaration.ClassDeclaration;
32 import org.apache.beehive.netui.compiler.typesystem.declaration.MethodDeclaration;
33 import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
34 import org.apache.beehive.netui.compiler.typesystem.declaration.TypeDeclaration;
35 import org.apache.beehive.netui.compiler.typesystem.declaration.ParameterDeclaration;
36 import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType;
37 import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance;
38 import org.apache.beehive.netui.compiler.typesystem.type.ClassType;
39 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;
40 import org.apache.xmlbeans.XmlException;
41
42 import java.io.File JavaDoc;
43 import java.io.FileNotFoundException JavaDoc;
44 import java.io.FileOutputStream JavaDoc;
45 import java.io.IOException JavaDoc;
46 import java.io.PrintStream JavaDoc;
47 import java.util.Collection JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.List JavaDoc;
50 import java.util.Locale JavaDoc;
51 import java.util.Map JavaDoc;
52 import java.util.ArrayList JavaDoc;
53
54 public class GenValidationModel
55         extends ValidationModel
56         implements JpfLanguageConstants, ValidatorConstants
57 {
58     private static final String JavaDoc STRUTS_VALIDATION_PREFIX = "jpf-validation";
59     private static final ValidatorRuleFactory VALIDATOR_RULE_FACTORY = new DefaultValidatorRuleFactory();
60     
61     private GenStrutsApp _strutsApp;
62     private File JavaDoc _mergeFile;
63     private AnnotationProcessorEnvironment _env;
64
65
66     public GenValidationModel( ClassDeclaration jclass, GenStrutsApp strutsApp, AnnotationProcessorEnvironment env )
67             throws FatalCompileTimeException
68     {
69         MergedControllerAnnotation mca = strutsApp.getFlowControllerInfo().getMergedControllerAnnotation();
70         _strutsApp = strutsApp;
71         setValidatorVersion( mca.getValidatorVersion() );
72         addRulesFromBeans( jclass );
73         addRulesFromActions( jclass, mca );
74         addRulesFromClass( mca );
75         String JavaDoc mergeFileName = mca.getValidatorMerge();
76         _mergeFile = strutsApp.getMergeFile( mergeFileName );
77         _env = env;
78     }
79     
80     private void addRulesFromBeans( ClassDeclaration jclass )
81     {
82         //
83
// Read validation rules from public static inner classes (beans).
84
//
85
Collection JavaDoc innerTypes = CompilerUtils.getClassNestedTypes( jclass );
86         
87         for ( Iterator JavaDoc ii = innerTypes.iterator(); ii.hasNext(); )
88         {
89             TypeDeclaration innerType = ( TypeDeclaration ) ii.next();
90             if ( innerType instanceof ClassDeclaration
91                  && innerType.hasModifier( Modifier.PUBLIC )
92                  && innerType.hasModifier( Modifier.STATIC ) )
93             {
94                 addRulesFromBeanClass( ( ClassDeclaration ) innerType );
95             }
96         }
97     }
98     
99     private void addRulesFromBeanClass( ClassDeclaration beanClass )
100     {
101         Collection JavaDoc properties = CompilerUtils.getBeanProperties( beanClass, true );
102         
103         for ( Iterator JavaDoc ii = properties.iterator(); ii.hasNext(); )
104         {
105             CompilerUtils.BeanPropertyDeclaration property = ( CompilerUtils.BeanPropertyDeclaration ) ii.next();
106             MethodDeclaration getter = property.getGetter();
107             String JavaDoc propertyName = property.getPropertyName();
108             
109             if ( getter != null )
110             {
111                 //
112
// Parse validation annotations on each getter.
113
//
114
AnnotationInstance[] annotations = getter.getAnnotationInstances();
115                 
116                 if ( annotations != null )
117                 {
118                     List JavaDoc formNames = getFormBeanNames( beanClass );
119                     
120                     for ( Iterator JavaDoc j = formNames.iterator(); j.hasNext(); )
121                     {
122                         String JavaDoc formName = ( String JavaDoc ) j.next();
123                         
124                         for ( int i = 0; i < annotations.length; i++ )
125                         {
126                             AnnotationInstance ann = annotations[i];
127                             
128                             if ( CompilerUtils.isJpfAnnotation( ann, VALIDATABLE_PROPERTY_TAG_NAME ) )
129                             {
130                                 //
131
// Add field rules from the Jpf.ValidationLocaleRules annotation.
132
//
133
addRulesFromAnnotation( ann, formName, propertyName );
134                             }
135                         }
136                     }
137                 }
138             }
139         }
140     }
141     
142     
143     private void addRulesFromAnnotation( AnnotationInstance validationFieldAnn, String JavaDoc entityName, String JavaDoc propertyName )
144     {
145         //
146
// Add rules from the FieldValidationRules annotations in the "localeRules" member.
147
//
148
Collection JavaDoc localeRulesAnnotations =
149                 CompilerUtils.getAnnotationArray( validationFieldAnn, LOCALE_RULES_ATTR, false );
150         String JavaDoc displayName = CompilerUtils.getString( validationFieldAnn, DISPLAY_NAME_ATTR, true );
151         String JavaDoc displayNameKey = CompilerUtils.getString( validationFieldAnn, DISPLAY_NAME_KEY_ATTR, true );
152         RuleInfo ruleInfo = new RuleInfo( entityName, propertyName, displayName, displayNameKey );
153                 
154         
155         for ( Iterator JavaDoc ii = localeRulesAnnotations.iterator(); ii.hasNext(); )
156         {
157             AnnotationInstance ann = ( AnnotationInstance ) ii.next();
158             addFieldRules( ann, ruleInfo, false );
159         }
160         
161         addFieldRules( validationFieldAnn, ruleInfo, true );
162     }
163     
164     private void addRulesFromActions( ClassDeclaration jclass, MergedControllerAnnotation mca )
165     {
166         MethodDeclaration[] methods = CompilerUtils.getClassMethods( jclass, ACTION_TAG_NAME );
167         
168         for ( int i = 0; i < methods.length; i++ )
169         {
170             MethodDeclaration method = methods[i];
171             AnnotationInstance actionAnnotation = CompilerUtils.getAnnotation( method, ACTION_TAG_NAME );
172             assert actionAnnotation != null;
173             addRulesFromActionAnnotation( actionAnnotation, method.getSimpleName() );
174             
175             ParameterDeclaration[] parameters = method.getParameters();
176             if ( parameters.length > 0 )
177             {
178                 TypeInstance type = parameters[0].getType();
179                 
180                 if ( type instanceof ClassType )
181                 {
182                     ClassDeclaration classDecl = ( ( ClassType ) type ).getClassTypeDeclaration();
183                     if ( classDecl.getDeclaringType() == null ) addRulesFromBeanClass( classDecl );
184                 }
185             }
186         }
187         
188         
189         Collection JavaDoc simpleActions = mca.getSimpleActions();
190         
191         if ( simpleActions != null )
192         {
193             for ( Iterator JavaDoc ii = simpleActions.iterator(); ii.hasNext(); )
194             {
195                 AnnotationInstance simpleAction = ( AnnotationInstance ) ii.next();
196                 String JavaDoc actionName = CompilerUtils.getString( simpleAction, NAME_ATTR, true );
197                 assert actionName != null; //checker should enforce this.
198
addRulesFromActionAnnotation( simpleAction, actionName );
199             }
200         }
201     }
202     
203     private void addRulesFromActionAnnotation( AnnotationInstance actionAnnotation, String JavaDoc actionName )
204     {
205         Collection JavaDoc validatablePropertyAnnotations =
206                 CompilerUtils.getAnnotationArray( actionAnnotation, VALIDATABLE_PROPERTIES_ATTR, false );
207         
208         for ( Iterator JavaDoc ii = validatablePropertyAnnotations.iterator(); ii.hasNext(); )
209         {
210             AnnotationInstance validationFieldAnnotation = ( AnnotationInstance ) ii.next();
211             String JavaDoc propertyName = CompilerUtils.getString( validationFieldAnnotation, PROPERTY_NAME_ATTR, true );
212             assert propertyName != null; // TODO: checker must enforce this
213
assert ! propertyName.equals( "" ); // TODO: checker must enforce this
214

215             //
216
// Add the rules, and associate them with the action path ("/" + the action name).
217
//
218
String JavaDoc actionPath = '/' + actionName; // Struts validator needs the slash in front
219
addRulesFromAnnotation( validationFieldAnnotation, actionPath, propertyName );
220         }
221     }
222     
223     /**
224      * Returns a list of String names.
225      */

226     private List JavaDoc getFormBeanNames( TypeDeclaration beanType )
227     {
228         String JavaDoc actualType = CompilerUtils.getLoadableName( beanType );
229         List JavaDoc formBeans = _strutsApp.getFormBeansByActualType( actualType, null );
230         ArrayList JavaDoc formBeanNames = new ArrayList JavaDoc();
231
232         if ( formBeans == null )
233         {
234             String JavaDoc beanClassName = CompilerUtils.getFormClassName( beanType, _strutsApp.getEnv() );
235             String JavaDoc formName = _strutsApp.getFormNameForType( actualType, false );
236             FormBeanModel formBean = new FormBeanModel( formName, beanClassName, actualType, false, _strutsApp );
237             _strutsApp.addFormBean( formBean );
238             formBeanNames.add( formBean.getName() );
239         }
240         else
241         {
242             for ( Iterator JavaDoc i = formBeans.iterator(); i.hasNext(); )
243             {
244                 FormBeanModel formBeanModel = ( FormBeanModel ) i.next();
245                 formBeanNames.add( formBeanModel.getName() );
246             }
247         }
248
249         return formBeanNames;
250     }
251     
252     private void addRulesFromClass( MergedControllerAnnotation mca )
253     {
254         Collection JavaDoc validationBeanAnnotations = mca.getValidatableBeans();
255         
256         for ( Iterator JavaDoc ii = validationBeanAnnotations.iterator(); ii.hasNext(); )
257         {
258             AnnotationInstance validationBeanAnnotation = ( AnnotationInstance ) ii.next();
259             DeclaredType beanType = CompilerUtils.getDeclaredType( validationBeanAnnotation, TYPE_ATTR, true );
260             assert beanType != null; // checker should enforce this
261

262             Collection JavaDoc validationFieldAnnotations =
263                     CompilerUtils.getAnnotationArray( validationBeanAnnotation, VALIDATABLE_PROPERTIES_ATTR, false );
264             
265             for ( Iterator JavaDoc i2 = validationFieldAnnotations.iterator(); i2.hasNext(); )
266             {
267                 AnnotationInstance validationFieldAnnotation = ( AnnotationInstance ) i2.next();
268                 String JavaDoc propName = CompilerUtils.getString( validationFieldAnnotation, PROPERTY_NAME_ATTR, true );
269                 assert propName != null; // checker should enforce this
270
assert ! propName.equals( "" ); // TODO: get checker to enforce this
271

272                 //
273
// Add the rules. If the bean is derived from ActionForm, associate the rules with the *name* of
274
// the form; otherwise, associate them with the classname of the bean type.
275
//
276
List JavaDoc formNames = getFormBeanNames( CompilerUtils.getDeclaration( beanType ) );
277                 
278                 for ( Iterator JavaDoc j = formNames.iterator(); j.hasNext(); )
279                 {
280                     String JavaDoc formName = ( String JavaDoc ) j.next();
281                     addRulesFromAnnotation( validationFieldAnnotation, formName, propName );
282                 }
283             }
284         }
285     }
286     
287     /**
288      * Add field rules from either a Jpf.ValidationField or a Jpf.ValidationLocaleRules annotation.
289      */

290     private void addFieldRules( AnnotationInstance rulesContainerAnnotation, RuleInfo ruleInfo,
291                                 boolean applyToAllLocales )
292     {
293         //
294
// First parse the locale from the wrapper annotation. This will apply to all rules inside.
295
//
296
Locale JavaDoc locale = null;
297         
298         if ( ! applyToAllLocales )
299         {
300             String JavaDoc language = CompilerUtils.getString( rulesContainerAnnotation, LANGUAGE_ATTR, true );
301             
302             //
303
// If there's no language specified, then this rule will only apply for the default ruleset
304
// (i.e., if there are explicit rules for the requested locale, this rule will not be run).
305
//
306
if ( language != null )
307             {
308                 String JavaDoc country = CompilerUtils.getString( rulesContainerAnnotation, COUNTRY_ATTR, true );
309                 String JavaDoc variant = CompilerUtils.getString( rulesContainerAnnotation, VARIANT_ATTR, true );
310                 
311                 language = language.trim();
312                 if ( country != null ) country = country.trim();
313                 if ( variant != null ) variant = variant.trim();
314
315                 if ( country != null && variant != null ) locale = new Locale JavaDoc( language, country, variant );
316                 else if ( country != null ) locale = new Locale JavaDoc( language, country );
317                 else locale = new Locale JavaDoc( language );
318             }
319         }
320         
321         Map JavaDoc valuesPresent = rulesContainerAnnotation.getElementValues();
322         
323         for ( Iterator JavaDoc ii = valuesPresent.entrySet().iterator(); ii.hasNext(); )
324         {
325             Map.Entry JavaDoc entry = ( Map.Entry JavaDoc ) ii.next();
326             AnnotationValue value = ( AnnotationValue ) entry.getValue();
327             Object JavaDoc val = value.getValue();
328             
329             if ( val instanceof AnnotationInstance )
330             {
331                 addFieldRuleFromAnnotation( ruleInfo, ( AnnotationInstance ) val, locale, applyToAllLocales );
332             }
333             else if ( val instanceof List JavaDoc )
334             {
335                 List JavaDoc annotations = CompilerUtils.getAnnotationArray( value );
336                 
337                 for ( Iterator JavaDoc i3 = annotations.iterator(); i3.hasNext(); )
338                 {
339                     AnnotationInstance i = ( AnnotationInstance ) i3.next();
340                     addFieldRuleFromAnnotation( ruleInfo, i, locale, applyToAllLocales );
341                 }
342             }
343         }
344         
345         setEmpty( false ); // this ValidationModel is only "empty" if there are no rules.
346
}
347     
348     private void addFieldRuleFromAnnotation( RuleInfo ruleInfo, AnnotationInstance annotation, Locale JavaDoc locale,
349                                              boolean applyToAllLocales )
350     {
351         
352         ValidatorRule rule = getFieldRule( ruleInfo.getEntityName(), ruleInfo.getFieldName(), annotation );
353         
354         if ( rule != null )
355         {
356             if ( applyToAllLocales )
357             {
358                 addFieldRuleForAllLocales( ruleInfo, rule );
359             }
360             else
361             {
362                 addFieldRule( ruleInfo, rule, locale );
363             }
364         }
365     }
366     
367     private static ValidatorRule getFieldRule( String JavaDoc entityName, String JavaDoc propertyName, AnnotationInstance ruleAnnotation )
368     {
369         ValidatorRule rule = VALIDATOR_RULE_FACTORY.getFieldRule( entityName, propertyName, ruleAnnotation );
370         
371         if ( rule != null )
372         {
373             //
374
// message/message-key
375
//
376
rule.setMessage( CompilerUtils.getString( ruleAnnotation, MESSAGE_ATTR, true ) );
377             rule.setMessageKey( CompilerUtils.getString( ruleAnnotation, MESSAGE_KEY_ATTR, true ) );
378             rule.setBundle( CompilerUtils.getString( ruleAnnotation, BUNDLE_NAME_ATTR, true ) );
379             if ( rule.getMessage() != null ) assert rule.getMessageKey() == null; // TODO: checker should enforce
380

381             //
382
// args
383
//
384
addMessageArgs( rule, ruleAnnotation );
385         }
386         
387         return rule;
388     }
389
390     protected static void addMessageArgs( ValidatorRule rule, AnnotationInstance annotation )
391     {
392         List JavaDoc messageArgs =
393                 CompilerUtils.getAnnotationArray( annotation, MESSAGE_ARGS_ATTR, true );
394
395         if ( messageArgs != null )
396         {
397             int inferredPosition = 0;
398             for ( Iterator JavaDoc ii = messageArgs.iterator(); ii.hasNext(); )
399             {
400                 AnnotationInstance ann = ( AnnotationInstance ) ii.next();
401                 String JavaDoc arg = CompilerUtils.getString( ann, ARG_ATTR, true );
402                 String JavaDoc bundle = CompilerUtils.getString( ann, BUNDLE_NAME_ATTR, true );
403                 Integer JavaDoc position = CompilerUtils.getInteger( ann, POSITION_ATTR, true );
404
405                 if ( position == null )
406                 {
407                     position = new Integer JavaDoc( inferredPosition );
408                 }
409
410                 if ( arg != null )
411                 {
412                     rule.setArg( arg, false, bundle, position );
413                 }
414                 else
415                 {
416                     String JavaDoc argKey = CompilerUtils.getString( ann, ARG_KEY_ATTR, true );
417                     if ( argKey != null ) rule.setArg( argKey, true, bundle, position );
418                 }
419
420                 inferredPosition++;
421             }
422         }
423     }
424
425     protected String JavaDoc getHeaderComment( File JavaDoc mergeFile )
426             throws FatalCompileTimeException
427     {
428         return _strutsApp.getHeaderComment( mergeFile );
429     }
430
431     public void writeToFile()
432         throws FileNotFoundException JavaDoc, XmlException, IOException JavaDoc, FatalCompileTimeException
433     {
434         String JavaDoc outputFile =
435                 CompilerUtils.getWebBuildRoot( _env ) + _strutsApp.getOutputFileURI( STRUTS_VALIDATION_PREFIX );
436         PrintStream JavaDoc printStream = new PrintStream JavaDoc( new FileOutputStream JavaDoc( outputFile ) );
437         writeXml( printStream, _mergeFile );
438         printStream.close();
439     }
440
441     public String JavaDoc getOutputFileURI()
442     {
443         return _strutsApp.getOutputFileURI( STRUTS_VALIDATION_PREFIX );
444     }
445 }
446
Popular Tags