KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > compiler > PageFlowChecker


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;
19
20 import org.apache.beehive.netui.compiler.genmodel.GenStrutsApp;
21 import org.apache.beehive.netui.compiler.grammar.ControllerGrammar;
22 import org.apache.beehive.netui.compiler.grammar.WebappPathOrActionType;
23 import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
24 import org.apache.beehive.netui.compiler.typesystem.declaration.ClassDeclaration;
25 import org.apache.beehive.netui.compiler.typesystem.declaration.FieldDeclaration;
26 import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
27 import org.apache.beehive.netui.compiler.typesystem.declaration.PackageDeclaration;
28 import org.apache.beehive.netui.compiler.typesystem.declaration.TypeDeclaration;
29 import org.apache.beehive.netui.compiler.typesystem.env.AnnotationProcessorEnvironment;
30 import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType;
31 import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance;
32 import org.apache.xmlbeans.XmlException;
33
34 import java.io.File JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.util.Collection JavaDoc;
37 import java.util.Iterator JavaDoc;
38
39
40 public class PageFlowChecker
41         extends FlowControllerChecker
42         implements JpfLanguageConstants
43 {
44     public PageFlowChecker( AnnotationProcessorEnvironment env, Diagnostics diagnostics, FlowControllerInfo fcInfo )
45     {
46         super( env, fcInfo, diagnostics );
47     }
48
49     protected void checkField( FieldDeclaration field, TypeDeclaration jclass )
50     {
51         //
52
// Check to make sure that if this is a Shared Flow field, its type matches up with the type declared
53
// for the shared flow of that name.
54
//
55
AnnotationInstance sfFieldAnn = CompilerUtils.getAnnotation( field, SHARED_FLOW_FIELD_TAG_NAME );
56         
57         if ( sfFieldAnn != null )
58         {
59             String JavaDoc sharedFlowName = CompilerUtils.getString( sfFieldAnn, NAME_ATTR, true );
60             assert sharedFlowName != null;
61             
62             Collection JavaDoc sharedFlowRefs =
63                     getFCSourceFileInfo().getMergedControllerAnnotation().getSharedFlowRefs();
64             
65             boolean foundOne = false;
66             
67             if ( sharedFlowRefs != null )
68             {
69                 for ( Iterator JavaDoc ii = sharedFlowRefs.iterator(); ii.hasNext(); )
70                 {
71                     AnnotationInstance sharedFlowRef = ( AnnotationInstance ) ii.next();
72                     if ( sharedFlowName.equals( CompilerUtils.getString( sharedFlowRef, NAME_ATTR, true ) ) )
73                     {
74                         foundOne = true;
75                         
76                         TypeInstance sfType = CompilerUtils.getTypeInstance( sharedFlowRef, TYPE_ATTR, true );
77                         TypeInstance ft = field.getType();
78                         
79                         if ( ! ( sfType instanceof DeclaredType )
80                              || ! CompilerUtils.isAssignableFrom( ft, ( ( DeclaredType ) sfType ).getDeclaration() ) )
81                         {
82                             getDiagnostics().addError(
83                                     field, "error.field-not-assignable",
84                                     CompilerUtils.getDeclaration( ( DeclaredType ) sfType ).getQualifiedName() );
85                         }
86                     }
87                 }
88             }
89             
90             if ( ! foundOne )
91             {
92                 getDiagnostics().addError( sfFieldAnn, "error.no-matching-shared-flow-declared",
93                                            SHARED_FLOW_REF_TAG_NAME, sharedFlowName );
94             }
95         }
96         else if ( CompilerUtils.isAssignableFrom( SHARED_FLOW_BASE_CLASS, field.getType(), getEnv() )
97                   && ! CompilerUtils.isAssignableFrom( GLOBALAPP_BASE_CLASS, field.getType(), getEnv() ) )
98         {
99             // Output a warning if the field type extends SharedFlowController but there's no @Jpf.SharedFlowField
100
// annotation (in which case the field won't get auto-initialized at runtime.
101
getDiagnostics().addWarning( field, "warning.shared-flow-field-no-annotation",
102                                          field.getSimpleName(), SHARED_FLOW_BASE_CLASS,
103                                          ANNOTATION_INTERFACE_PREFIX + SHARED_FLOW_FIELD_TAG_NAME );
104         }
105         
106         super.checkField( field, jclass );
107     }
108
109     protected void doAdditionalClassChecks( ClassDeclaration jpfClass )
110     {
111         // Make sure there are no other page flows in this package/directory.
112
checkForOverlappingClasses( jpfClass, JPF_BASE_CLASS, JPF_FILE_EXTENSION_DOT, "error.overlapping-pageflows" );
113         
114         PackageDeclaration pkg = jpfClass.getPackage();
115         File JavaDoc jpfFile = CompilerUtils.getSourceFile( jpfClass, true );
116         File JavaDoc parentDir = jpfFile.getParentFile();
117         
118         //
119
// Check the package name.
120
//
121
String JavaDoc jpfPackageName = pkg.getQualifiedName();
122         
123         if ( jpfPackageName != null && jpfPackageName.length() > 0 )
124         {
125             String JavaDoc expectedPackage = parentDir.getAbsolutePath().replace( '\\', '/' ).replace( '/', '.' );
126             
127             if ( ! expectedPackage.endsWith( jpfPackageName ) )
128             {
129                 getDiagnostics().addError( jpfClass, "error.wrong-package-for-directory", parentDir.getPath() );
130             }
131         }
132
133         //
134
// Issue a warning if the class name is the same as the parent package name.
135
// This causes ambiguity when resolving inner classes.
136
//
137
if ( jpfClass.getSimpleName().equals( pkg.getQualifiedName() ) )
138         {
139             getDiagnostics().addWarning( jpfClass, "warning.classname-same-as-package" );
140         }
141         
142         //
143
// Make sure every .jpf has a begin action if the class isn't abstract.
144
//
145
boolean isAbstract = jpfClass.hasModifier( Modifier.ABSTRACT );
146         FlowControllerInfo fcInfo = getFCSourceFileInfo();
147         
148         if ( ! WebappPathOrActionType.actionExists( BEGIN_ACTION_NAME, jpfClass, null, getEnv(), fcInfo, true )
149              && ! isAbstract )
150         {
151             getDiagnostics().addError( jpfClass, "error.no-begin-action" );
152         }
153
154         //
155
// Make sure every nested pageflow has a returnAction. Return actions are added by ForwardGrammar, but
156
// here we also need to add them for inherited Forwards and SimpleActions.
157
//
158
if ( fcInfo.isNested() )
159         {
160             MergedControllerAnnotation mca = fcInfo.getMergedControllerAnnotation();
161             addReturnActions( mca.getSimpleActions(), fcInfo, jpfClass, CONDITIONAL_FORWARDS_ATTR );
162             addReturnActions( mca.getForwards(), fcInfo, jpfClass, null );
163             
164             if ( ! isAbstract && fcInfo.countReturnActions() == 0 )
165             {
166                 getDiagnostics().addError( jpfClass, "error.no-return-action",
167                                            ANNOTATION_INTERFACE_PREFIX + FORWARD_TAG_NAME,
168                                            RETURN_ACTION_ATTR );
169             }
170         }
171     }
172     
173     private void addReturnActions( Collection JavaDoc forwardAnnotations, FlowControllerInfo fcInfo,
174                                    TypeDeclaration outerType, String JavaDoc childArrayAttr )
175     {
176         for ( Iterator JavaDoc ii = forwardAnnotations.iterator(); ii.hasNext(); )
177         {
178             AnnotationInstance ann = ( AnnotationInstance ) ii.next();
179             String JavaDoc returnAction = CompilerUtils.getString( ann, RETURN_ACTION_ATTR, true );
180             if ( returnAction != null ) fcInfo.addReturnAction( returnAction, ann, outerType );
181             
182             if ( childArrayAttr != null )
183             {
184                 Collection JavaDoc children = CompilerUtils.getAnnotationArray( ann, childArrayAttr, true );
185                 if ( children != null ) addReturnActions( children, fcInfo, outerType, null );
186             }
187         }
188     }
189     
190     protected String JavaDoc getDesiredBaseClass( ClassDeclaration jclass )
191     {
192         return JPF_BASE_CLASS;
193     }
194
195     protected GenStrutsApp createStrutsApp( ClassDeclaration jclass )
196         throws XmlException, IOException JavaDoc, FatalCompileTimeException
197     {
198         File JavaDoc sourceFile = CompilerUtils.getSourceFile( jclass, true );
199         return new GenStrutsApp( sourceFile, jclass, getEnv(), getFCSourceFileInfo(), true, getDiagnostics() );
200     }
201
202     protected AnnotationGrammar getControllerGrammar()
203     {
204         return new JpfControllerGrammar();
205     }
206     
207     private class JpfControllerGrammar
208         extends ControllerGrammar
209     {
210         public JpfControllerGrammar()
211         {
212             super( PageFlowChecker.this.getEnv(), PageFlowChecker.this.getDiagnostics(),
213                    PageFlowChecker.this.getRuntimeVersionChecker(), PageFlowChecker.this.getFCSourceFileInfo() );
214             addMemberType( NESTED_ATTR, new AnnotationMemberType( null, this ) );
215             addMemberType( LONGLIVED_ATTR, new AnnotationMemberType( null, this ) );
216         }
217     }
218 }
219
Popular Tags