KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > rebind > rpc > RemoteServiceAsyncValidator


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.user.rebind.rpc;
17
18 import com.google.gwt.core.ext.TreeLogger;
19 import com.google.gwt.core.ext.UnableToCompleteException;
20 import com.google.gwt.core.ext.typeinfo.JClassType;
21 import com.google.gwt.core.ext.typeinfo.JMethod;
22 import com.google.gwt.core.ext.typeinfo.JPackage;
23 import com.google.gwt.core.ext.typeinfo.JParameter;
24 import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
25 import com.google.gwt.core.ext.typeinfo.NotFoundException;
26 import com.google.gwt.core.ext.typeinfo.TypeOracle;
27 import com.google.gwt.user.client.rpc.AsyncCallback;
28
29 import java.util.Map JavaDoc;
30 import java.util.TreeMap JavaDoc;
31
32 /**
33  * Validates the asynchronous version of
34  * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService} interface.
35  */

36 class RemoteServiceAsyncValidator {
37   private static String JavaDoc synthesizeAsynchronousInterfaceDefinition(
38       JClassType serviceIntf) {
39     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
40     JPackage pkg = serviceIntf.getPackage();
41     if (pkg != null) {
42       sb.append("\npackage ");
43       sb.append(pkg.getName());
44       sb.append(";\n");
45     }
46
47     sb.append("\npublic interface ");
48     sb.append(serviceIntf.getSimpleSourceName());
49     sb.append("Async {\n");
50
51     JMethod[] methods = serviceIntf.getOverridableMethods();
52     for (int index = 0; index < methods.length; ++index) {
53       JMethod method = methods[index];
54       assert (method != null);
55
56       sb.append("\tvoid ");
57       sb.append(method.getName());
58       sb.append("(");
59
60       JParameter[] params = method.getParameters();
61       for (int paramIndex = 0; paramIndex < params.length; ++paramIndex) {
62         JParameter param = params[paramIndex];
63
64         if (paramIndex > 0) {
65           sb.append(", ");
66         }
67
68         sb.append(param.toString());
69       }
70
71       if (params.length > 0) {
72         sb.append(", ");
73       }
74
75       sb.append(AsyncCallback.class.getName());
76       sb.append(" arg");
77       sb.append(Integer.toString(params.length + 1));
78       sb.append(");\n");
79     }
80
81     sb.append("}");
82
83     return sb.toString();
84   }
85
86   private final JClassType asyncCallbackClass;
87   private final TypeOracle typeOracle;
88
89   RemoteServiceAsyncValidator(TypeOracle typeOracle) throws NotFoundException {
90     this.typeOracle = typeOracle;
91     asyncCallbackClass = typeOracle.getType(AsyncCallback.class.getName());
92   }
93
94   /**
95    * Checks that for there is an asynchronous
96    * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService}
97    * interface and that it has an asynchronous version of every synchronous
98    * method.
99    *
100    * @throws UnableToCompleteException if the asynchronous
101    * {@link com.google.gwt.user.client.rpc.RemoteService RemoteService}
102    * was not found, or if it does not have an asynchronous method
103    * version of every synchronous one
104    */

105   public void validateRemoteServiceAsync(TreeLogger logger,
106       JClassType remoteService) throws UnableToCompleteException {
107     TreeLogger branch = logger.branch(TreeLogger.DEBUG,
108         "Checking the synchronous interface '"
109             + remoteService.getQualifiedSourceName()
110             + "' against its asynchronous version '"
111             + remoteService.getQualifiedSourceName() + "Async'", null);
112     boolean failed = false;
113     JClassType serviceAsync = typeOracle.findType(remoteService.getQualifiedSourceName()
114         + "Async");
115     if (serviceAsync == null) {
116       failed = true;
117       branch.branch(TreeLogger.ERROR,
118           "Could not find an asynchronous version for the service interface "
119               + remoteService.getQualifiedSourceName(), null);
120     } else {
121       JMethod[] asyncMethods = serviceAsync.getOverridableMethods();
122       JMethod[] syncMethods = remoteService.getOverridableMethods();
123
124       if (asyncMethods.length != syncMethods.length) {
125         branch.branch(TreeLogger.ERROR, "The asynchronous version of "
126             + remoteService.getQualifiedSourceName() + " has "
127             + (asyncMethods.length > syncMethods.length ? "more" : "less")
128             + " methods than the synchronous version", null);
129         failed = true;
130       } else {
131         Map JavaDoc asyncMethodMap = initializeAsyncMethodMap(asyncMethods);
132         for (int i = 0; i < syncMethods.length; ++i) {
133           JMethod syncMethod = syncMethods[i];
134           String JavaDoc asyncSig = computeAsyncMethodSignature(syncMethod);
135           JMethod asyncMethod = (JMethod) asyncMethodMap.get(asyncSig);
136           if (asyncMethod == null) {
137             branch.branch(TreeLogger.ERROR,
138                 "Missing asynchronous version of the synchronous method '"
139                     + syncMethod.getReadableDeclaration() + "'", null);
140             failed = true;
141           } else if (asyncMethod.getReturnType() != JPrimitiveType.VOID) {
142             branch.branch(TreeLogger.ERROR,
143                 "The asynchronous version of the synchronous method '"
144                     + syncMethod.getReadableDeclaration()
145                     + "' must have a 'void' return type", null);
146             failed = true;
147           }
148         }
149       }
150     }
151
152     if (failed) {
153       logValidAsyncInterfaceDeclaration(branch, remoteService);
154       throw new UnableToCompleteException();
155     }
156   }
157
158   private String JavaDoc computeAsyncMethodSignature(JMethod syncMethod) {
159     return computeInternalSignature(syncMethod) + "/"
160         + asyncCallbackClass.getQualifiedSourceName();
161   }
162
163   private String JavaDoc computeInternalSignature(JMethod method) {
164     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
165     sb.setLength(0);
166     sb.append(method.getName());
167     JParameter[] params = method.getParameters();
168     for (int j = 0; j < params.length; j++) {
169       JParameter param = params[j];
170       sb.append("/");
171       sb.append(param.getType().getQualifiedSourceName());
172     }
173     return sb.toString();
174   }
175
176   /**
177    * Builds a map of asynchronous method internal signatures to the
178    * corresponding asynchronous {@link JMethod}.
179    */

180   private Map JavaDoc initializeAsyncMethodMap(JMethod[] asyncMethods) {
181     Map JavaDoc /* <String,JClassType> */sigs = new TreeMap JavaDoc();
182     for (int i = 0; i < asyncMethods.length; ++i) {
183       JMethod asyncMethod = asyncMethods[i];
184       sigs.put(computeInternalSignature(asyncMethod), asyncMethod);
185     }
186     return sigs;
187   }
188
189   private void logValidAsyncInterfaceDeclaration(TreeLogger logger,
190       JClassType remoteService) {
191     TreeLogger branch = logger.branch(TreeLogger.INFO,
192         "A valid definition for the asynchronous version of interface '"
193             + remoteService.getQualifiedSourceName() + "' would be:\n", null);
194     branch.log(TreeLogger.ERROR,
195         synthesizeAsynchronousInterfaceDefinition(remoteService), null);
196   }
197 }
Popular Tags