KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > controls > system > jdbc > parser > ParameterChecker


1 /*
2  * Copyright 2005 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.controls.system.jdbc.parser;
19
20 import com.sun.mirror.declaration.ClassDeclaration;
21 import com.sun.mirror.declaration.FieldDeclaration;
22 import com.sun.mirror.declaration.MethodDeclaration;
23 import com.sun.mirror.declaration.ParameterDeclaration;
24 import com.sun.mirror.declaration.TypeDeclaration;
25 import com.sun.mirror.type.DeclaredType;
26 import com.sun.mirror.type.TypeMirror;
27 import com.sun.mirror.util.DeclarationFilter;
28 import org.apache.beehive.controls.api.ControlException;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.HashMap JavaDoc;
33
34 /**
35  * Does compile-time checking of reflection parameteres in the SQL annotations's statement
36  * element vs. method parameters. Invoked by the JdbcControlChecker.
37  */

38 public class ParameterChecker {
39
40     /**
41      * Verify that all reflection parameters in the statement element can be mapped to method parameters.
42      *
43      * @param statement The parsed statement element.
44      * @param methodDecl The method declaration which was annotated.
45      */

46     public static void checkReflectionParameters(SqlFragmentContainer statement, MethodDeclaration methodDecl) {
47
48         ArrayList JavaDoc<ParameterDeclaration> params =
49                 new ArrayList JavaDoc<ParameterDeclaration>(methodDecl.getParameters());
50         HashMap JavaDoc<String JavaDoc, ParameterDeclaration> paramMap = new HashMap JavaDoc<String JavaDoc, ParameterDeclaration>();
51
52         // don't run these checks if this is a compiled class file (method names replaced with arg0, arg1, etc)
53
if (params.size() > 0 && params.get(0).getSimpleName().equals("arg0")) {
54             return;
55         }
56
57         for (int i = 0; i < params.size(); i++) {
58             paramMap.put(params.get(i).getSimpleName(), params.get(i));
59         }
60
61         doCheck(statement, paramMap, methodDecl);
62     }
63
64     /**
65      * Walk the tree of children of the statement, process all children of type ReflectionFragment.
66      *
67      * @param statement The parsed statement element.
68      * @param paramMap The method parameters, keyed by name.
69      * @param method The method declaration which was annotated.
70      */

71     private static void doCheck(SqlFragmentContainer statement, HashMap JavaDoc<String JavaDoc, ParameterDeclaration> paramMap,
72                          final MethodDeclaration method)
73     {
74
75         SqlFragment[] fragments = statement.getChildren();
76         for (SqlFragment fragment : fragments) {
77
78             // if the fragment is a container check all of its children.
79
if (fragment instanceof SqlFragmentContainer) {
80                 doCheck((SqlFragmentContainer) fragment, paramMap, method);
81
82                 // reflection fragment - make sure it can be mapped using the method's param values.
83
} else if (fragment instanceof ReflectionFragment) {
84                 checkReflectionFragment((ReflectionFragment) fragment, paramMap, method);
85             }
86         }
87     }
88
89     /**
90      * Check the fragment. Must be able to resolve references like 'foo.bar' -> 'foo' where 'foo' is a method param
91      * of a type which contains a public getter or field named 'getBar()' or 'bar' respectively.
92      *
93      * @param fragment The reflection fragment to check.
94      * @param paramMap The method parameters, keyed by name.
95      * @param method The method declaration which was annotated.
96      */

97     private static void checkReflectionFragment(ReflectionFragment fragment,
98                                                 HashMap JavaDoc<String JavaDoc, ParameterDeclaration> paramMap, MethodDeclaration method)
99     {
100
101         final String JavaDoc[] paramNameQualifiers = ((ReflectionFragment) fragment).getParameterNameQualifiers();
102         final String JavaDoc parameterName = ((ReflectionFragment) fragment).getParameterName();
103
104         if (paramMap.containsKey(paramNameQualifiers[0]) == false) {
105             throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
106         }
107
108         ParameterDeclaration tpd = paramMap.get(paramNameQualifiers[0]);
109         TypeMirror type = tpd.getType();
110
111         MethodDeclaration getterMethod = null;
112         FieldDeclaration field = null;
113
114         for (int i = 1; i < paramNameQualifiers.length; i++) {
115
116             getterMethod = null;
117             field = null;
118
119             // loop through superclasses until we find a match or run out of superclasses
120
while (type != null) {
121
122                 if (type instanceof DeclaredType == false) {
123                     throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
124                 }
125
126                 TypeDeclaration td = ((DeclaredType) type).getDeclaration();
127                 //
128
// abort if Map!!! No further checking can be done.
129
//
130
if (td.getQualifiedName().equals("java.util.Map")) {
131                     return;
132                 }
133
134                 Collection JavaDoc<? extends MethodDeclaration> methods =
135                         DeclarationFilter.FILTER_PUBLIC.filter(td.getMethods());
136                 for (MethodDeclaration m : methods) {
137                     String JavaDoc upperFirst = paramNameQualifiers[i].substring(0,1).toUpperCase();
138                     if (paramNameQualifiers[i].length() > 1) {
139                         upperFirst = upperFirst + paramNameQualifiers[i].substring(1);
140                     }
141                     if (m.getSimpleName().equals("get" + upperFirst)
142                         || m.getSimpleName().equals("is" + upperFirst)) {
143                         getterMethod = m;
144                     }
145                 }
146
147                 if (getterMethod == null) {
148                     Collection JavaDoc<FieldDeclaration> fields =
149                             DeclarationFilter.FILTER_PUBLIC.filter(td.getFields());
150                     for (FieldDeclaration fd : fields) {
151                         if (fd.getSimpleName().equals(paramNameQualifiers[i])) {
152                             field = fd;
153                         }
154                     }
155                 }
156
157                 // try the super-class
158
if (getterMethod == null && field == null) {
159                     if (td instanceof ClassDeclaration) {
160                         type = ((ClassDeclaration) td).getSuperclass();
161                         continue;
162                     }
163                 }
164
165                 break;
166             } // while
167

168             // found a match, get its type and continue within the for loop
169
if (getterMethod != null) {
170                 type = getterMethod.getReturnType();
171             } else if (field != null) {
172                 type = field.getType();
173             } else {
174                 throw new ControlException(buildMessage(parameterName, method.getSimpleName()));
175             }
176         }
177     }
178
179     /**
180      * build the error message for this module.
181      *
182      * @param parameterName
183      * @param methodName
184      * @return
185      */

186     private static String JavaDoc buildMessage(String JavaDoc parameterName, String JavaDoc methodName) {
187         StringBuilder JavaDoc message = new StringBuilder JavaDoc();
188         message.append("Unable to map the parameter in SQL statement ");
189         message.append(parameterName);
190         message.append(" to a parameter of the method ");
191         message.append(methodName);
192         message.append(". Mapping is accomplished by matching a method parameter name to ");
193         message.append("a value delimited by '{' and '}' in the statement element.");
194         return message.toString();
195     }
196 }
197
Popular Tags